Ashkan Rezaee
Ashkan Rezaee

Reputation: 11

How to implement a new constraint based on two other constraints on CPLEX?

I am very new to Cplex. I have these two constraints (R is the set of numbers in range 20) :

        model.add_constraints((model.sum(x[i, j] for j in R2 ) == 2 for i in R),"C1" )
        model.add_constraints((x[i, n1-4] ==x[i, n1-2]  for i in R ),"C2" )

I need to count how many i are fulfilling both C1 and C2 and then define a new constraint that says "at least 10 of i fulfill both C1 as C2".

How can I do that with cplex?

Upvotes: 0

Views: 974

Answers (3)

Philippe Couronne
Philippe Couronne

Reputation: 846

In the following code, I create two lists of 100 integer variables, xi and xj.

I then define a list of logical and constraints ctands, true when xi[k]>=3 and yi[k]>=5.

I then post that the sum of these logical constraints is exactly equal to 10, which means exactly 10 of them must be satisfied, as any constraint can be used as a binary variable, equal to 1 when satisfied.

The objective is to minimize the sum of xi and xj, so the result is, as expected 10 * 3 + 10*5 = 80

m = Model()
xi = m.integer_var_list(100, ub=10, name='xi')
xj = m.integer_var_list(100, ub=11, name='xj')

ctands = [((xi[k]>=3) + (xj[k]>=5)==2) for k in range(100)]
# version with logical_and
# ctands = [mdl.logical_and((xi[k]>=3), (xj[k]>=5)==2)) for k in range(100)]

#state that exactly 10 ands are true: the value of an and is 1 when true, 0 when false
m.add(m.sum(ctands) == 10)
# this minimize pulls xs and ys variables to 0
m.minimize(m.sum(xi) + m.sum(xj))
m.solve()
m.print_solution()

Upvotes: 0

Alex Fleischer
Alex Fleischer

Reputation: 10077

let me give you an example out of the zoo example

from docplex.mp.model import Model

# Data

Buses=[
    (40,500),
    (30,400),
    (35,450),
    (20,300)
    ]

nbKids=300

# Indexes

busSize=0;
busCost=1;

for b in Buses:
    print("buses with ",b[busSize]," seats cost ",b[busCost])

mdl = Model(name='buses')

#decision variables
mdl.nbBus=mdl.integer_var_dict(Buses,name="nbBus")

# Constraint
mdl.add_constraint(sum(mdl.nbBus[b]*b[busSize] for b in Buses) >= nbKids, 'kids')

# Objective
mdl.minimize(sum(mdl.nbBus[b]*b[busCost] for b in Buses))

mdl.solve()

# Display solution
for b in Buses:
    print(mdl.nbBus[b].solution_value," buses with ",b[busSize]," seats");

#Add a constraint
# Number of sizes where we have 1 or 2 buses should be at least 3

mdl.add(mdl.sum(mdl.logical_and(1<=mdl.nbBus[b],mdl.nbBus[b]<=2) for b in Buses) >=3)

mdl.solve()

# Display solution
for b in Buses:
    print(mdl.nbBus[b].solution_value," buses with ",b[busSize]," seats");

which gives

buses with  40  seats cost  500
buses with  30  seats cost  400
buses with  35  seats cost  450
buses with  20  seats cost  300
5.0  buses with  40  seats
1.0  buses with  30  seats
2.0  buses with  35  seats
0  buses with  20  seats
4.0  buses with  40  seats
1.0  buses with  30  seats
2.0  buses with  35  seats
2.0  buses with  20  seats

Upvotes: 0

Philippe Couronne
Philippe Couronne

Reputation: 846

In Docplex, each linear constraint can be used as an expression, that acts like a boolean variable, equal to 1 if the constraint is satisfied, to 0 if not satisfied.

Note that when added to the model (via Mode.add, Model.add_constraint(s)), a constraint will always be satisfied. However, you can write:

m.add( (x<=3) + (y>=5) >= 1)

which means that at least one (possibly two) of the constraints (x<=3) and (y>=5) is satisfied.

In your case, , assuming an array of N constraints cts[i], writing:

m.add( m.sum(cts) >= 10)

You can also use such an expression in the objective:

m.maximize(m.sum(cts)) 

will maximize the number of satisfied constraints

will ensure at least 10 of them are satisfied

Note: always use Model.sum, not Python sum to avoid performance issues.

Upvotes: 1

Related Questions