kostis-init/CP-Bench huggingface dataset:
Problem description:
These problems have many practical applications in communications and electrical engineering. The objective is to construct a binary sequence of length n that minimizes the autocorrelations between bits. Each bit in the sequence takes the value +1 or -1. With non-periodic (or open) boundary conditions, the k-th autocorrelation, Ck is defined to be \[ C_k = \sum_{i=0}^{n-k-1} S_i \cdot S_{i+k} \]. With periodic (or cyclic) boundary conditions, the k-th autocorrelation, Ck is defined to be \[ C_k = \sum_{i=0}^{n-1} S_i \cdot S_{(i+k) \mod n} \]. The aim is to minimize the sum of the squares of these autocorrelations. That is, to minimize \[ E = \sum_{k=1}^{n-1} C_k^2 \].  Print the binary sequence (sequence) and the energy value (E).

Input data:
n = 10  # Length of the binary sequence

Decision variables: sequence, E

CPMpy model:
# Data
n = 10  # Length of the binary sequence
# End of data

# Import libraries
from cpmpy import *
import numpy as np
import json


# periodic auto correlation
def PAF(arr, s):
    # roll the array 's' indices
    return sum(arr * np.roll(arr, -s))


# Decision Variables
sequence = intvar(-1, 1, shape=n, name="sequence")  # binary sequence
E = sum([PAF(sequence, s) ** 2 for s in range(1, n)])  # energy value

model = Model()

# exclude 0
model += sequence != 0

# minimize sum of squares
model.minimize(E)

# Solve
model.solve()

