kostis-init/CP-Bench huggingface dataset:
Problem description:
Here's a fantastic problem I recently heard. Apparently it was first posed by Claude Gaspard Bachet de Meziriac in a book of arithmetic problems published in 1612, and can also be found in Heinrich Dorrie's 100 Great Problems of Elementary Mathematics.    A merchant had a forty pound measuring weight that broke   into four pieces as the result of a fall. When the pieces were   subsequently weighed, it was found that the weight of each piece   was a whole number of pounds and that the four pieces could be   used to weigh every integral weight between 1 and 40 pounds. What   were the weights of the pieces?  Note that since this was a 17th-century merchant, he of course used a balance scale to weigh things. So, for example, he could use a 1-pound weight and a 4-pound weight to weigh a 3-pound object, by placing the 3-pound object and 1-pound weight on one side of the scale, and the 4-pound weight on the other side.  Print the weights of the four pieces (weights).

Input data:

Decision variables: weights

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


def increasing_strict(args):
    """
    Ensure that the values in args are strict increasing.
    """
    return [args[i - 1] < args[i] for i in range(1, len(args))]


# Parameters
m = 40
n = 4

# variables
weights = intvar(1, m, shape=n, name="weights")
x = intvar(-1, 1, shape=(m, n), name="x")

model = Model(minimize=weights[-1])
# model = Model()

# constraints

model += [AllDifferent(weights)]
model += [sum(weights) == m]

# Check that all weights from 1 to 40 can be made.
#
# Since all weights can be on either side
# of the side of the scale we allow either
# -1, 0, or 1 of the weights, assuming that
# -1 is the weights on the left and 1 is on the right.
#
for i in range(m):
    model += [sum([weights[j] * x[i, j] for j in range(n)]) == i + 1]
    # model += [i+1 == sum(weights * x[i])] # using numpy's magic

# symmetry breaking
# for j in range(1, n):
#   model += [weights[j-1] < weights[j]]
model += [increasing_strict(weights)]
model.solve()

# Print the solution
solution = {"weights": weights.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Each of four alphabet blocks has a single letter of the alphabet on each of its six sides. In all, the four blocks contain every letter but Q and Z. By arranging the blocks in various ways, you can spell all of the words listed below. Can you figure out how the letters are arranged on the four blocks?   BAKE ONYX ECHO OVAL  GIRD SMUG JUMP TORN  LUCK VINY LUSH WRAP  Print the solution as a list of 24 numbers representing at which block each letter is placed (dice), between 0 and 3.

Input data:

Decision variables: dice

CPMpy model:
# Import libraries
from cpmpy import *
import json
import numpy as np


def count(a, val, c):
    """
    count(a,val,c)

    c is the number of occurrences of val in array a.
    """
    return [c == sum([a[i] == val for i in range(len(a))])]


def global_cardinality_count(a, gcc):
    """
    global_cardinality_count(a,gcc)

    Global cardinality count: Collect the number of occurrences of each value 0..a.ub
    in gcc. The array gcc must be of length 0..ub.
    """
    n = len(a)
    ub = max([a[i].ub for i in range(n)])
    constraints = []
    for i in range(ub + 1):
        constraints += [count(a, i, gcc[i])]

    return constraints


n = 4
num_words = 12
m = 24

# Index 1 based (adjusted below)
A = 1;
B = 2;
C = 3;
D = 4;
E = 5;
F = 6;
G = 7;
H = 8;
I = 9;
J = 10;
K = 11;
L = 12;
M = 13;
N = 14;
O = 15;
P = 16;
R = 17;
S = 18;
T = 19;
U = 20;
V = 21;
W = 22;
X = 23;
Y = 24;

alpha = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
         "N", "O", "P", "R", "S", "T", "U", "V", "W", "X", "Y"];

words = np.array([[B, A, K, E],
                  [O, N, Y, X],
                  [E, C, H, O],
                  [O, V, A, L],
                  [G, I, R, D],
                  [S, M, U, G],
                  [J, U, M, P],
                  [T, O, R, N],
                  [L, U, C, K],
                  [V, I, N, Y],
                  [L, U, S, H],
                  [W, R, A, P]])

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

model = Model()

# the letters in a word must be on a different die
for word in range(num_words):
    # Also, adjust for 1-based
    model += (AllDifferent([dice[words[word] - 1]]))

