Skip to content

Commit 3c6bbd3

Browse files
committed
golomb
1 parent b0072d1 commit 3c6bbd3

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

pycona/benchmarks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
from .nurse_rostering import construct_nurse_rostering
77
from .zebra import construct_zebra_problem
88
from .nqueens import construct_nqueens_problem
9+
from .golomb8 import construct_golomb8

pycona/benchmarks/golomb8.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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

Comments
 (0)