Une structure de données pour des ensembles d'arbres.


10

Les essais permettent un stockage efficace des listes d'éléments. Les préfixes sont partagés, ce qui optimise l'espace.

Je cherche un moyen similaire de stocker efficacement les arbres. Je voudrais pouvoir vérifier l'appartenance et ajouter des éléments, sachant si un arbre donné est un sous-arbre de certains arbres stockés ou s'il existe un arbre stocké étant un sous-arbre de l'arbre donné est également souhaitable.

Je stockais généralement environ 500 arbres binaires non équilibrés d'une hauteur inférieure à 50.

ÉDITER

Mon application est une sorte de vérificateur de modèle utilisant une sorte de mémorisation. Imaginez que j'ai un état et les formules suivantes: et avec étant une sous-formule complexe, et imaginez que je veux d'abord savoir si tient dans . Je vérifie si tient et après un long processus j'obtiens que c'est le cas. Maintenant, je veux savoir si est valable dans l' . Je voudrais me souvenir du fait que est vrai et remarquer que pour que je puisse dériver in presque instantanément.f = ϕ g = ( ϕ ψ ) ϕ f s ϕ g s f g f g ssF=ϕg=(ϕψ)ϕFsϕgsFgFgs
Inversement, si j'ai prouvé que ne tient pas en , alors je veux dire que ne tient pas en presque instantanément.t f tgtFt

Nous pouvons construire un ordre partiel sur les formules, et avoir iff . Pour chaque état , nous stockons deux ensembles de formules; stocke les formules maximales qui tiennent et stocke les formules minimales qui ne tiennent pas. Maintenant donné un état et une formule , je peux voir si , ou si auquel cas je suis fait et je sais directement si est valable à l' .g f s L ( s ) l ( s ) s g f L ( s ) , f g f l ( s ) , g f g sgFgFsL(s)l(s)sgFL(s),FgFl(s),gFgs

Actuellement, et sont implémentés sous forme de listes et ce n'est clairement pas optimal car j'ai besoin d'itérer individuellement toutes les formules stockées. Si mes formules étaient des séquences, et si l'ordre partiel était "est un préfixe de" alors un trie pourrait s'avérer beaucoup plus rapide. Malheureusement, mes formules ont une structure arborescente basée sur ¬ , , un opérateur modal et des propositions atomiques.lLl¬,

Comme le souligne @Raphael et @Jack, je pourrais séquencer les arbres, mais je crains que cela ne résoudrait pas le problème car l'ordre partiel qui m'intéresse ne correspondrait pas à "est un préfixe de".


Juste une idée rapide: Avez-vous essayé de séquencer les arbres (effectuer une traversée dans l'ordre, répertorier les nœuds visités en conséquence et ajouter des éléments spéciaux pour les mouvements ascendants ou descendants) et les stocker dans un trie? Bien sûr, cela autoriserait "uniquement" les vérifications des sous-arbres gauches, dans un sens.
Raphael

2
Et si vous utilisiez simplement une sérialisation d'arbres avec la propriété suivante: T est un sous-arbre de T si et seulement si S ( T ) est une sous-chaîne de S ( T ) ? Construire un tel S est simple [si vous trouvez d'abord une forme canonique de vos arbres]. Après cela, votre question équivaut à la correspondance de sous-chaînes, qui est un problème largement étudié en stringologie. STTS(T)S(T)S
Jukka Suomela

1
Jetez un œil à l' indexation des termes .
starblue

1
Une autre idée rapide serait de stocker tous les arbres t1, t2, .. dans un grand arbre T, en se souvenant pour chaque bord de l'ensemble d'arbres dont il fait partie. Ensuite, pour déterminer si f est un sous-arbre de l'un des arbres stockés, vous déterminez d'abord si f est un sous-arbre dans T et si oui, puis coupez tous les ensembles d'étiquettes de bord de ce sous-arbre. La réponse est oui si l'intersection n'est pas vide. (Vous pouvez également combiner les deux étapes).
Martin B.

Réponses:


5

Vous voudrez peut-être consulter les g-try . Il s'agit essentiellement de la structure de données que vous recherchez, mais conçue pour être utilisée avec des graphiques généraux au lieu de simplement des arbres. En tant que tel, je ne suis pas sûr que les g-try aient de bonnes garanties théoriques - je pense qu'ils utilisent un algorithme de canonisation de graphe comme sous-programme - mais en pratique, ils semblent bien fonctionner.

(N'ayez pas peur que l'article lié porte sur les "motifs de réseau dans les réseaux biologiques": le g-trie est une structure de données abstraite parfaitement bonne pour les graphiques.)


4

La persistance en est une forme particulière : voir les articles Rendre les structures de données persistantes par Driscoll, Sarnak, Sleator et Tarjan et Planar Point Location Using Persistent Search Trees de Sarnak & Tarjan, qui stockent les familles d'arbres associés.


1
Merci pour les références. Je ne peux pas accéder pour l'instant à rendre les structures de données persistantes , mais je connais un peu le concept de persistance. Cependant, je ne vois pas comment utiliser la persistance pour résoudre mon problème. En fait, je veux utiliser des dictionnaires qui mappent les arbres en booléen et le même arbre pourrait être la clé de différentes valeurs dans différents dictionnaires.
Abdallah

1
Comme je n'étais pas sûr de ce qu'était votre application, j'ai déclenché votre analogie avec les essais, qui stockent les chaînes en partageant des préfixes. Cependant, votre commentaire selon lequel "le même arbre pourrait être une clé pour différentes valeurs dans différents dictionnaires" ne semble pas correspondre aux essais. Peut-être que vous voulez juste une collection de signatures pour un arbre (et tous ses sous-arbres) que vous pouvez rechercher? (par exemple, en utilisant des nombres catalans pour les arbres binaires ou des codes Prufer pour les arbres étiquetés.)
Jack

1

Cela ressemble un peu à une forêt (forêts disjointes ) ...

Il amortit le coût d'insertion grâce à une technique appelée union par rang et l'opération de recherche utilisant la compression de chemin . Je sais qu'il y a aussi une version persistante de cette structure développée par Sylvain Conchon et Jean-Christophe Filliâtre mais je ne sais pas si c'est la même que celle que Jack mentionne ...



0

Dans "Purely Functional Data Structures" (1998), Chris Okasaki propose des essais d'arbres binaires en utilisant l'agrégation de types (10.3.2).

Je ne sais pas si cela aide immédiatement; la solution qui y est donnée pourrait ne pas être directement implémentable.


0

Dans le jargon du programmeur: Si vous créez les arbres à partir de sous-expressions / arbres / DAG communs, vous auriez un joli modèle compact. Graphiques acycliques ainsi dirigés. Ensuite, un ensemble d'arbres suffirait.

public class Tree {String operation; Arbres [] sous-arbres;

public int compareTo(Tree rhs) {
    if (rhs == null) return false;
    int cmp = operation.compareTo(rhs.operation);
    if (cmp == 0) {
        cmp = Arrays.compareTo(subtrees, rhs.subtrees);
    }
    return cmp;
}

...}

Map commonSubExpressions = new HashMap ();

Tree get (String expressionSyntax) {Tree t = new Tree (); t.operation = ...; t.subtrees = ... appel récursif pour obtenir des sous-expressions; Arbre t2 = commonSubExpressions.get (t); if (t2 == null) {t2 = t; commonSubExpressions.put (t2, t2); } return t2; }}

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.