Generic Constraints
In the XCSP³-core standard, generic constraints are categorized into two main types: intention and extension constraints.
Intention Constraints
These are constraints that are defined by a logical expression or a function. They are called intentional because they are defined by the property they satisfy. For example, a constraint that specifies that a variable
Note that the intention constraint is not directly available through the JC-API in Constraints.jl. It is designed as such since defining a constraint through a predicate is the natural way.
We provide a straightforward example through the :dist_different
constraint on how to define and add such a constraint in the USUAL_CONSTRAINTS
collection.
Higher level modeling languages such as JuMP
should provide a Intention
interface.
Defining an intention constraint in JC-API
We use the dist_different
constraint to illustrate how to define an intention constraint in Constraints.jl. The dist_different
constraint ensures that the distances between marks
The constraint is then added to the usual constraints collection.
const description_dist_different = """
Ensures that the distances between marks on the ruler are unique.
"""
# Define the predicate
predicate_dist_different(x) = abs(x[1] - x[2]) ≠ abs(x[3] - x[4])
# Add it to usual constraints
@usual concept_dist_different(x) = xcsp_intention(
list = x,
predicate = predicate_dist_different
)
Please check the section dedicated to the Golomb Ruler problem to see a use for this constraint. <!– TODO: Golomb Ruler –>
APIs
Note that the intention constraint is not directly available through the JC-API in Constraints.jl. It is designed as such since defining a constraint through a predicate is the natural way.
We provide here a usage example for the :dist_different
constraint, previously added to the USUAL_CONSTRAINTS
collection.
Higher level modeling language such as JuMP
should provide an Intention
interface.
using Constraints
concept(:dist_different, x)
concept(:dist_different)(x)
# Defines the DistDifferent constraint
using Constraints
c = x -> xcsp_intention(
list = x,
predicate = y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4])
)
c([1, 2, 3, 3]) # true
c([1, 2, 3, 4]) # false
using CBLS, JuMP
model = Model(CBLS.Optimizer)
# Using build-in DistDifferent
@variable(model, 0 <= X[1:4] <= 10, Int)
@constraint(model, X in DistDifferent())
# Alternatively
@variable(model, 0 <= Y[1:4] <= 10, Int)
@constraint(model, Y in Intention(y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4])))
optimize!(model)
@info value.(X)
@info value.(Y)
using CBLS
import MathOptInterface as MOI
optimizer = CBLS.Optimizer()
x = MOI.add_variables(optimizer, 4)
for xi in x
# Missing RangeDomain currently in CBLS
MOI.add_constraint(optimizer, xi, CBLS.DiscreteSet(collect[1:10]))
end
MOI.add_constraint(optimizer, x, CBLS.Intention(y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4])))
MOI.optimize!(optimizer)
Extension Constraints
These are constraints that are defined by explicitly listing all the tuples of values that satisfy the constraint. They are called extensional because they are defined by the set of values they allow. For example, a binary constraint that specifies that a variable
These two types of constraints provide a flexible way to define complex relationships between variables in constraint programming.
using Constraints
concept(:dist_different, x)
concept(:dist_different)(x)
# Defines the DistDifferent constraint
using Constraints
c = x -> xcsp_intention(
list = x,
predicate = y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4])
)
c([1, 2, 3, 3]) # true
c([1, 2, 3, 4]) # false
using CBLS, JuMP
model = Model(CBLS.Optimizer)
# Using build-in DistDifferent
@variable(model, 0 <= X[1:4] <= 10, Int)
@constraint(model, X in DistDifferent())
# Alternatively
@variable(model, 0 <= Y[1:4] <= 10, Int)
@constraint(model, Y in Intention(y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4])))
optimize!(model)
@info value.(X)
@info value.(Y)
using CBLS
import MathOptInterface as MOI
optimizer = CBLS.Optimizer()
x = MOI.add_variables(optimizer, 4)
for xi in x
# Missing RangeDomain currently in CBLS
MOI.add_constraint(optimizer, xi, CBLS.DiscreteSet(collect[1:10]))
end
MOI.add_constraint(optimizer, x, CBLS.Intention(y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4])))
MOI.optimize!(optimizer)