1+ import cpmpy as cp
2+ from cpmpy .transformations .normalize import toplevel_list
3+ from ..answering_queries .constraint_oracle import ConstraintOracle
4+ from ..problem_instance import ProblemInstance , absvar
5+ from itertools import combinations
6+ from ..utils import get_scope , replace_variables , combine_sets_distinct
7+
8+ class GolombInstance (ProblemInstance ):
9+
10+ def construct_bias (self , X = None ):
11+ """
12+ Construct the bias (candidate constraints) for the golomb instance.
13+ We need a different bias construction for the golomb instance because
14+ it needs to include all permutations of scopes for the quaternary relations.
15+ """
16+ if X is None :
17+ X = self .X
18+
19+ all_cons = []
20+
21+ for relation in self .language :
22+
23+ abs_vars = get_scope (relation )
24+
25+ combs = list (combinations (X , 2 ))
26+
27+ if len (abs_vars ) == 2 :
28+ for comb in combs :
29+ replace_dict = dict ()
30+ for i , v in enumerate (comb ):
31+ replace_dict [abs_vars [i ]] = v
32+ constraint = replace_variables (relation , replace_dict )
33+ all_cons .append (constraint )
34+ elif len (abs_vars ) == 4 :
35+ result_combinations = combine_sets_distinct (combs , combs )
36+ for ((v1 , v2 ), (v3 , v4 )) in result_combinations :
37+ replace_dict = dict ()
38+ replace_dict [abs_vars [0 ]] = v1
39+ replace_dict [abs_vars [1 ]] = v2
40+ replace_dict [abs_vars [2 ]] = v3
41+ replace_dict [abs_vars [3 ]] = v4
42+ constraint = replace_variables (relation , replace_dict )
43+ all_cons .append (constraint )
44+
45+ self .bias = list (set (all_cons ) - set (self .cl ) - set (self .excluded_cons ))
46+
47+
48+
49+ def construct_golomb8 ():
50+ """
51+ :Description: The Golomb ruler problem is to place n marks on a ruler such that the distances between any two marks are all different.
52+ A Golomb ruler with 8 marks is sought in this instance.
53+ :return: a ProblemInstance object, along with a constraint-based oracle
54+ """
55+ # Parameters
56+ parameters = {"n_marks" : 8 }
57+
58+ # Variables
59+ grid = cp .intvar (1 , 35 , shape = (1 , 8 ), name = "grid" )
60+
61+ C_T = []
62+
63+ all_mark_pairs = []
64+ for a in range (8 ):
65+ for b in range (a + 1 , 8 ):
66+ all_mark_pairs .append ((a , b ))
67+
68+ for outer_idx in range (len (all_mark_pairs )):
69+ i , j = all_mark_pairs [outer_idx ] # Get the first pair of marks (i, j)
70+
71+ for inner_idx in range (outer_idx + 1 , len (all_mark_pairs )):
72+ x , y = all_mark_pairs [inner_idx ] # Get the second pair of marks (x, y)
73+
74+ C_T += [cp .abs (grid [0 , j ] - grid [0 , i ]) != cp .abs (grid [0 , y ] - grid [0 , x ])]
75+
76+ for i in range (8 ):
77+ for j in range (i + 1 , 8 ):
78+ C_T += [grid [0 , i ] < grid [0 , j ]]
79+
80+ # Create the language:
81+ AV = absvar (4 ) # create abstract vars - as many as maximum arity
82+
83+ # create abstract relations using the abstract vars
84+ lang = [AV [0 ] == AV [1 ], AV [0 ] != AV [1 ], AV [0 ] < AV [1 ], AV [0 ] > AV [1 ], AV [0 ] >= AV [1 ], AV [0 ] <= AV [1 ], cp .abs (AV [0 ] - AV [1 ]) != cp .abs (AV [2 ] - AV [3 ])]
85+
86+ instance = GolombInstance (variables = grid , params = parameters , language = lang , name = "golomb8" )
87+
88+ oracle = ConstraintOracle (list (set (toplevel_list (C_T ))))
89+
90+ return instance , oracle
0 commit comments