4

I am aware that languages like Prolog allow you to write things like the following:

mortal(X) :- man(X).    % All men are mortal
man(socrates).          % Socrates is a man

?- mortal(socrates).    % Is Socrates mortal?
yes

What I want is something like this, but backwards. Suppose I have this:

mortal(X) :- man(X).
man(socrates).
man(plato).
man(aristotle).

I then ask it to give me a random X for which mortal(X) is true (thus it should give me one of 'socrates', 'plato', or 'aristotle' according to some random seed).

My questions are:

  • Does this sort of reverse inference have a name?
  • Are there any languages or libraries that support it?

EDIT

As somebody below pointed out, you can simply ask mortal(X) and it will return all X, from which you can simply pick a random one from the list. What if, however, that list would be very large, perhaps in the billions? Obviously in that case it wouldn't do to generate every possible result before picking one.

To see how this would be a practical problem, imagine a simple grammar that generated a random sentence of the form "adjective1 noun1 adverb transitive_verb adjective2 noun2". If the lists of adjectives, nouns, verbs, etc. are very large, you can see how the combinatorial explosion is a problem. If each list had 1000 words, you'd have 1000^6 possible sentences.

Kef Schecter
  • 212
  • 2
  • 9

3 Answers3

2

Instead of the deep-first search of Prolog, a randomized deep-first search strategy could be easyly implemented. All that is required is to randomize the program flow at choice points so that every time a disjunction is reached a random pole on the search tree (= prolog program) is selected instead of the first.

Though, note that this approach does not guarantees that all the solutions will be equally probable. To guarantee that, it is required to known in advance how many solutions will be generated by every pole to weight the randomization accordingly.

salva
  • 9,943
  • 4
  • 29
  • 57
0

I've never used Prolog or anything similar, but judging by what Wikipedia says on the subject, asking

?- mortal(X).

should list everything for which mortal is true. After that, just pick one of the results.

So to answer your questions,

  • I'd go with "a query with a variable in it"
  • From what I can tell, Prolog itself should support it quite fine.
Matti Virkkunen
  • 63,558
  • 9
  • 127
  • 159
  • Ah, right. The problem, though, is it has to be a random result, whereas Prolog systems will return results the same order each time. While it would be simple to just return all X and pick a random one from the list, what if there are, say, billions of possible results? – Kef Schecter Nov 16 '11 at 02:20
0

I dont think that you can calculate the nth solution directly but you can calculate the n first solutions (n randomly picked) and pick the last. Of course this would be problematic if n=10^(big_number)...

You could also do something like

mortal(ID,X) :- man(ID,X).

man(X):- random(1,4,ID), man(ID,X).
man(1,socrates).
man(2,plato).
man(3,aristotle).

but the problem is that if not every man was mortal, for example if only 1 out of 1000000 was mortal you would have to search a lot. It would be like searching for solutions for an equation by trying random numbers till you find one. You could develop some sort of heuristic to find a solution close to the number but that may affect (negatively) the randomness.

I suspect that there is no way to do it more efficiently: you either have to calculate the set of solutions and pick one or pick one member of the superset of all solutions till you find one solution. But don't take my word for it xd

Thanos Tintinidis
  • 5,828
  • 1
  • 20
  • 31