# there must be exactly 6 letters of each die
model += (global_cardinality_count(dice, [6 for i in range(n)]))

# symmetry breaking (first word is placed)
model += (dice[0] <= dice[6])
model += (dice[6] <= dice[12])

model.solve()

# Print the solution
solution = {"dice": dice.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Take a rack cabinet, like this one:   [ an image ]  Let's say, there are 8 1U devices, maybe servers, routers and whatnot, named as A, B, C, D, E, F, G, H. Devices must be connected by cables: probably twisted pair or whatever network engineers using today. Some devices must be connected by several cables (2 cables, 3 or 4):  A <--- 1 cable  ---> H A <--- 2 cables ---> E B <--- 4 cables ---> F C <--- 1 cable  ---> G C <--- 1 cable  ---> D C <--- 1 cable  ---> E D <--- 3 cables ---> H G <--- 1 cable  ---> H  The problem: how we can place these 8 devices in such an order, so that sum of all cable lengths would be as short as possible?  Print the optimal sum of all cable lengths (final_sum).

Input data:

Decision variables: final_sum

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

# Parameters
n = 8

model = Model()

# A <--- 1 cable  ---> H
# A <--- 2 cables ---> E
# B <--- 4 cables ---> F
# C <--- 1 cable  ---> G
# C <--- 1 cable  ---> D
# C <--- 1 cable  ---> E
# D <--- 3 cables ---> H
# G <--- 1 cable  ---> H
A, B, C, D, E, F, G, H = list(range(n))

cable_struct = [[A, H, 1],
                [A, E, 2],
                [B, F, 4],
                [C, G, 1],
                [C, D, 1],
                [C, E, 1],
                [D, H, 3],
                [G, H, 1]]

x = intvar(0, n - 1, shape=n, name="x")  # position of the device in the rack
t = intvar(1, n * n, shape=len(cable_struct), name="t")  # cable lengths
final_sum = intvar(0, n * n, name="final_sum")  # sum of all cable lengths

# all "devices" has distinct positions in rack:
model += [AllDifferent(x),
          final_sum == sum(t)]

for i in range(len(cable_struct)):
    a, b, num = cable_struct[i]
    model += [t[i] == abs(x[a] - x[b]) * num]

model.minimize(final_sum)

# Solve
model.solve()

# Print the solution
solution = {"final_sum": final_sum.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
The Purpose of the Game  To take an n by n grid, representing n^2 squares, and completely fill every square based on two types of movements.  Movement Type I)  If the next number in the sequence is going to be placed vertically or horizontally, then it must be placed exactly three squares away from the previous number (there must be a two square gap between the numbers).  Movement Type II) If the next number in the sequence is going to be placed diagonally, then it must be placed exactly two squares away from the previous number (there must be a one square gap between the numbers).  Print the completed grid (x).

Input data:
n = 5

Decision variables: x

CPMpy model:
# Data
n = 5
# End of data

# Import libraries
from cpmpy import *
import json

# Decision variables
x = intvar(1, n * n, shape=(n, n), name="x")

x_flat = [x[i, j] for i in range(n) for j in range(n)]

model = Model(AllDifferent(x_flat))
model += (x[0, 0] == 1)

for k in range(1, n * n):
    i = intvar(0, n - 1, name=f"i_{k}")
    j = intvar(0, n - 1, name=f"j_{k}")
    a = intvar(-3, 3, name=f"a_{k}")
    b = intvar(-3, 3, name=f"b_{k}")

    # Ensure that we are in the square
    model += [i + a >= 0, i + a <= n - 1, j + b >= 0, j + b <= n - 1]

    # model += [a != -1, a != 1, b != -1, b != 1]

    model += [((abs(a) == 3) & (b == 0)) |
              ((abs(b) == 3) & (a == 0)) |
              ((abs(a) == 2) & (abs(b) == 2))
              ]

    # Valid moved
    # model += [ ((a == 3) & (b == 0))  |
    #            ((a == -3) & (b == 0)) |

    #            ((b == 3) & (a == 0))  |
    #            ((b == -3) & (a == 0)) |

    #            ((a == 2) & (b == 2))  |
    #            ((a == 2) & (b == -2)) |
    #            ((a == -2) & (b == 2)) |
    #            ((a == -2) & (b == -2))
    #         ]

    # 1) First: fix this k, i.e.
    model += [k == Element(x_flat, (i * n) + j)]

    # 2) Then, find the position of the next value, i.e.
    model += [(k + 1) == Element(x_flat, ((i + a) * n) + (j + b))]

