|
| 1 | +# -------------------------------------------------------------------------- |
| 2 | +# Source file provided under Apache License, Version 2.0, January 2004, |
| 3 | +# http://www.apache.org/licenses/ |
| 4 | +# (c) Copyright IBM Corp. 2015, 2016 |
| 5 | +# -------------------------------------------------------------------------- |
| 6 | + |
| 7 | +""" |
| 8 | +In mathematics, a Golomb ruler is a set of marks at integer positions along |
| 9 | +an imaginary ruler such that no two pairs of marks are the same distance apart. |
| 10 | +The number of marks on the ruler is its order, and the largest distance |
| 11 | +between two of its marks is its length. |
| 12 | +
|
| 13 | +This implementation differs from the 'basic' one because it calls the solver |
| 14 | +twice: |
| 15 | + * First time to know the minimal size of the ruler for the required order, |
| 16 | + * A second time to list all possible rulers for this optimal size |
| 17 | +
|
| 18 | +See https://en.wikipedia.org/wiki/Golomb_ruler for more information. |
| 19 | +
|
| 20 | +For order 5: 2 solutions 0 1 4 9 11 ; 0 2 7 8 11 |
| 21 | +
|
| 22 | +Please refer to documentation for appropriate setup of solving configuration. |
| 23 | +""" |
| 24 | + |
| 25 | +from docplex.cp.model import * |
| 26 | +from sys import stdout |
| 27 | + |
| 28 | +from docplex.cp.config import context |
| 29 | + |
| 30 | +# Set model parameters |
| 31 | +ORDER = 10 # Number of marks |
| 32 | +MAX_LENGTH = (ORDER - 1) ** 2 # Max rule length |
| 33 | + |
| 34 | +# Create model |
| 35 | +mdl = CpoModel() |
| 36 | + |
| 37 | +# Create array of variables corresponding to position rule marks |
| 38 | +marks = integer_var_list(ORDER, 0, MAX_LENGTH, "M") |
| 39 | + |
| 40 | +# Create marks distances that should be all different |
| 41 | +dist = [marks[i] - marks[j] for i in range(1, ORDER) for j in range(0, i)] |
| 42 | +mdl.add(all_diff(dist)) |
| 43 | + |
| 44 | +# Avoid symmetric solutions by ordering marks |
| 45 | +mdl.add(marks[0] == 0) |
| 46 | +for i in range(1, ORDER): |
| 47 | + mdl.add(marks[i] > marks[i - 1]) |
| 48 | + |
| 49 | +# Avoid mirror solution |
| 50 | +mdl.add((marks[1] - marks[0]) < (marks[ORDER - 1] - marks[ORDER - 2])) |
| 51 | + |
| 52 | +# Minimize ruler size (position of the last mark) |
| 53 | +minexpr = minimize(marks[ORDER - 1]) |
| 54 | +mdl.add(minexpr) |
| 55 | + |
| 56 | +# Call propagation |
| 57 | +solver = CpoSolver(mdl) |
| 58 | +try: |
| 59 | + msol = solver.propagate() |
| 60 | + msol.print_solution() |
| 61 | +except CpoNotSupportedException: |
| 62 | + print("The configured solver agent does not support propagation.") |
0 commit comments