Download
/*
Steiner triplets in Comet.
http://www.probp.com/examples/clpset/steiner.pl
"""
The ternary Steiner problem of order n is to find n(n-1)/6 sets of elements
in {1,2,...,n} such that each set contains three elements and any two
sets have at most one element in common.
For example, the following shows a solution for size n=7:
{1,2,3}, {1,4,5}, {1,6,7}, {2,4,6}, {2,5,7}, {3,4,7}, {3,5,6}
Problem taken from:
C. Gervet: Interval Propagation to Reason about Sets: Definition and
Implementation of a PracticalLanguage,
Constraints, An International Journal, vol.1, pp.191-246, 1997.
"""
Also see:
- http://mathworld.wolfram.com/SteinerTripleSystem.html
- http://en.wikipedia.org/wiki/Steiner_system
Note: This model uses arrays of booleans as an representation of sets.
This Comet model was created by Hakan Kjellerstrand (hakank@gmail.com)
Also, see my Comet page: http://www.hakank.org/comet
*/
% Licenced under CC-BY-4.0 : http://creativecommons.org/licenses/by/4.0/
import cotfd;
int t0 = System.getCPUTime();
int n = 7;
int nb = (n * (n-1)) / 6;
cout << "n: " << n << " nb: " << nb << endl;
Solver<CP> m();
var<CP>{bool} sets[1..nb, 1..n](m);
Integer num_solutions(0);
exploreall<m> {
// explore<m> {
forall(i in 1..nb)
m.post(sum(j in 1..n) sets[i,j] == 3);
forall(i in 1..nb, j in i+1..nb) {
m.post( sum(k in 1..n) ( sets[i,k] && sets[j,k]) <= 1);
}
// symmetry breaking
forall(i in 1..nb, j in i+1..nb)
m.post(lexleq(all(k in 1..n) sets[i,k], all(k in 1..n) sets[j,k]) );
} using {
label(m);
num_solutions := num_solutions + 1;
forall(i in 1..nb) {
forall(j in 1..n) {
if (sets[i,j])
cout << j << " ";
}
cout << endl;
}
cout << endl;
}
cout << "\nnum_solutions: " << num_solutions << endl;
int t1 = System.getCPUTime();
cout << "time: " << (t1-t0) << endl;
cout << "#choices = " << m.getNChoice() << endl;
cout << "#fail = " << m.getNFail() << endl;
cout << "#propag = " << m.getNPropag() << endl;