e-x-a.org » Úkol B

SMILES

SMILES je jednoduchý textový formát na ruční zadávání grafů do počítače. Původně je vymyšlený pro molekuly, ale koncept jde jednoduše generalizovat na libovolné grafy. Přesný popis a nějaké příklady jsou na wikipedii.

Volně přeloženo, SMILES v chemii popisuje anotovaný graf (a.k.a. molekulu), kde všechny vrcholy (a.k.a atomy) mají jméno (a.k.a. prvek) a všechny hrany (a.k.a. chemické vazby) mají přiřazený typ (např. násobnost).

My budeme pracovat se zjednodušeným SMILES systémem, který popisuje jen obyčejný, chemií nezatížený graf, pouze s anotovanými vrcholy. Anotace vrcholu je string začínající jedním velkým písmenem a pokračující libovolným množstvím malých písmen. Budeme uvažovat jen spojité grafy.

Jednoduché rovné grafy (cesty) se zapisují následovně:

  • A je graf obsahující jediný vrchol s anotací (jménem) “A”
  • AA je graf obsahující 2 vrcholy se jmény “A” a “A”, spojené hranou. Graficky asi takhle: (A)—(A)
  • ABA je graf s jednou cestou na které jsou postupně vrcholy “A”, “B” a “A”: (A)—(B)—(A)
  • AhojAhoj obsahuje 2 spojené vrcholy anotované “Ahoj”: (Ahoj)—(Ahoj)

Když chcete udělat na grafu odbočku (tj. vyrobit strom), otevřete závorku:

  • AB(C)D je graf ve kterém je cesta z A, B a D, a na B je ještě navíc připojené C.
  • Uprostred(Kolem)(Kolem)(Kolem)(Kolem) je graf který má na vrchol se jménem “Uprostřed” připojené 4 vrcholy se jménem “Kolem”.
  • Závorky jde samozřejmě libovolně zahnizďovat do sebe. Třeba tahle super molekula se zapíše jako HOC(H)(C(H)(H)H)C(H)(H)H (v obrázku na wiki je černě uhlík©, červeně kyslík (O) a bíle vodík (H)).

Graficky: například SMILES АAA(B)(C)(DE(F)G)F popisuje tenhle graf:

          (B)   (C)    (F)
             \ /        |
   (A)--(A)--(A)--(D)--(E)--(G)
              |
             (F)

Když chcete v grafu udělat cyklus (tj. vyrobit kolečko), můžete 2 libovolné molekuly ve vytvářeném stromě spojit pomocí číselné zpětné reference — nějaký vrchol označíte libovolným číslem, a to samé číslo pak můžete použít kdekoliv znova pro vyrobení hrany vedoucí k původnímu vrcholu.

  • V grafu A1AAA1 je první A označené jedničkou, a poslední A je s ním spojené. Ve výsledku z toho je čtvercový graf s vrcholy označenými A.
  • Graf K4 se zapíše jako X1X2X1X(1)2
  • Graf K3,3 se dá zapsat jako X10Y20X11Y21(10)X12(20)Y22(10)11.

Grafický příklad — SMILES A123B(C123)(E)D123 vypadá jako graf takhle:

      (C)
     /   \
   (A)---(B)--(E)
     \   /
      (D)

Zadání

Vyrobte predikát smiles_graph(+SmilesString, -Graf), který ze stringu ve formátu SMILES vyrobí nějaký pěkný, strojově zpracovatelný popis grafu. Pěkný popis je například seznam označení vrcholů a seznam hran s indexy sousedících vrcholů.

Příklad

Na dotaz

?-  smiles_graph("Aaa555BbbCcc555", graph(V,E)).

by prolog mohl odpovědět např. takhle:

V = ['Aaa', 'Bbb', 'Ccc']
E = [edge(0,1), edge(1,2), edge(2,0)]

Ideálně do řešení zahrňte predikát demo, který bude obsahovat nějaký návod, jak vaši formu predikátu správně spustit. V tomhle případě třeba takhle:

demo :-
  smiles_graph("AaAaAa", graph(V,E)),
  write("Vrcholy: "), writeln(V),
  write("Hrany: "), writeln(E).

Na neplatný SMILES vzorec by Prolog měl odpovědět false.

Pomůcky

Můžou se hodit následující věci ze standardní knihovny Prologu:

?- string_chars("aSd('1",X).
X = [a, 'S', d, '(', '\'', '1'].
?- atom_number('1',N).
Y = 1.
?- string_to_list("aSd('1",ASCII).
ASCII = [97, 83, 100, 40, 39, 49].
?- atom_concat(ka,kao,X).
X = kakao.
?- char_type('a', lower).
true.
?- char_type('a', upper).
false.
?- char_type('a', digit).
false.

Parsování SMILES určitě proveďte pomocí prologových gramatik, je to tak nejpohodlnější. Do seznamu cvičení (na hlavní stránce dole) jsem přidal nějakou formálnější definici, příklady přepisování gramatických pravidel na normální, a taky demo s parsováním aritmetiky. (SMILES bude mít podstatně jednodušší parser, ale s vyparsovaným obsahem bude potřeba dělat trochu složitější věci.)

DCG jsou kdyžtak na internetu dokumentované různě systematicky.