-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathprob024_langford.py
75 lines (53 loc) · 2.25 KB
/
prob024_langford.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"""
Langford's number problem in cpmpy.
Langford's number problem (CSP lib problem 24)
http://www.csplib.org/prob/prob024/
Arrange 2 sets of positive integers 1..k to a sequence,
such that, following the first occurence of an integer i,
each subsequent occurrence of i, appears i+1 indices later
than the last.
For example, for k=4, a solution would be 41312432
Model created by Hakan Kjellerstrand, [email protected]
See also my cpmpy page: http://www.hakank.org/cpmpy/
Modified by Ignace Bleukx
"""
import sys
from cpmpy import *
import numpy as np
def langford(k=8):
model = Model()
if not (k % 4 == 0 or k % 4 == 3):
print("There is no solution for K unless K mod 4 == 0 or K mod 4 == 3")
return
# variables
position = intvar(0, 2 * k - 1, shape=2 * k, name="position")
solution = intvar(1, k, shape=2 * k, name="solution")
# constraints
model += [AllDifferent(position)]
# can be written without for-loop, see issue #117 on github
# i = np.arange(1,k+1)
# model += position[i + k -1] == (position[i - 1] + i + 1)
# model += solution[position[i-1]] == i
# model += solution[position[k+i-1]] == i
for i in range(1, k + 1):
model += [position[i + k - 1] == position[i - 1] + i + 1]
model += [i == solution[position[i - 1]]]
model += [i == solution[position[k + i - 1]]]
# symmetry breaking
model += [solution[0] < solution[2 * k - 1]]
return model, (position, solution)
def print_solution(position, solution):
print(f"position: {position.value()}")
print(f"solution: {solution.value()}")
print()
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-k", type=int, default=8, help="Number of integers")
parser.add_argument("--solution_limit", type=int, default=10, help="Number of solutions to search for, find all by default")
args = parser.parse_args()
model, (position, solution) = langford(args.k)
num_sols = model.solveAll(solution_limit=args.solution_limit,
display=lambda: print_solution(position, solution))
if num_sols == 0:
raise ValueError("Model is unsatsifiable")