kostis-init/CP-Bench huggingface dataset:
Problem description:
The problem is to schedule a tournament of \( n \) teams over \( n-1 \) weeks, with each week divided into \( n/2 \) periods, and each period divided into two slots. The first team in each slot plays at home, whilst the second plays the first team away. A tournament must satisfy the following three constraints: every team plays once a week; every team plays at most twice in the same period over the tournament; every team plays every other team.  An example schedule for 8 teams is:  | Week 1  | Week 2  | Week 3  | Week 4  | Week 5  | Week 6  | Week 7  | |---------|---------|---------|---------|---------|---------|---------| | 0 v 1   | 0 v 2   | 4 v 7   | 3 v 6   | 3 v 7   | 1 v 5   | 2 v 4   | | 2 v 3   | 1 v 7   | 0 v 3   | 5 v 7   | 1 v 4   | 0 v 6   | 5 v 6   | | 4 v 5   | 3 v 5   | 1 v 6   | 0 v 4   | 2 v 6   | 2 v 7   | 0 v 7   | | 6 v 7   | 4 v 6   | 2 v 5   | 1 v 2   | 0 v 5   | 3 v 4   | 1 v 3   |  One extension of the problem is to double round robin tournaments in which each team plays every other team (as before) but now both at home and away. This is often solved by repeating the round robin pattern, but swapping home games for away games in the repeat.  Print the home and away schedules (home, away).

Input data:
n_teams = 8  # Number of teams

Decision variables: home, away

CPMpy model:
# Data
n_teams = 8  # Number of teams
# End of data

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


def sport_scheduling(n_teams):
    n_weeks, n_periods, n_matches = n_teams - 1, n_teams // 2, (n_teams - 1) * n_teams // 2

    home = intvar(1, n_teams, shape=(n_weeks, n_periods), name="home")
    away = intvar(1, n_teams, shape=(n_weeks, n_periods), name="away")

    model = Model()

    # teams cannot play each other
    model += home != away

    # every teams plays once a week
    # can be written cleaner, see issue #117
    # model += AllDifferent(np.append(home, away, axis=1), axis=0)
    for w in range(n_weeks):
        model += AllDifferent(np.append(home[w], away[w]))

    # every team plays each other
    for t1, t2 in all_pairs(range(1, n_teams + 1)):
        model += (sum((home == t1) & (away == t2)) + sum((home == t2) & (away == t1))) >= 1

    # every team plays at most twice in the same period
    for t in range(1, n_teams + 1):
        # can be written cleaner, see issue #117
        # sum((home == t) | (away == t), axis=1) <= 2
        for p in range(n_periods):
            model += sum((home[p] == t) | (away[p] == t)) <= 2

    return model, (home, away)


# Example usage
model, (home, away) = sport_scheduling(n_teams)
model.solve()

