How to randamly pick a structure from the facts database

I’m using: SWI-Prolog version 8.0.2
I want the code to pick randomly a term from the database which is something like:


word(wordX, subject..., translation(...)).
.
word(wordY, verb..., translation(...)).

I could have 300 - 400 structures like this. I want the code to show/ask me randomly words so I can memorize those. It is going to be a vocabulary trainer. One solution could be to put the structures in a list and then select an element of the list with some predicate “random pick an element from a list”. I wander if there could be a different solution, avoiding the list?

I have not used this, so can’t say for sure it will work.

See: library(random): Random numbers

You can maybe find the number of clauses for table of facts, then generate a random number and pick a clause by its index.

If you have the words like this:

word(first).
word(second).
word(third).
word(fourth).
word(last).

random_word(W) :-
    predicate_propery(word(_), number_of_clauses(N)),
    random_between(1, N, Rnd),
    nth_clause(word(_), Rnd, Ref),
    clause(word(W), true, Ref).

Of course if you know that the number of words is not changing you might hardcode the number of clauses.

Then:

?- repeat, random_word(W).
W = fourth ;
W = first ;
W = last ;
W = third ;
W = third .
2 Likes

Nice solution. It doesn’t scale very well as nth_clause/3 is linear. The quickest solution is probably to create a predicate as below, compute the random number and use word(Rnd, Word).

word(1, first).
word(2, second).
...
word(NNN, last).

You may also consider this to have a backtracking source of random words. This is different from the above of course as it never returns the same word twice.

findall(W, word(W), Ws),
random_permutation(Ws, Rnd),
member(R, Rnd).
2 Likes

Yes, this is the more obvious solution, for a static table of facts. If you add/delete rows you need to re-index it, which is annoying.

What you show with permuting the list is called “sampling without replacement” (as alternative to sampling with replacement), at least in R lingo. Both are useful and needed.

How about clause/3? If the third argument Ref is ground, is it still linear?

clause/3 in mode clause(-,-,+) is O(1). In mode (+,-,-) it uses clause indexing on the head.

3 Likes