Neo4j は、すぐに使用できる機能を提供しませんが、データベースに正しくデータを入力するところまでは既に到達しているため、必要なトラバーサルは数行のコードだけです。
いくつかの変更を加えて、ここであなたの実験を再現しました。最初に、テキストを 1 回通過してデータベースにデータを入力します (ステップ 2 と 3) が、これは些細なことです。さらに重要なことは、確率を事前に計算する必要はないと思うので、各リレーションシップの発生数とノードの合計数のみを保存することです (ステップ 4)。
あなたが求めているコードは次のようになります。
/**
* A component that creates a random sentence by a random walk on a Markov Chain stored in Neo4j, produced by
* {@link NGramDatabasePopulator}.
*/
public class RandomSentenceCreator {
private final Random random = new Random(System.currentTimeMillis());
/**
* Create a random sentence from the underlying n-gram model. Starts at a random node an follows random outgoing
* relationships of type {@link Constants#REL} with a probability proportional to that transition occurrence in the
* text that was processed to form the model. This happens until the desired length is achieved. In case a node with
* no outgoing relationships it reached, the walk is re-started from a random node.
*
* @param database storing the n-gram model.
* @param length desired number of characters in the random sentence.
* @return random sentence.
*/
public String createRandomSentence(GraphDatabaseService database, int length) {
Node startNode = randomNode(database);
return walk(startNode, length, 0);
}
private String walk(Node startNode, int maxLength, int currentLength) {
if (currentLength >= maxLength) {
return (String) startNode.getProperty(NAME);
}
int totalRelationships = (int) startNode.getProperty(TOTAL, 0);
if (totalRelationships == 0) {
//terminal node, restart from random
return walk(randomNode(startNode.getGraphDatabase()), maxLength, currentLength);
}
int choice = random.nextInt(totalRelationships) + 1;
int total = 0;
Iterator<Relationship> relationshipIterator = startNode.getRelationships(OUTGOING, REL).iterator();
Relationship toFollow = null;
while (total < choice && relationshipIterator.hasNext()) {
toFollow = relationshipIterator.next();
total += (int) toFollow.getProperty(PROBABILITY);
}
Node nextNode;
if (toFollow == null) {
//no relationship to follow => stay on the same node and try again
nextNode = startNode;
} else {
nextNode = toFollow.getEndNode();
}
return ((String) nextNode.getProperty(NAME)).substring(0, 1) + walk(nextNode, maxLength, currentLength + 1);
}
private Node randomNode(GraphDatabaseService database) {
return random(GlobalGraphOperations.at(database).getAllNodes());
}
}