2011-09-20 4 views
1

Par exemple, j'ai:Obtenir un prédicat aléatoire à partir de la base de connaissances. Prolog

upred(mary, have, knife). 
upred(john, have, sword). 
upred(sam, have, bowl). 
upred(sword, is, long). 

Comment puis-je obtenir prédicat au hasard?

% call this and get random predicate as Pred 
get_random_pred(Pred) :- 
+1

Aléatoire comme dans ...?! Pouvez-vous donner un exemple de résultat pour Pred? A partir de quel ensemble de valeurs les arguments du prédicat doivent-ils être pris? – ThomasH

Répondre

5

Drôle, c'est quelque chose dont je me suis inquiété récemment. J'ai une solution partielle qui dépend du magasin dynamique et identifie les faits que vous voulez pouvoir obtenir au hasard. Je ne l'aime pas parce que cela dépend du magasin dynamique et aussi parce que cela dépend de la fabrication de métadonnées, qui peuvent être non synchronisées. Cependant, cela peut être suffisant pour vos objectifs. Il ne capture pas non plus parfaitement votre API, parce que vous devez donner une idée de ce qui vous «intéresse». En pratique, cela fonctionnerait probablement bien, parce que vous ne vous trouverez probablement pas dans un situation où fait ferait, car il échouera probablement à la prochaine correspondance de modèle.

Mon astuce consiste à utiliser =.. pour désassembler les prédicats et à utiliser asserta pour attribuer à chaque fait une valeur d'index. Si vous voulez que cela fonctionne mieux, vous devrez utiliser une directive d'indexation pour dire à Prolog que vous voulez qu'il indexe tout le chemin jusqu'au troisième champ de mon random_fact, mais je ne l'ai pas pris aussi loin. Pour les petites bases de données (pas WordNet), cela sera probablement OK, mais pour les plus grandes, vous aurez probablement besoin de la performance.

% random_fact(Head, Instantiation, Index) 
:- dynamic(random_fact/3). 

% fact_count(Head, Count) 
:- dynamic(fact_count/2). 

% one big side-effect to make it possible to query for a random predicate 
prepare_randomization_metadata(Goal) :- 
    findall(Goal, Goal, Occurrances), 
    prepare_randomization_metadata(Occurrances, 0), 
    Goal =.. [Head|_], 
    length(Occurrances, N), 
    asserta(fact_count(Head, N)). 

prepare_randomization_metadata([], _). 
prepare_randomization_metadata([Goal|Goals], N) :- 
    Goal =.. [Head|_], 
    asserta(random_fact(Head, Goal, N)), 
    N1 is N+1, 
    prepare_randomization_metadata(Goals, N1), !. 

Comme vous pouvez le voir, le moteur est à prendre ici essentiellement un objectif donné et construire une petite base de données de métadonnées. Il pourrait probablement être amélioré par quelqu'un qui connaît mieux Prolog que moi. Pour l'utiliser, vous conduire comme ceci:

?- prepare_randomization_metadata(upred(X, Y, Z)). 
true. 

Maintenant, vous avez une base de données avec des faits comme celui-ci en elle:

random_fact(upred, upred(mary, have, knife), 0). 
random_fact(upred, upred(john, have, sword), 1). 
... 

C'est quelque chose que vous pouvez raisonner sur Prolog. Donc, si vous voulez que le second prédicat, vous pouvez l'interroger comme ceci:

?- random_fact(upred, X, 1) 
X = upred(mary, have, knife) ; 
false. 

Maintenant get_random_pred est assez facile, mais nous avons besoin d'un argument supplémentaire pour identifier le « genre » de fait, nous voulons:

get_random_pred(Head, Pred) :- 
    fact_count(Head, N), 
    % pick a random number between 0 and the # of facts we have for this pred 
    random(0, N, I), 
    random_fact(Head, Pred, I), !. 

Je ne suis pas encore assez bien avec Prolog pour vous dire pourquoi cela m'a parfois paru avoir plusieurs solutions, mais c'est ce que j'ai fait, alors j'ai inséré la coupure rouge à la fin. Mais, si vous souhaitez plusieurs solutions, il est assez facile d'écrire une version qui le fait aussi.

endless_random_facts(Head, Fact) :- repeat, get_random_pred(Head, Fact). 

Par exemple:

?- get_random_pred(upred, X). 
X = upred(sword, is, long) ; 
X = upred(john, have, sword) ; 
X = upred(mary, have, knife) ; 
X = upred(john, have, sword) ; 
X = upred(john, have, sword) ; 

Quoi qu'il en soit, j'espère que cela aide, malgré les lacunes. J'ai seulement testé dans SWI-Prolog.

Questions connexes