# Solve the model
model.solve()

# Print the solution
solution = {"x": x.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Alice is a kindergarden teacher. She wants to give some candies to the children in her class.  All the children sit in a line and each  of them  has a rating score according to his or her usual performance. Alice wants to give at least 1 candy for each child.Children get jealous of their immediate neighbors, so if two children sit next to each other then the one with the higher rating must get more candies. Alice wants to save money, so she wants to minimize the total number of candies.  Print the optimal number of candies needed in total (z).

Input data:
ratings = [2, 3, 4, 4, 4, 2, 1, 3, 4]  # Ratings of the children

Decision variables: z

CPMpy model:
# Data
ratings = [2, 3, 4, 4, 4, 2, 1, 3, 4]  # Ratings of the children
# End of data

# Import libraries
from cpmpy import *
import json

# Parameters
n = len(ratings)

# variables
x = intvar(1, n, shape=n, name="x")  # number of candies for each child
z = intvar(1, n * n, name="z")  # total number of candies

# constraints
model = Model([z == sum(x),
               z >= n])

for i in range(1, n):
    if ratings[i - 1] > ratings[i]:
        model += (x[i - 1] > x[i])
    elif ratings[i - 1] < ratings[i]:
        model += (x[i - 1] < x[i])

model.minimize(z)
# Solve the model
model.solve()

# Print the solution
solution = {"z": z.value(), "x": x.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Stockco is considering four investments. Investment 1 will yield a net present value (NPV) of $16,000; investment 2, an NPV of $22,000; investment 3, an NPV of $12,000; and investment 4, an NPV of $8,000. Each investment requires a certain cash outflow at the present time: investment 1, $5,000; investment 2, $7,000; investment 3, $4,000; and investment 4, $3,000. Currently, $14,000 is available for investment. How to maximize the NPV obtained from investments 1–4?  Print whether each investment is chosen (x) as a list of 0/1 values.

Input data:

Decision variables: x

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

# Parameters
budget = 14
npv = [16, 22, 12, 8]
cash_flow = [5, 7, 4, 3]
n = 4

# variables
x = boolvar(shape=n, name="x")  # x[i] = 1 if investments i
z = intvar(0, 1000, name="z")  # total NPV

# constraints
model = Model([
    # the sum of all choosen investments must be less than the budget
    sum(x * cash_flow) <= budget,
    z == sum(x * npv)
])

# Objective: maximize the NPV
model.maximize(z)

# Solve the model
model.solve()

# Print the solution
solution = {"z": z.value(), "x": x.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
A small joinery makes two different sizes of boxwood chess sets. The small set requires 3 hours of machining on a lathe, and the large set requires 2 hours. There are four lathes with skilled operators who each work a 40 hour week, so we have 160 lathe-hours per week. The small chess set requires 1 kg of boxwood, and the large set requires 3 kg. Unfortunately, boxwood is scarce and only 200 kg per week can be obtained. When sold, each of the large chess sets yields a profit of $20, and one of the small chess set has a profit of $5. The problem is to decide how many sets of each kind should be made each week so as to maximize profit.  Print the number of small sets and large sets, and the maximum profit (small_set, large_set, max_profit).

Input data:

Decision variables: large_set, small_set, max_profit

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

# Decision variables
small_set = intvar(0, 100, name="small_set")
large_set = intvar(0, 100, name="large_set")
max_profit = intvar(0, 10000, name="max_profit")

# Model
model = Model([
    small_set + 3 * large_set <= 200,  # Boxwood constraint
    3 * small_set + 2 * large_set <= 160,  # Lathe-hours constraint
    max_profit == 5 * small_set + 20 * large_set  # Profit calculation
])

# Objective: maximize the profit
model.maximize(max_profit)

# Solve the model
model.solve()

# Print the solution
solution = {
    "small_set": small_set.value(),
    "large_set": large_set.value(),
    "max_profit": max_profit.value()
}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Circling the squares:  The puzzle is to place a different number in each of the ten squares so that the sum of the squares of any two adjacent numbers shall be equal to the sum of the squares of the two numbers diametrically opposite to them. The four numbers placed, as examples, must stand as they are. The square of 16 is 256, and the square of 2 is 4. Add these together, and the result is 260. Also—the square of 14 is 196, and the square of 8 is 64. These together also make 260. Now, in precisely the same way, B and C should be equal to G and H (the sum will not necessarily be 260), A and K to F and E, H and I to C and D, and so on, with any two adjoining squares in the circle.  All you have to do is to fill in the remaining six numbers. Fractions are not allowed, and I shall show that no number need contain more than two figures.  Print the 10 numbers in the circle (A, B, C, D, E, F, G, H, I, K) when A=16, B=2, F=8, G=14.

Input data:

Decision variables: H, D, K, G, E, C, I, F, A, B

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


def s(x1, x2, y1, y2):
    return x1 * x1 + x2 * x2 == y1 * y1 + y2 * y2


n = 10

# variables
x = intvar(1, 99, shape=n, name="x")
A, B, C, D, E, F, G, H, I, K = x

# constraints
model = Model([AllDifferent(x),
               A == 16,
               B == 2,
               F == 8,
               G == 14,

               s(A, B, F, G),
               s(B, C, G, H),
               s(C, D, H, I),
               s(D, E, I, K),
               s(E, F, K, A),
               ])
# End of CPMPy script

# Solve
model.solve()

# Print the solution
solution = {"A": A.value(), "B": B.value(), "C": C.value(), "D": D.value(), "E": E.value(),
            "F": F.value(), "G": G.value(), "H": H.value(), "I": I.value(), "K": K.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Three players (X, Y, Z) of different nationalities (American, English, French) are seated around a circular table playing a game of Hearts. Each passed three cards to the person on their right. Y passed three hearts to the American, X passed the queen of spades and two diamonds to the person who passed their cards to the Frenchwoman. Determine the nationality of each person.  Print the values of X, Y, Z, American, English, French (x, y, z, american, english, french), such that the same value denotes the matching between the person and their nationality. Use 0, 1 or 2.

Input data:

Decision variables: y, english, american, french, x, z

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


# a is right to b
def right_to(a, b):
    # return ((a == b+1) | (a == b-2) )
    return (a == (b + 1) % 3)


# a is left to b
def left_to(a, b):
    return [right_to(b, a)]


n = 3

# variables
players = intvar(0, 2, shape=n, name="players")
x, y, z = players

nationalities = intvar(0, 2, shape=n, name="women")
american, english, french = nationalities

model = Model([AllDifferent(players),
               AllDifferent([american, english, french]),
               right_to(y, american),
               left_to(x, french),

               # symmetry breaking
               x == 0
               ])

model.solve()

# Print the solution
solution = {"x": x.value(), "y": y.value(), "z": z.value(), "american": american.value(), "english": english.value(),
            "french": french.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Rearrange the numbers on the face of a clock (1 to 12) so no triplet of adjacent numbers has a sum higher than 21. This is the smallest value that the highest sum of a triplet can have.  Print the arrangement of the 12 numbers on the clock (x) as a list, with the first number being 12.

Input data:

Decision variables: x

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

# Parameters
n = 12

# variables
x = intvar(1, n, shape=n, name="x")  # The numbers on the clock
triplet_sum = intvar(0, 21, name="triplet_sum")

# constraints
model = Model([AllDifferent(x),
               x[0] == 12,
               x[1] > x[11],
               [(x[i % 12] + x[(i % 12) - 1] + x[(i % 12) - 2]) <= triplet_sum for i in range(n)],
               ])

# Solve
model.solve()

# Print the solution
solution = {"x": x.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Given two positive integers a and b, where a - b is a prime number and a × b is a perfect square n^2, find the smallest value of a no less than 2012.  Print the values of a, b, n, and p (a, b, n, p).

Input data:

Decision variables: b, p, a, n

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


def is_prime(n):
    """Return True if n is prime, False otherwise"""
    if n < 2:
        return False
    for i in range(2, int(sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True


def primes(n):
    """Return a list of primes less than n"""
    primes = []
    for i in range(2, n):
        if is_prime(i):
            primes.append(i)
    return primes


max_val = 10000
prime_list = primes(2012)

a = intvar(2012, max_val, name="a")
b = intvar(2, 2012, name="b")
n = intvar(2, 2012, name="n")
# p can only take primes (reduced below).
# How do one create a list of specific domain in cpmpy?
p = intvar(2, 2012, name="p")

model = Model(minimize=a)

for i in range(max(prime_list)):
    # if not i in prime_list:
    #  model += [p != i]
    if not is_prime(i):
        model += [p != i]

model += [a >= b]
model += [p == a - b]
model += [a * b == n * n]

model.solve()

solution = {"a": a.value(), "b": b.value(), "n": n.value(), "p": p.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
Find the minimum number of coins that allows one to pay exactly any amount smaller than one Euro using the denominations 1, 2, 5, 10, 20, 50 cents.  Print the number of each type of coin used (x) as a list.

Input data:

Decision variables: x

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

# Parameters
denominations = [1, 2, 5, 10, 20, 50]  # Euro cent denominations
n = len(denominations)

# declare variables
x = intvar(0, 99, shape=n, name="x")  # The number of each type of coin used
num_coins = intvar(0, 99, name="num_coins")  # The total number of coins used

model = Model(minimize=num_coins)

# constraints

# number of used coins, to be minimized
model += [num_coins == sum(x)]

# Check that all changes from 1 to 99 can be made.
for j in range(1, 100):
    tmp = intvar(0, 99, shape=n)
    model += [sum(tmp * denominations) == j]
    model += [tmp[i] <= x[i] for i in range(n)]

# Solve the model
model.solve()

# Print the solution
solution = {"x": x.value().tolist()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
In a quadratic grid (or a larger chessboard) with 31x31 cells, one should  place coins in such a way that the following conditions are fulfilled:    1. In each row exactly 14 coins must be placed.    2. In each column exactly 14 coins must be placed.    3. The sum of the quadratic horizontal distance from the main       diagonal of all cells containing a coin must be as       small as possible.    4. In each cell at most one coin can be placed.  The description says to place 14x31 = 434 coins on the chessboard each row containing 14 coins and each column also containing 14 coins.  Print whether a coin is placed in each cell (x) as a list of 0/1 lists, and the sum of the quadratic horizontal distance from the main diagonal (z) as a number.

Input data:

Decision variables: x, z

CPMpy model:
# Import libraries
from cpmpy import *
import json
import numpy as np

# Parameters
n = 31
c = 14

# variables
x = intvar(0, 1, shape=(n, n), name="x")  # The coins on the grid (1 if a coin is placed, 0 otherwise)
z = intvar(0, 1000000, name="z")  # The sum of the quadratic horizontal distance from the main diagonal

model = Model([
    # every row adds up to c
    [sum(row) == c for row in x],

    # every col adds up to c
    [sum(col) == c for col in x.transpose()],

    # quadratic horizonal distance
    z == sum([x[i, j] * abs(i - j) * abs(i - j) for i in range(0, n) for j in range(0, n)]),

], minimize=z
)

# Solve the model
model.solve()

# Print the solution
solution = {"x": x.value().tolist(), "z": z.value()}
print(json.dumps(solution))
# End of CPMPy script
Problem description:
A contractor planning the construction of a house found that he would have to pay:    * $ 1,100 to the paper hanger and the painter,   * $ 1,700 to the painter and plumber,   * $ 1,100 to the plumber and electrician,   * $ 3,300 to the electrician and carpenter,   * $ 5,300 to the carpenter and mason,   * $ 3,200 to the mason and painter.  What does each man charge for his services?  Print the cost of each person's service (paper_hanger, painter, plumber, electrician, carpenter, mason) in dollars.

Input data:

Decision variables: painter, plumber, electrician, carpenter, mason, paper_hanger

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

n = 6
x = intvar(1, 5300, shape=n, name="x")
paper_hanger, painter, plumber, electrician, carpenter, mason = x

costs = [[paper_hanger, painter, 1100],
         [painter, plumber, 1700],
         [plumber, electrician, 1100],
         [electrician, carpenter, 3300],
         [carpenter, mason, 5300],
         [mason, painter, 3200],
         ]

# model = Model([1100 == paper_hanger + painter,
#                1700 == painter + plumber,
#                1100 == plumber + electrician,
#                3300 == electrician + carpenter,
#                5300 == carpenter + mason,
#                3200 == mason + painter,
#                ])

# Alternative encoding:
model = Model([sum(costs[i][:2]) == costs[i][2] for i in range(n)])

# Solve
model.solve()

# Print the solution
solution = {"paper_hanger": paper_hanger.value(), "painter": painter.value(), "plumber": plumber.value(),
            "electrician": electrician.value(), "carpenter": carpenter.value(), "mason": mason.value()}
print(json.dumps(solution))
# End of CPMPy script