# Print
solution = {
    "home": home.value().tolist(),
    "away": away.value().tolist()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Balanced Incomplete Block Design (BIBD) generation is a standard combinatorial problem from design theory, originally used in the design of statistical experiments but since finding other applications such as cryptography. It is a special case of Block Design, which also includes Latin Square problems.  BIBD generation is described in most standard textbooks on combinatorics. A BIBD is defined as an arrangement of \( v \) distinct objects into \( b \) blocks such that each block contains exactly \( k \) distinct objects, each object occurs in exactly \( r \) different blocks, and every two distinct objects occur together in exactly \( \lambda \) blocks. Another way of defining a BIBD is in terms of its incidence matrix, which is a \( v \) by \( b \) binary matrix with exactly \( r \) ones per row, \( k \) ones per column, and with a scalar product of \( \lambda \) between any pair of distinct rows. A BIBD is therefore specified by its parameters \( (v, b, r, k, \lambda) \). An example of a solution for \( (7, 7, 3, 3, 1) \) is:  0 1 1 0 0 1 0 1 0 1 0 1 0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 1 0 0  Lam’s problem is that of finding a BIBD with parameters \( (111, 111, 11, 11, 1) \).  Print the incidence matrix of the BIBD (matrix).

Input data:
v = 9  # Number of distinct objects b = 12  # Number of blocks r = 4  # Number of blocks each object occurs in k = 3  # Number of objects each block contains l = 1  # Number of blocks in which each pair of distinct objects occurs together

Decision variables: matrix

CPMpy model:
# Data
v = 9  # Number of distinct objects
b = 12  # Number of blocks
r = 4  # Number of blocks each object occurs in
k = 3  # Number of objects each block contains
l = 1  # Number of blocks in which each pair of distinct objects occurs together
# End of data

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

def bibd(v, b, r, k, l):
    matrix = boolvar(shape=(v, b), name="matrix")

    model = Model()

    # Every row adds up to r
    model += [sum(row) == r for row in matrix]
    # Every column adds up to k
    model += [sum(col) == k for col in matrix.T]

    # The scalar product of every pair of columns adds up to l
    model += [np.dot(row_i, row_j) == l for row_i, row_j in all_pairs(matrix)]

    # Break symmetry
    # Lexicographic ordering of rows
    for r in range(v - 1):
        bvar = boolvar(shape=(b + 1))
        model += bvar[0] == 1
        model += bvar == ((matrix[r] <= matrix[r + 1]) &
                          ((matrix[r] < matrix[r + 1]) | (bvar[1:] == 1)))
        model += bvar[-1] == 0
    # Lexicographic ordering of columns
    for c in range(b - 1):
        bvar = boolvar(shape=(v + 1))
        model += bvar[0] == 1
        model += bvar == ((matrix.T[c] <= matrix.T[c + 1]) &
                          ((matrix.T[c] < matrix.T[c + 1]) | (bvar[1:] == 1)))
        model += bvar[-1] == 0

    return model, (matrix,)

# Example usage
model, (matrix,) = bibd(v, b, r, k, l)
model.solve()

# Print
solution = {"matrix": matrix.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
This problem has its roots in Bioinformatics and Coding Theory.  Problem: find as large a set \( S \) of strings (words) of length 8 over the alphabet \( W = \{ A,C,G,T \} \) with the following properties:  - Each word in \( S \) has 4 symbols from \{ C,G \}; - Each pair of distinct words in \( S \) differ in at least 4 positions; and - Each pair of words \( x \) and \( y \) in \( S \) (where \( x \) and \( y \) may be identical) are such that \( x^R \) and \( y^C \) differ in at least 4 positions. Here, \( ( x_1,\ldots,x_8 )^R = ( x_8,\ldots,x_1 ) \) is the reverse of \( ( x_1,\ldots,x_8 ) \) and \( ( y_1,\ldots,y_8 )^C \) is the Watson-Crick complement of \( ( y_1,\ldots,y_8 ) \), i.e. the word where each \( A \) is replaced by a \( T \) and vice versa and each \( C \) is replaced by a \( G \) and vice versa.  Print the set of words (words).

Input data:
n = 8  # Number of words to find

Decision variables: words

CPMpy model:
# Data
n = 8  # Number of words to find
# End of data

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

def word_design(n=2):
    A, C, G, T = 1, 2, 3, 4

    # words[i,j] is the j'th letter of the i'th word
    words = intvar(A, T, shape=(n, 8), name="words")

    model = Model()

    # 4 symbols from {C,G}
    for w in words:
        model += sum((w == C) | (w == G)) >= 4

    # Each pair of distinct words differ in at least 4 positions
    for x, y in all_pairs(words):
        model += (sum(x != y) >= 4)

    # Each pair of words x and y (where x and y may be identical)
    # are such that x^R and y^C differ in at least 4 positions
    for y in words:
        y_c = 5 - y  # Watson-Crick complement
        for x in words:
            x_r = x[::-1]  # reversed x
            model += sum(x_r != y_c) >= 4

    # Break symmetry
    for r in range(n - 1):
        b = boolvar(shape=(9,))
        model += b[0] == 1
        model += b == ((words[r] <= words[r + 1]) &
                       ((words[r] < words[r + 1]) | (b[1:] == 1)))
        model += b[-1] == 0

    return model, (words,)

# Example usage
model, (words,) = word_design(n)
model.solve()

# Print
solution = {"words": words.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
The ternary Steiner problem of order \( n \) consists of finding a set of \( n \cdot (n-1)/6 \) triples of distinct integer elements in \(\{1, \ldots, n\}\) such that any two triples have at most one common element. It is a hypergraph problem coming from combinatorial mathematics [luneburg1989tools] where \( n \) modulo 6 has to be equal to 1 or 3 [lindner2011topics]. One possible solution for \( n = 7 \) is \(\{\{1, 2, 3\}, \{1, 4, 5\}, \{1, 6, 7\}, \{2, 4, 6\}, \{2, 5, 7\}, \{3, 4, 7\}, \{3, 5, 6\}\}\). The solution contains \( 7 \cdot (7-1)/6 = 7 \) triples.  This is a particular case of the more general Steiner system.  More generally still, you may refer to Balanced Incomplete Block Designs. In fact, a Steiner Triple System with \( n \) elements is a BIBD(\( n, n \cdot (n-1)/6, (n-1)/2, 3, 1 \)).  Print the set of triples (sets).

Input data:
n = 9  # Order of the Steiner Triple System

Decision variables: sets

CPMpy model:
# Data
n = 9  # Order of the Steiner Triple System
# End of data

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

def steiner(n=15):
    assert n % 6 == 1 or n % 6 == 3, "N must be (1|3) modulo 6"

    n_sets = int(n * (n - 1) // 6)

    model = Model()

    # boolean representation of sets
    # sets[i,j] = true iff item j is part of set i
    sets = boolvar(shape=(n_sets, n), name="sets")

    # cardinality of set if 3
    # can be written cleaner, see issue #117
    # model += sum(sets, axis=0) == 3
    model += [sum(s) == 3 for s in sets]

    # cardinality of intersection <= 1
    for s1, s2 in all_pairs(sets):
        model += sum(s1 & s2) <= 1

    # symmetry breaking
    model += (sets[(0, 0)] == 1)

    return model, (sets,)

# Example usage
model, (sets,) = steiner(n)
model.solve()

# Print
solution = {"sets": sets.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
This problem consists in finding a partition of numbers 1..N into two sets A and B such that:  - A and B have the same cardinality - Sum of numbers in A = sum of numbers in B - Sum of squares of numbers in A = sum of squares of numbers in B  There is no solution for \( N < 8 \).  Here is an example for \( N = 8 \): A = (1, 4, 6, 7) and B = (2, 3, 5, 8)  From \( N \geq 8 \), there is no solution if \( N \) is not a multiple of 4.  Print the sets A and B (A, B).

Input data:
n = 12  # The number N

Decision variables: A, B

CPMpy model:
# Data
n = 12  # The number N
# End of data

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

def number_partitioning(n=8):
    assert n % 2 == 0, "The value of n must be even"

    # x[i] is the ith value of the first set
    x = intvar(1, n, shape=n // 2)

    # y[i] is the ith value of the second set
    y = intvar(1, n, shape=n // 2)

    model = Model()

    model += AllDifferent(np.append(x, y))

    # sum of numbers is equal in both sets
    model += sum(x) == sum(y)

    # sum of squares is equal in both sets
    model += sum(x ** 2) == sum(y ** 2)

    # break symmetry
    model += x[:-1] <= x[1:]
    model += y[:-1] <= x[1:]

    return model, (x,y)

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

A = x
B = y

# Print
solution = {"A": x.value().tolist(), "B": y.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
A labelling \( f \) of the nodes of a graph with \( q \) edges is graceful if \( f \) assigns each node a unique label from \( \{0, 1, \ldots, q\} \) and when each edge \( xy \) is labelled with \( |f(x) - f(y)| \), the edge labels are all different. Gallian surveys graceful graphs, i.e., graphs with a graceful labelling, and lists the graphs whose status is known.  All-Interval Series is a special case of a graceful graph where the graph is a line.  Print the node labels and edge labels (nodes, edges).

Input data:
m = 16  # Number of edges in the graph n = 8  # Number of nodes in the graph graph = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3],          [4, 5], [4, 6], [4, 7], [5, 6], [5, 7], [6, 7],          [0, 4], [1, 5], [2, 6], [3, 7]]  # Edges of the graph

Decision variables: edges, nodes

CPMpy model:
# Data
m = 16  # Number of edges in the graph
n = 8  # Number of nodes in the graph
graph = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3],
         [4, 5], [4, 6], [4, 7], [5, 6], [5, 7], [6, 7],
         [0, 4], [1, 5], [2, 6], [3, 7]]  # Edges of the graph
# End of data

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


def graceful_graphs(m, n, graph):
    graph = np.array(graph)

    model = Model()

    # variables
    nodes = intvar(0, m, shape=n, name="nodes")
    edges = intvar(1, m, shape=m, name="edges")

    # constraints
    model += np.abs(nodes[graph[:, 0]] - nodes[graph[:, 1]]) == edges

    model += (AllDifferent(edges))
    model += (AllDifferent(nodes))

    return model, (nodes, edges)


# Example usage
model, (nodes, edges) = graceful_graphs(m, n, graph)
model.solve()

# Print
solution = {"nodes": nodes.value().tolist(), "edges": edges.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Can \( n \) queens (of the same color) be placed on a \( n \times n \) chessboard so that none of the queens can attack each other? In chess, a queen attacks other squares on the same row, column, or either diagonal as itself. So the \( n \)-queens problem is to find a set of \( n \) locations on a chessboard, no two of which are on the same row, column or diagonal.  A simple arithmetical observation may be helpful in understanding models. Suppose a queen is represented by an ordered pair \((\alpha, \beta)\), the value \(\alpha\) represents the queen’s column, and \(\beta\) its row on the chessboard. Then two queens do not attack each other iff they have different values of all of \(\alpha\), \(\beta\), \(\alpha - \beta\), and \(\alpha + \beta\). It may not be intuitively obvious that chessboard diagonals correspond to sums and differences, but consider moving one square along the two orthogonal diagonals: in one direction the sum of the coordinates does not change, while in the other direction the difference does not change. (We do not suggest that pairs \((\alpha, \beta)\) is a good representation for solving.)  The problem has inherent symmetry. That is, for any solution we obtain another solution by any of the 8 symmetries of the chessboard (including the identity) obtained by combinations of rotations by 90 degrees and reflections.  Print the positions of the queens on the chessboard (queens).

Input data:
n = 10  # Size of the chessboard and number of queens

Decision variables: queens

CPMpy model:
# Data
n = 10  # Size of the chessboard and number of queens
# End of data

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

def n_queens(n=8):

    queens = intvar(1, n, shape=n, name="queens")

    # Constraints on columns and left/right diagonal
    model = Model([
        AllDifferent(queens),
        AllDifferent(queens - np.arange(n)),
        AllDifferent(queens + np.arange(n)),
    ])

    return model, (queens,)

# Example usage
model, (queens,) = n_queens(n)
model.solve()

# Print
solution = {"queens": queens.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
A Costas array is a pattern of \( n \) marks on an \( n \times n \) grid, one mark per row and one per column, in which the \( n \cdot (n-1)/2 \) vectors between the marks are all different.  Such patterns are important as they provide a template for generating radar and sonar signals with ideal ambiguity functions.  A model for Costas Array Problem (CAP) is to define an array of variables \( X_1, \ldots, X_n \) which form a permutation. For each length \( l \in \{1, \ldots, n-1\} \), we add \( n-l \) more variables \( X_{l1}, \ldots, X_{ln-1} \), whereby each of these variables is assigned the difference of \( X_i - X_{i+l} \) for \( i \in \{1, \ldots, n-l\} \). These additional variables form a difference triangle.  Each line of this difference triangle must not contain any value twice. That is, the CAP is simply a collection of all-different constraints on \( X_1, \ldots, X_n \) and \( X_{l1}, \ldots, X_{ln-l} \) for all \( l \in \{1, \ldots, n-1\} \).  Print the Costas array (costas).

Input data:
n = 8  # Size of the Costas array

Decision variables: costas

CPMpy model:
# Data
n = 8  # Size of the Costas array
# End of data

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

def costas_array(n=6):
    model = Model()

    # Declare variables
    costas = intvar(1, n, shape=n, name="costas")
    differences = intvar(-n + 1, n - 1, shape=(n, n), name="differences")

    tril_idx = np.tril_indices(n, -1)
    triu_idx = np.triu_indices(n, 1)

    # Constraints
    # Fix the values in the lower triangle in the difference matrix to -n+1.
    model += differences[tril_idx] == -n + 1

    model += [AllDifferent(costas)]

    # Define the differences
    for i, j in zip(*triu_idx):
        model += [differences[i, j] == costas[j] - costas[j - i - 1]]

    # All entries in a particular row of the difference triangle must be distinct
    for i in range(n - 2):
        model += [AllDifferent([differences[i, j] for j in range(n) if j > i])]

    # Additional constraints to speed up the search
    model += differences[triu_idx] != 0
    for k, l in zip(*triu_idx):
        if k < 2 or l < 2:
            continue
        model += [differences[k - 2, l - 1] + differences[k, l] ==
                  differences[k - 1, l - 1] + differences[k - 1, l]]

    return model, (costas, differences)

# Example usage
model, (costas, differences) = costas_array(n)
model.solve()

# Print
solution = {
    "costas": costas.value().tolist()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
For every odd positive integer \( \ell \) (and \( m = \frac{\ell - 1}{2} \)) we define the 2cc Hadamard matrix Legendre pairs CSP using the \{V, D, C\} format (Variables, Domains, Constraints) as follows:  - \( V = \{a_1, \ldots, a_\ell, b_1, \ldots, b_\ell\} \), a set of \( 2 \cdot \ell \) variables - \( D = \{D_{a_1}, \ldots, D_{a_\ell}, D_{b_1}, \ldots, D_{b_\ell}\} \), a set of \( 2 \cdot \ell \) domains, all of them equal to \{-1, +1\} - \( C = \{c_1, \ldots, c_m, c_{m+1}, c_{m+2}\} \), a set of \( m+2 \) constraints (\( m \) quadratic constraints and 2 linear constraints)  The \( m \) quadratic constraints are given by: \[ c_s := \text{PAF}(A, s) + \text{PAF}(B, s) = -2, \forall s = 1, \ldots, m \] where PAF denotes the periodic autocorrelation function: (\(i + s\) is taken mod \( \ell \) when it exceeds \( \ell \)) \[ A = [a_1, \ldots, a_\ell], \, \text{PAF}(A, s) = \sum_{i=1}^\ell a_i a_{i+s} \] \[ B = [b_1, \ldots, b_\ell], \, \text{PAF}(B, s) = \sum_{i=1}^\ell b_i b_{i+s} \]  The 2 linear constraints are given by: \[ c_{m+1} := a_1 + \ldots + a_\ell = 1 \] \[ c_{m+2} := b_1 + \ldots + b_\ell = 1 \]  The 2cc Hadamard matrix Legendre pairs CSP for all odd \( \ell = 3, \ldots, 99 \) are given in http://www.cargo.wlu.ca/CSP_2cc_Hadamard/ (and in the data section). There are 49 CSPs. All of them are known to have solutions.  It is conjectured that the 2cc Hadamard matrix Legendre pairs CSP has solutions, for every odd \( \ell \), and this is linked to the famous Hadamard conjecture [Kotsireas].  Print the variables a and b (a, b).

Input data:
l = 9  # Value of l (must be an odd positive integer)

Decision variables: b, a

CPMpy model:
# Data
l = 9  # Value of l (must be an odd positive integer)
# End of data

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

def PAF(arr, s):
    return sum(arr * np.roll(arr,-s))

def hadamard_matrix(l=5):

    m = int((l - 1) / 2)

    a = intvar(-1,1, shape=l, name="a")
    b = intvar(-1,1, shape=l, name="b")

    model = Model()

    model += a != 0 # exclude 0 from dom
    model += b != 0 # exclude 0 from dom

    model += sum(a) == 1
    model += sum(b) == 1

    for s in range(1,m+1):
        model += (PAF(a,s) + PAF(b,s)) == -2

    return model, (a,b)


# Example usage
model, (a, b) = hadamard_matrix(l)
model.solve()

# Print
solution = {"a": a.value().tolist(), "b": b.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
If 100 bushels of corn were distributed among 100 people such that each man received three bushels, each woman two, and each child half a bushel, and there are five times as many women as men, find the number of men, women, and children.  Print the number of men, women, and children (men, women, children).

Input data:

Decision variables: men, women, children

CPMpy model:
# Import libraries
from cpmpy import *
import json

# Decision variables
men = intvar(0, 100, name="men")
women = intvar(0, 100, name="women")
children = intvar(0, 100, name="children")

# Model
model = Model([
    men + women + children == 100,  # Total number of people
    men * 6 + women * 4 + children == 200,  # Total bushels of corn
    men * 5 == women  # Five times as many women as men
])

# Solve the model
model.solve()

# Print the solution
solution = {
    "men": men.value(),
    "women": women.value(),
    "children": children.value()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Enter the digits 1 through 8 in the circles and squares such that the number in each square is equal to the sum of the numbers in the adjoining circles. ...   C F C   F   F   C F C '''  Print the values for each position (positions).

Input data:

Decision variables: positions

CPMpy model:
# Import libraries
from cpmpy import *
import json

# Parameters
n = 8  # Number of digits

# Decision variables
positions = intvar(1, n, shape=n, name="positions")
a, b, c, d, e, f, g, h = positions

# Model
model = Model([
    AllDifferent(positions),
    b == a + c,
    d == a + f,
    e == c + h,
    g == f + h
])

# Solve the model
model.solve()

# Print the solution
solution = {"positions": positions.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
An old man asked a mathematician to guess the ages of his three sons.  Old man said: "The product of their ages is 36." Mathematician said: "I need more information."  Old man said:"Over there you can see a building. The sum of their ages equals the number of the windows in that building." After a short while the mathematician said: "I need more information."  Old man said: "The oldest son has blue eyes." Mathematician said: "I got it."  What are the ages of the three sons of the old man?  Print the ages of the sons (A1, A2, A3) starting from the oldest.

Input data:

Decision variables: A3, A1, A2

CPMpy model:
# Import libraries
from cpmpy import *
import json


A1 = intvar(0, 36, name="A1")  # oldest son
A2 = intvar(0, 36, name="A2")
A3 = intvar(0, 36, name="A3")

B1 = intvar(0, 36, name="B1")
B2 = intvar(0, 36, name="B2")
B3 = intvar(0, 36, name="B3")
AS = intvar(0, 1000, name="AS")
BS = intvar(0, 1000, name="BS")

model = Model([A1 > A2,
               A2 >= A3,
               36 == A1 * A2 * A3,

               B1 >= B2,
               B2 >= B3,
               A1 != B1,

               36 == B1 * B2 * B3,
               AS == A1 + A2 + A3,
               BS == B1 + B2 + B3,
               AS == BS
               ])

# Solve
model.solve()

# Print the solution
solution = {"A1": A1.value(), "A2": A2.value(), "A3": A3.value()}
print(json.dumps(solution))
# End of CPMPy script