# Print
solution = {"sequence": sequence.value().tolist(), "E": E.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
These problems are said to have many practical applications including sensor placements for x-ray crystallography and radio astronomy. A Golomb ruler may be defined as a set of \( m \) integers \( 0 = a_1 < a_2 < \cdots < a_m \) such that the \( \frac{m(m-1)}{2} \) differences \( a_j - a_i, \, 1 \leq i < j \leq m \) are distinct. Such a ruler is said to contain \( m \) marks and is of length \( a_m \). The objective is to find optimal (minimum length) or near-optimal rulers. Note that a symmetry can be removed by adding the constraint that \( a_2 - a_1 < a_m - a_{m-1} \), the first difference is less than the last.  There is no requirement that a Golomb ruler measures all distances up to its length - the only requirement is that each distance is only measured in one way. However, if a ruler does measure all distances, it is classified as a perfect Golomb ruler.  There exist several interesting generalizations of the problem which have received attention like modular Golomb rulers (differences are all distinct mod a given base), disjoint Golomb rulers, Golomb rectangles (the 2-dimensional generalization of Golomb rulers), and difference triangle sets (sets of rulers with no common difference).  Print the positions of the marks (marks) and the total length of the Golomb ruler (length).

Input data:
size = 10  # Number of marks on the Golomb ruler

Decision variables: marks, length

CPMpy model:
# Data
size = 10  # Number of marks on the Golomb ruler
# End of data

# Import libraries
from cpmpy import *
import json

# Decision variables
marks = intvar(0, size * size, shape=size, name="marks")
length = marks[-1]

# Model
model = Model()

# first mark is 0
model += (marks[0] == 0)

# marks must be increasing
model += marks[:-1] < marks[1:]

# golomb constraint
diffs = [marks[j] - marks[i] for i in range(0, size - 1) for j in range(i + 1, size)]
model += AllDifferent(diffs)

# Symmetry breaking
model += (marks[size - 1] - marks[size - 2] > marks[1] - marks[0])
model += (diffs[0] < diffs[size - 1])

# find optimal ruler
model.minimize(length)

# Solve
model.solve()

# Print
solution = {"marks": marks.value().tolist(), "length": length.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Given the twelve standard pitch-classes (c, c#, d, …), represented by numbers \(0, 1, \ldots, 11\), find a series in which each pitch-class occurs exactly once and in which the musical intervals between neighbouring notes cover the full set of intervals from the minor second (1 semitone) to the major seventh (11 semitones). That is, for each of the intervals, there is a pair of neighbouring pitch-classes in the series, between which this interval appears.  The problem of finding such a series can be easily formulated as an instance of a more general arithmetic problem on \(\mathbb{Z}_n\), the set of integer residues modulo \(n\). Given \(n \in \mathbb{N}\), find a vector \(s = (s_1, \ldots, s_n)\), such that  - \(s\) is a permutation of \(\mathbb{Z}_n = \{0, 1, \ldots, n-1\}\); and - the interval vector \(v = (|s_2 - s_1|, |s_3 - s_2|, \ldots, |s_n - s_{n-1}|)\) is a permutation of   \(\mathbb{Z}_n \setminus \{0\} = \{1, 2, \ldots, n-1\}\).  A vector \(v\) satisfying these conditions is called an all-interval series of size \(n\); the problem of finding such a series is the all-interval series problem of size \(n\). We may also be interested in finding all possible series of a given size.  The All-Interval Series is a special case of the Graceful Graphs in which the graph is a line.  Print the sequence of pitch-classes (x) and the corresponding intervals (diffs).

Input data:
n = 12  # Number of pitch-classes

Decision variables: diffs, x

CPMpy model:
# Data
n = 12  # Number of pitch-classes
# End of data

# Import libraries
from cpmpy import *
import numpy as np
import json

# Create the solver
model = Model()

# Declare variables
x = intvar(0, n - 1, shape=n, name="x")  # Pitch-classes
diffs = intvar(1, n - 1, shape=n - 1, name="diffs")  # Intervals

# Constraints
model += [AllDifferent(x),
          AllDifferent(diffs)]

# Differences between successive values
model += diffs == np.abs(x[1:] - x[:-1])

# Symmetry breaking
model += [x[0] < x[-1]]  # Mirroring array is equivalent solution
model += [diffs[0] < diffs[1]]  # Further symmetry breaking

# Solve
model.solve()

# Print
solution = {"x": x.value().tolist(), "diffs": diffs.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Supply vessels transport containers from site to site. The deck area is rectangular. Containers are cuboid, and are laid out in a single layer. All containers are positioned parallel to the sides of the deck. The contents of the containers determine their class. Certain classes of containers are constrained to be separated by minimum distances either along the deck or across the deck.  The vessel loading decision problem is to determine whether a given set of containers can be positioned on a given deck, without overlapping, and without violating any of the separation constraints. The problem can be modelled as packing of a set of rectangles into a larger rectangle, subject to constraints.  In practice, the layout may be further constrained by the physical loading sequence. Containers are manoeuvred into position from the southeast corner. Each successive container in the loading sequence must be positioned so that it touches part of another container or a deck wall both to the north and to the west.  Print the positions of the containers (left, right, top, bottom).

Input data:
deck_width = 5  # Width of the deck deck_length = 5  # Length of the deck n_containers = 3  # Number of containers width = [5, 2, 3]  # Widths of containers length = [1, 4, 4]  # Lengths of containers classes = [1, 1, 1]  # Classes of containers separation = [  # Separation constraints between classes     [0, 0],     [0, 0] ]

Decision variables: right, top, left, bottom

CPMpy model:
# Data
deck_width = 5  # Width of the deck
deck_length = 5  # Length of the deck
n_containers = 3  # Number of containers
width = [5, 2, 3]  # Widths of containers
length = [1, 4, 4]  # Lengths of containers
classes = [1, 1, 1]  # Classes of containers
separation = [  # Separation constraints between classes
    [0, 0],
    [0, 0]
]
# End of data

# Import libraries
from cpmpy import *
import json
from cpmpy.expressions.utils import all_pairs

# Create the model
model = Model()

# Declare variables
left = intvar(0, deck_width, shape=n_containers, name="left")
right = intvar(0, deck_width, shape=n_containers, name="right")
top = intvar(0, deck_length, shape=n_containers, name="top")
bottom = intvar(0, deck_length, shape=n_containers, name="bottom")

# Set shape of containers
for i in range(n_containers):
    model += ((right[i] - left[i] == width[i]) & (top[i] - bottom[i] == length[i])) | \
             ((right[i] - left[i] == length[i]) & (top[i] - bottom[i] == width[i]))

# No overlap between containers
for x, y in all_pairs(range(n_containers)):
    c1, c2 = classes[x], classes[y]
    sep = separation[c1 - 1][c2 - 1]
    model += (
            (right[x] + sep <= left[y]) |  # x at least sep left of y or
            (left[x] >= right[y] + sep) |  # x at least sep right of y or
            (top[x] + sep <= bottom[y]) |  # x at least sep under y or
            (bottom[x] >= top[y] + sep)  # x at least sep above y
    )

# Solve
model.solve()

# Print
solution = {
    "left": left.value().tolist(),
    "right": right.value().tolist(),
    "top": top.value().tolist(),
    "bottom": bottom.value().tolist()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
The perfect square placement problem (also called the squared square problem) is to pack a set of squares with given integer sizes into a bigger square in such a way that no squares overlap each other and all square borders are parallel to the border of the big square. For a perfect placement problem, all squares have different sizes. The sum of the square surfaces is equal to the surface of the packing square, so that there is no spare capacity. A simple perfect square placement problem is a perfect square placement problem in which no subset of the squares (greater than one) are placed in a rectangle.  Print the coordinates of the squares (x_coords, y_coords).

Input data:
base = 6  # Side length of the large square sides = [3, 3, 3, 2, 1, 1, 1, 1, 1]  # Side lengths of the smaller squares

Decision variables: y_coords, x_coords

CPMpy model:
# Data
base = 6  # Side length of the large square
sides = [3, 3, 3, 2, 1, 1, 1, 1, 1]  # Side lengths of the smaller squares
# End of data

# Import libraries
import json
import numpy as np
from cpmpy import *
from cpmpy.expressions.utils import all_pairs

def perfect_squares(base, sides):
    model = Model()
    sides = np.array(sides)

    squares = range(len(sides))

    # Ensure that the squares cover the base exactly
    assert np.square(sides).sum() == base ** 2, "Squares do not cover the base exactly!"

    # Variables
    x_coords = intvar(0, base, shape=len(squares), name="x_coords")
    y_coords = intvar(0, base, shape=len(squares), name="y_coords")

    # Squares must be in bounds of big square
    model += x_coords + sides <= base
    model += y_coords + sides <= base

    # No overlap between squares
    for a, b in all_pairs(squares):
        model += (
            (x_coords[a] + sides[a] <= x_coords[b]) |
            (x_coords[b] + sides[b] <= x_coords[a]) |
            (y_coords[a] + sides[a] <= y_coords[b]) |
            (y_coords[b] + sides[b] <= y_coords[a])
        )

    return model, (x_coords, y_coords)

# Example usage
model, (x_coords, y_coords) = perfect_squares(base, sides)

# Solve
model.solve()

# Print
solution = {
    "x_coords": x_coords.value().tolist(),
    "y_coords": y_coords.value().tolist()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
The coordinator of a local golf club has come to you with the following problem. In their club, there are 32 social golfers, each of whom play golf once a week, and always in groups of 4. They would like you to come up with a schedule of play for these golfers, to last as many weeks as possible, such that no golfer plays in the same group as any other golfer on more than one occasion. Possible variants of the above problem include: finding a 10-week schedule with "maximum socialisation"; that is, as few repeated pairs as possible (this has the same solutions as the original problem if it is possible to have no repeated pairs), and finding a schedule of minimum length such that each golfer plays with every other golfer at least once ("full socialisation").  The problem can easily be generalized to that of scheduling \( m \) groups of \( n \) golfers over \( p \) weeks, such that no golfer plays in the same group as any other golfer twice (i.e. maximum socialisation is achieved).  This problem is derived from a question posted to sci.op-research by bigwind777@aol.com (Bigwind777) in May 1998. It is a generalisation of the problem of constructing a round-robin tournament schedule, where the number of players in a "game" is more than two. The optimal solution for 32 golfers is not yet known.  Print the assignments of golfers to groups for each week (assign).

Input data:
n_weeks = 4  # Number of weeks n_groups = 3  # Number of groups group_size = 3  # Size of each group

Decision variables: assign

CPMpy model:
# Data
n_weeks = 4  # Number of weeks
n_groups = 3  # Number of groups
group_size = 3  # Size of each group
# End of data

# Import libraries
from cpmpy import *
from cpmpy.expressions.utils import all_pairs
import numpy as np
import json


def social_golfers(n_weeks, n_groups, group_size):

    n_golfers = n_groups * group_size
    golfers = np.arange(n_golfers)
    weeks = np.arange(n_weeks)
    groups = np.arange(n_groups)

    # Possible configurations
    assign = intvar(0, n_groups - 1, shape=(n_golfers, n_weeks), name="assign")

    model = Model()

    # C1: Each group has exactly group_size players
    for gr in groups:
        for w in weeks:
            model += sum(assign[:, w] == gr) == group_size

    # C2: Each pair of players only meets at most once
    for g1, g2 in all_pairs(golfers):
        model += sum(assign[g1] == assign[g2]) <= 1

    # SBSA: Symmetry-breaking by selective assignment
    # On the first week, the first group_size golfers play in group 1, the
    # second group_size golfers play in group 2, etc. On the second week,
    # golfer 1 plays in group 1, golfer 2 plays in group 2, etc.
    # model += [assign[:, 0] == (golfers // group_size)]

    for g in golfers:
        if g < group_size:
            model += [assign[g, 1] == g]

    # First golfer always in group 0
    model += [assign[0, :] == 0]

    return model, assign

# Example usage
model, assign = social_golfers(n_weeks, n_groups, group_size)

# Solve
model.solve()

# Print
solution = {
    "assign": assign.value().tolist()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
The problem is to timetable a party at a yacht club. Certain boats are to be designated hosts, and the crews of the remaining boats in turn visit the host boats for several successive half-hour periods. The crew of a host boat remains on board to act as hosts while the crew of a guest boat together visits several hosts. Every boat can only hold a limited number of people at a time (its capacity) and crew sizes are different. The total number of people aboard a boat, including the host crew and guest crews, must not exceed the capacity. A guest boat cannot not revisit a host and guest crews cannot meet more than once. The problem facing the rally organizer is that of minimizing the number of host boats.  Print the visit schedule (visits) and the host designations (is_host).

Input data:
n_boats = 5  # Number of boats n_periods = 4  # Number of periods capacity = [6, 8, 12, 12, 12]  # Capacities of the boats crew_size = [2, 2, 2, 2, 4]  # Crew sizes of the boats

Decision variables: is_host, visits

CPMpy model:
# Data
n_boats = 5  # Number of boats
n_periods = 4  # Number of periods
capacity = [6, 8, 12, 12, 12]  # Capacities of the boats
crew_size = [2, 2, 2, 2, 4]  # Crew sizes of the boats
# End of data

# Import libraries
import json
from cpmpy import *
from cpmpy.expressions.utils import all_pairs


def progressive_party(n_boats, n_periods, capacity, crew_size, **kwargs):
    is_host = boolvar(shape=n_boats, name="is_host")
    visits = intvar(0, n_boats - 1, shape=(n_periods, n_boats), name="visits")

    model = Model()

    # Crews of host boats stay on boat
    for boat in range(n_boats):
        model += (is_host[boat]).implies((visits[:, boat] == boat).all())

    # Number of visitors can never exceed capacity of boat
    for slot in range(n_periods):
        for boat in range(n_boats):
            model += sum((visits[slot] == boat) * crew_size) + crew_size[boat] * is_host[boat] <= capacity[boat]

    # Guests cannot visit a boat twice
    for boat in range(n_boats):
        model += (~is_host[boat]).implies(AllDifferent(visits[:, boat]))

    # Non-host boats cannot be visited
    for boat in range(n_boats):
        model += (~is_host[boat]).implies((visits != boat).all())

    # Crews cannot meet more than once
    for c1, c2 in all_pairs(range(n_boats)):
        model += sum(visits[:, c1] == visits[:, c2]) <= 1

    # Minimize number of hosts needed
    model.minimize(sum(is_host))

    return model, (visits, is_host)


# Example usage
model, (visits, is_host) = progressive_party(n_boats, n_periods, capacity, crew_size)
model.solve()

# Print
solution = {
    "visits": visits.value().tolist(),
    "is_host": is_host.value().tolist()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
The problem is to put \( n \) balls labelled \( 1, \ldots, n \) into 3 boxes so that for any triple of balls \( (x, y, z) \) with \( x + y = z \), not all are in the same box. This has a solution iff \( n < 14 \). The problem can be formulated as a 0-1 problem using the variables \( M_{ij} \) for \( i \in \{1, \ldots, n\}, j \in \{1, 2, 3\} \) with \( M_{ij} \) true if ball \( i \) is in box \( j \). The constraints are that a ball must be in exactly one box, \( M_{i1} + M_{i2} + M_{i3} = 1 \) for all \( i \in \{1, \ldots, n\} \). And for each \( x + y = z \) and \( j \in \{1, 2, 3\} \), not \( (M_{xj} \land M_{yj} \land M_{zj}) \). This converts to, \( (1 - M_{xj}) + (1 - M_{yj}) + (1 - M_{zj}) \geq 1 \) or, \( M_{xj} + M_{yj} + M_{zj} \leq 2 \).  Print the assignment of balls to boxes (balls) as a list of n integers from 1 to 3.

Input data:
n = 13  # Number of balls c = 3  # Number of boxes

Decision variables: balls

CPMpy model:
# Data
n = 13  # Number of balls
c = 3  # Number of boxes
# End of data

# Import libraries
import json
from cpmpy import *


def shur_lemma(n, c):
    # balls[i] = j iff ball i is in box j
    balls = intvar(1, c, shape=n, name="balls")

    model = Model()

    # Ensure each triple (x, y, z) with x + y = z are not in the same box
    for x in range(1, n):
        for y in range(1, n - x + 1):
            z = x + y
            if z <= n:
                model += (balls[x - 1] != balls[y - 1]) | \
                         (balls[x - 1] != balls[z - 1]) | \
                         (balls[y - 1] != balls[z - 1])

    return model, (balls,)


# Example usage
model, (balls,) = shur_lemma(n, c)
model.solve()

# Print
solution = {"balls": balls.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
An order \( n \) magic square is a \( n \) by \( n \) matrix containing the numbers 1 to \( n^2 \), with each row, column, and main diagonal equal to the same sum. As well as finding magic squares, we are interested in the number of a given size that exist. There are several interesting variations. For example, we may insist on certain values in certain squares (like in quasigroup completion) and ask if the magic square can be completed. In a heterosquare, each row, column, and diagonal sums to a different value. In an anti-magic square, the row, column, and diagonal sums form a sequence of consecutive integers.  A magic sequence of length \( n \) is a sequence of integers \( x_0, \ldots, x_{n-1} \) between 0 and \( n-1 \), such that for all \( i \) in 0 to \( n-1 \), the number \( i \) occurs exactly \( x_i \) times in the sequence. For instance, 6, 2, 1, 0, 0, 0, 1, 0, 0, 0 is a magic sequence since 0 occurs 6 times in it, 1 occurs twice, etc.  Print the magic sequence (x).

Input data:
n = 12  # Length of the magic sequence

Decision variables: x

CPMpy model:
# Data
n = 12  # Length of the magic sequence
# End of data

# Import libraries
import json
import numpy as np
from cpmpy import *

def magic_sequence(n):
    model = Model()

    x = intvar(0, n - 1, shape=n, name="x")

    # Constraints
    for i in range(n):
        model += x[i] == sum(x == i)

    # Speedup search
    model += sum(x) == n
    model += sum(x * np.arange(n)) == n

    return model, (x,)

# Example usage
model, (x,) = magic_sequence(n)
model.solve()

# Print
solution = {"x": x.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Consider two sets of the numbers from 1 to 4. The problem is to arrange the eight numbers in the two sets into a single sequence in which the two 1’s appear one number apart, the two 2’s appear two numbers apart, the two 3’s appear three numbers apart, and the two 4’s appear four numbers apart.  The problem generalizes to the L(k, n) problem, which is to arrange k sets of numbers 1 to n, so that each appearance of the number m is m numbers on from the last. For example, the L(3, 9) problem is to arrange 3 sets of the numbers 1 to 9 so that the first two 1’s and the second two 1’s appear one number apart, the first two 2’s and the second two 2’s appear two numbers apart, etc.  Print the positions (position) and the solution sequence (solution).

Input data:
k = 4  # Number of sets

Decision variables: position, solution

CPMpy model:
# Data
k = 4  # Number of sets
# End of data

# Import libraries
import json
from cpmpy import *


def langford(k):
    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 None, None

    # 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)]

    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)


# Example usage
model, (position, solution) = langford(k)
if model:
    model.solve()

    # Print
    solution_dict = {
        "position": position.value().tolist(),
        "solution": solution.value().tolist()
    }
    print(json.dumps(solution_dict))
# End of CPMPy script