Tato stránka popisuje úvahy okolo budoucího řešení koordinací v Treexu, který by měl tou dobou nativně podporovat Universal Dependencies (UD).
Mým cílem bylo, aby to bylo intuitivní. Tedy aby člověk, který o tom moc neví, na první pokus napsal kód, který bude dělat tu správnou věc, a to zejména, pokud ten kód neřeší koordinace. (Teď totiž na koordinace člověk musí v Treexu myslet, ať už píše jakýkoli kód.) Samozřejmě takovýto cíl nejde nikdy zcela splnit, koordinace jsou prostě zapeklité ve všech stylech a svým způsobem se pletou do skoro všech ostatních jevů v jazyce.
Názvy metod, parametrů a atributů nejsou definitivní, zatím mi jde spíš o celkovou koncepci. Samozřejmě uvítám návrhy na lepší názvy.
get_children
bude vracet všechny efektivní děti (společná rozvití do toho ale nepočítám, to se vrátí jen u “primárního” rodiče, viz níže).get_parent
bude vracet efektivního rodiče (u společných rozvití opět jen toho primárního)# John, Mary and Bob love bed and breakfast my ($john, $comma, $mary, $and1, $bob, $bed, $and2, $bf) = $love->get_children();
is_member
bude is_conjunct
(malý rozdíl: v pražském stylu má spojka vnořené koordinace is_member=1
, ale teď bude mít is_conjunct=0
). Případně můžeme zavést další metody jako is_coord_conjunction
a is_coord_delimiter
, pokud budou potřeba.get_coord_children()
vrátí objekty typu Treex::Core::Coord
nebo prázdný seznam, např.# John, Mary and Bob love bed and breakfast my ($coord1, $coord2) = $love->get_coord_children(); my ($john, $mary, $bob) = $coord1->conjuncts(); my ($and) = $coord1->conjunctions(); # deprel=cc my ($comma) = $coord1->delimiters(); # deprel=punct
get_coordination
vrátí objekt typu Treex::Core::Coord
(nebo undef). Půjde takto také snadno zjistit, zda je uzel součástí nějaké koordinace jako conjunct, conjunction či delimiter (typicky čárka). U vnořených koordinací se vrátí nejvyšší koordinace, např.# Simon and Garfunkel or Dylan my $coord = $simon->get_coordination(); my ($simon, $garfunkel, $dylan) = $coord->conjuncts(transitive=>1); my ($coord_inner, $dylan) = $coord->conjuncts(transitive=>0); # otázka je, jaká bude defaultní hodonota parametru transitive my ($or) = $coord->conjunctions(); my ($and) = $coord_inner->conjunctions();
no_coord
$node->get_children({no_coord=>1}); # bude ekvivalentní grep {!$_->get_coordination} $node->get_children();
my ($simon, $and, $garfunkel, $or, $dylan) = map {$nodeA->create_child()} (1..5); my $coord_inner = $nodeA->create_coord_child(); my $coord_outer = $nodeA->create_coord_child(); $coord_inner->add_conjuncts($simon, $garfunkel); $coord_inner->add_conjunctions($and); $coord_outer->add_conjuncts($coord_inner, $dylan); $coord_outer->add_conjunctions($or); # ekvivalentní zkratka: my $coord_inner = $nodeA->create_coord_child({conjuncts=>[$simon, $garfunkel], conjunction=>$and}); my $coord_outer = $nodeA->create_coord_child({conjuncts=>[$coord_inner, $dylan], conjunction=>$or});
Uzly tvořící koordinaci musejí existovat (a tedy musejí mít nějakého závislostního rodiče, Treex nedovoluje uzly visící ve vzduchu) dřív, než se přidají do koordinace. Metody add_
* (a create_coord_child
ve zkratce) by ale měly uzly převěsit tak, aby visely pod $nodeA
(pokud původně visely někde jinde).
Společná rozvití (shared dependants) se budou zachycovat jen pomocí secondary dependencies definovaných v UD (viz dokumentace syntaxe a CoNLL-U).
# "big and cheap apples and oranges, which were sold yesterday" my $apples = $big->get_parent(); my ($oranges) = $big->get_secondary_parents(); ($oranges) = $cheap->get_secondary_parents(); $oranges = $sold->get_parent(); ($apples) = $sold->get_secondary_parents();
Secondary dependencies jde v UD využít i k dalším jevům (např. doplněk). Měli bychom možná nějak odlišit ty případy, kdy se jedná o společné rozvití. Secondary dependencies jsou v UD typované (mají svůj deprel), takže asi bude třeba ještě nějaká další metoda, která vrátí i typ, viz typovane-hrany.
Společné rozvití je většinou těžké odlišit od privátního (cf. “Jan a Marie, kteří”). Typicky jsme si jedním rodičem jisti a ten druhý (či třetí) je nejistý (jako v životě, mohli bychom jim tedy říkat mother a father, až na to, že pokud je možných otců víc (koordinovaných), tak v lingvistice se nestává, že by jen jeden byl rodičem a ostatní ne).
Často nás rozdíl mezi společným a privátním rozvitím nezajímá a pražský styl nám to komplikuje, že takto jemná distinkce se odráží v celé topologii stromu. V tomto návrhu je snadné tu distinkci ignorovat.
Zdeněk má taky případnou poznámku:
V tom, kolik ve větě najdeme společných rozvití, je určitá arbitrárnost. Nemyslím víceznačnost, ale např. reprezentaci vět typu “Kristus přišel a zvěstoval pokoj”, ve kterých můžeme vidět buď společné rozvití, anebo rekonstruovaný perspron s koreferencí.
Ano, pokud bychom chtěli doplňovat takovéto koreference, tak prostě smažeme secondary parent u “Kristus” a doplníme šipku z nově vytvořeného perspronu na “Kristus”. Tedy nemusíme vůbec měnit topologii existujících uzlů, a to je myslím velká výhoda oproti současnému PDT stylu.
Možná by se v Treexu hodil obecný prostředek na zachycení množiny uzlů (která nemusí tvořit podstrom). Pro klauze máme clause_number
a metody get_clause_nodes, get_clause_root
atd. Pro pojmenované entity máme n-strom, kde z n-uzlu vedou odkazy na množinu a-uzlů, ale Treex automaticky udržuje i odkazy v opačném směru, takže mám metodu $anode-
>n_node()
. Aby fungovalo Treex API pro koordinace, tak potřebujeme nějaký takový mechanismus. Aby fungovalo rozlišení vnořených koordinací, tak potřebujeme spíš něco jako ty n-stromy, kde půjde zachytit, která koordinace je vnořena do které.
Občas v Treexu potřebujeme seznam uzlů, kam se z aktuálního uzlu dá dostat přes “šipku” daného typu. Občas potřebujeme ale pro každý vrácený uzel znát přesný typ (a podtyp) té šipky.
Např. od metody get_aligned_nodes
většinou chceme jen ten seznam uzlů, ale občas potřebujeme znát i typ alignmentu. Současné řešení vrací dvojici ($nodes_array_ref, $types_array_ref
), ale to komplikuje to častější použití, kdy nás typy nezajímají.
U normálních závislostí tento problém nenastává, protože každý uzel má jen jednoho rodiče (takže lze kdykoli na ten uzel zavolat deprel()
či afun()
a typ závislosti zjistit). Ale sekundárních závislostí může být víc než jedna.
Možná by šlo využít perlovských anotací proměnných (viz perldoc attributes
), ale to moc lidí neumí používat. Jednodušší asi bude metoda $nodeA-
>align_type_to($nodeB)
, respektive $nodeA-
>deprel_to($nodeB)
(deprel_to
by fungovalo pro sekundární rodiče i pro toho primárního, pro ostatní uzly by to vrátilo undef).
Pokud se TrEd nepoužívá k editaci, ale jen k prohlížení, dovedu si představit i nějaké “předstírání” jiné struktury, než jaká je ta skutečná interní, a víc zobrazovacích módů. Jednalo by se jen o vizualizaci definovanou v stylesheetu. Přesto bych jako výchozí zobrazovací mód vybral takový, který nic nepředstírá, aby to uživatele nemátlo.
Primární mód by zobrazoval všechny koordinované uzly jako sourozence (v jedné rovině). U vnořených koordinací by tedy toto zobrazení vedlo k o něco širším (plošším, tedy ne tak hlubokým) stromům než v současnosti (což na širokoúhlých monitorech může být spíš vítané). Uzly s is_conjunct
by byly nějak zvýrazněné. Pokud to TrEd umí, tak bych koordinované uzly dal do společného rámečku, tedy nějak takto
------------------ love----------- / / / \ \ ---/-----/--------/-- ---\-------\--------- | John Mary and Bob | | bed and breakfast | --------------------- ---------------------Simon and Garfunkel or Dylan
Alternativní zobrazovací mód by byl podobný tomu současnému, až na to že (stejně jako v primárním módu):
love / \ #Coord #Coord / / | \ /| \ / / | \ / | \ John Mary and Bob bed and breakfast #Coord / | \ #Coord or Dylan / | \ Simon and Garfunkel