potassco / clingo

🤔 A grounder and solver for logic programs.
https://potassco.org/clingo
MIT License
601 stars 79 forks source link

Randomly sampling a model #401

Closed RenatoGeh closed 1 year ago

RenatoGeh commented 1 year ago

Hi,

Is it possible to sample a model without having to enumerate all models and then choosing randomly from the set? For instance, suppose the following simple program:

{a; b; c; d; e}.

I'd like to be able to sample k random models from the above program.

I see that parameters --seed=n and --rand-freq=1.0 apparently set some randomness, as the first 5 models are distinct given n, but querying for only one model always returns an empty set.

Further, I can see that the randomness isn't uniform, as some atoms appear significantly more times than others.

More concretely, I guess my question is: is there a way to disable all heuristics and really just return a random model?

Below is what I used to test the uniformity of randomness.

import clingo
import sys

# Number of tries.
n = int(sys.argv[1])
# Number of atoms.
k = int(sys.argv[2])
# Number of samples per try.
s = int(sys.argv[3])

P = "{" + ";".join(f"a{i}" for i in range(k)) + "}."
A = [clingo.parse_term(f"a{i}") for i in range(k)]
N = [0 for _ in range(k)]

print("Program: ", P)
for i in range(n):
  C = clingo.Control([f"--seed={i}", "--rand-freq=1.0", sys.argv[3]])
  C.add("base", [], P)
  C.ground([("base", [])])
  with C.solve(yield_ = True) as H:
    for M in H:
      for i, a in enumerate(A):
        if M.contains(a): N[i] += 1

print(N)

Running the code above:

python test.py 1000 5 16
Program:  {a0;a1;a2;a3;a4}.
[4576, 6856, 6848, 6864, 6856]

Thanks

rkaminsk commented 1 year ago

To get better sampling, you could use a tool like xorro: https://github.com/potassco/xorro.

RenatoGeh commented 1 year ago

Great! I'll check it out, thanks!