Conditional if sum - conditional-statements

I want to sum over a range (Areas) except if j is not equal to k.
Can anybody help me?
I tried:
forall( k in Areas )
sum ( j in Areas: j!=k ) X[k][j] == 1;
Also tried:
forall( k in Areas )
sum ( j in Areas) (j!=k)*X[k][j] == 1;
int NbAreas = 5;
range Areas = 1..NbAreas;
float P[Areas] = [0, 0.3, 0.65, 0.2, 0.1];
float D[Areas] = [0, 7, 5, 3, 9];
float FROMTO[Areas][Areas] = [
[0, 2, 5, 1, 3],
[2, 0, 4, 3, 8],
[5, 4, 0, 6, 2],
[1, 3, 6, 0, 7],
[3, 8, 2, 7, 0]];
dvar int Y[Areas];
dvar int T[Areas];
dvar int X[Areas][Areas] in 0..1;
maximize sum( i in Areas ) P[i] * Y[i];
subject to {
forall( k in Areas )
sum ( j in Areas: j!=k) X[k][j] == 1;
forall( k in Areas)
sum ( i in Areas: i!=k) X[i][k] == 1;
forall( i in Areas) forall (j in Areas) T[i] + FROMTO[i][j] - T[j] - 100*(1-X[i][j]) <= 0;
T[1] == 0;
forall( i in Areas: i!=1) T[i] - D[i] - 1000*(1-Y[i]) <= 0;
}

I take it you meant
I want to sum over a range (Areas) except if j is equal (instead
of "not equal") to k.
I also assume that your issue is that the model you posted is infeasible. You should label your constraints so that the conflict refiner can run and then look at the results of the conflict refiner. If I label your constraints like so:
maximize sum( i in Areas ) P[i] * Y[i];
subject to {
forall( k in Areas )
sum1: sum ( j in Areas: j!=k) X[k][j] == 1;
forall( k in Areas)
sum2: sum ( i in Areas: i!=k) X[i][k] == 1;
forall( i in Areas) forall (j in Areas)
fromto: T[i] + FROMTO[i][j] - T[j] - 100*(1-X[i][j]) <= 0;
T[1] == 0;
forall( i in Areas: i!=1)
limit: T[i] - D[i] - 1000*(1-Y[i]) <= 0;
Then I get this conflict:
sum1(1): X(1)(2) + X(1)(3) + X(1)(4) + X(1)(5) = 1
sum1(2): X(2)(1) + X(2)(3) + X(2)(4) + X(2)(5) = 1
sum1(3): X(3)(1) + X(3)(2) + X(3)(4) + X(3)(5) = 1
sum1(4): X(4)(1) + X(4)(2) + X(4)(3) + X(4)(5) = 1
sum1(5): X(5)(1) + X(5)(2) + X(5)(3) + X(5)(4) = 1
fromto(1)(2): 100 X(1)(2) + T(1) - T(2) <= 98
fromto(1)(3): 100 X(1)(3) + T(1) - T(3) <= 95
fromto(1)(4): 100 X(1)(4) + T(1) - T(4) <= 99
fromto(1)(5): 100 X(1)(5) + T(1) - T(5) <= 97
fromto(2)(1): 100 X(2)(1) - T(1) + T(2) <= 98
fromto(2)(3): 100 X(2)(3) + T(2) - T(3) <= 96
fromto(2)(4): 100 X(2)(4) + T(2) - T(4) <= 97
fromto(2)(5): 100 X(2)(5) + T(2) - T(5) <= 92
fromto(3)(1): 100 X(3)(1) - T(1) + T(3) <= 95
fromto(3)(2): 100 X(3)(2) - T(2) + T(3) <= 96
fromto(3)(4): 100 X(3)(4) + T(3) - T(4) <= 94
fromto(3)(5): 100 X(3)(5) + T(3) - T(5) <= 98
fromto(4)(1): 100 X(4)(1) - T(1) + T(4) <= 99
fromto(4)(2): 100 X(4)(2) - T(2) + T(4) <= 97
fromto(4)(3): 100 X(4)(3) - T(3) + T(4) <= 94
fromto(4)(5): 100 X(4)(5) + T(4) - T(5) <= 93
fromto(5)(1): 100 X(5)(1) - T(1) + T(5) <= 97
fromto(5)(2): 100 X(5)(2) - T(2) + T(5) <= 92
fromto(5)(3): 100 X(5)(3) - T(3) + T(5) <= 98
fromto(5)(4): 100 X(5)(4) - T(4) + T(5) <= 93
So it seems your data in FROMTO and T does not allow a feasible solution.

You wrote "except if j is not equal to k".
So instead of
forall( k in Areas)
sum ( i in Areas: i!=k) X[i][k] == 1;
I would write
forall( k in Areas)
sum ( i in Areas: i==k) X[i][k] == 1;

Related

Updating constraint set rhs in docplex

I am trying to update the rhs of a constraint iteratively under a while loop in docplex, however, it does not work properly. As I analyze the output text file, while some constraints are updated as I want, others are not.
z_bar is a list consists of y+1 elements and is updated at each iteration. Constraint set I want to change the RHS of consists of (x+1)*(y+1) constraints. z_bar is related to the j indice, however since each constraint involves i and j indices, I have to update all. What do you think I am doing wrong?
Original constraint set:
for i in range(1, x + 1):
for j in range(1, y + 1):
sub_cbd.add_constraint(x_cbd[i, j] <= z_bar[j], ctname='constraint_name{0}{1}'.format(i, j))
Updating constraint set rhs attempt:
for i in range(1, x + 1):
for j in range(1, y + 1):
sub_cbd.get_constraint_by_name('constraint_name{0}{1}'.format(i, j)).rhs = z_bar[j]
For the updated z_bar: [0, 0, 0, 0, 1, 1, 0...0], 15 elements in total, two 1s and 13 0s.
How it looks now:
constraint11: x_1_1 <= 0
constraint12: x_1_2 <= 0
constraint13: x_1_3 <= 0
constraint14: x_1_4 <= 0
constraint15: x_1_5 <= 1
constraint16: x_1_6 <= 1
constraint17: x_1_7 <= 0
constraint18: x_1_8 <= 0
constraint19: x_1_9 <= 0
constraint110: x_1_10 <= 0
constraint111: x_1_11 <= 1
constraint112: x_1_12 <= 1
constraint113: x_1_13 <= 1
constraint114: x_1_14 <= 1
constraint115: x_1_15 <= 1
constraint21: x_2_1 <= 0
constraint22: x_2_2 <= 0
constraint23: x_2_3 <= 0
constraint24: x_2_4 <= 0
constraint25: x_2_5 <= 1
constraint26: x_2_6 <= 1
constraint27: x_2_7 <= 0
constraint28: x_2_8 <= 0
constraint29: x_2_9 <= 0
constraint210: x_2_10 <= 0
constraint211: x_2_11 <= 1
constraint212: x_2_12 <= 1
constraint213: x_2_13 <= 1
constraint214: x_2_14 <= 1
constraint215: x_2_15 <= 1
How it should look:
constraint11: x_1_1 <= 0
constraint12: x_1_2 <= 0
constraint13: x_1_3 <= 0
constraint14: x_1_4 <= 0
constraint15: x_1_5 <= 1
constraint16: x_1_6 <= 1
constraint17: x_1_7 <= 0
constraint18: x_1_8 <= 0
constraint19: x_1_9 <= 0
constraint110: x_1_10 <= 0
constraint111: x_1_11 <= 0
constraint112: x_1_12 <= 0
constraint113: x_1_13 <= 0
constraint114: x_1_14 <= 0
constraint115: x_1_15 <= 0
constraint21: x_2_1 <= 0
constraint22: x_2_2 <= 0
constraint23: x_2_3 <= 0
constraint24: x_2_4 <= 0
constraint25: x_2_5 <= 1
constraint26: x_2_6 <= 1
constraint27: x_2_7 <= 0
constraint28: x_2_8 <= 0
constraint29: x_2_9 <= 0
constraint210: x_2_10 <= 0
constraint211: x_2_11 <= 0
constraint212: x_2_12 <= 0
constraint213: x_2_13 <= 0
constraint214: x_2_14 <= 0
constraint215: x_2_15 <= 0
Full working example in https://github.com/AlexFleischerParis/zoodocplex/blob/master/zooincremental.py
from docplex.mp.model import Model
# original model
mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
mdl.minimize(nbbus40*500 + nbbus30*400)
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
#now 350 kids instead of 300
print()
print("now 350 kids instead of 300")
mdl.get_constraint_by_name("kids").rhs=350;
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
# no more than 4 buses 40 seats
print()
print("no more than 4 buses 40 seats")
mdl.get_var_by_name("nbBus40").ub=4
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
#change the objective so that cost for 40 seats is 450
#and remove the limit on the number of buses 40 seats
print()
print("change the objective so that cost for 40 seats is 450")
print("and remove the limit on the number of buses 40 seats ")
mdl.get_var_by_name("nbBus40").ub=1000
mdl.set_objective("min",nbbus40*450 + nbbus30*400);
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
Now let me change this into a loop:
from docplex.mp.model import Model
# original model
mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
for i in range(0,10):
mdl.add_constraint(nbbus40*40 + nbbus30*30*i >= 300+i,'kids'+str(i))
mdl.minimize(nbbus40*500 + nbbus30*400)
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
#now 350 kids instead of 300
for i in range(0,10):
mdl.get_constraint_by_name("kids"+str(i)).rhs=350+i;
mdl.export("zoo.lp")
mdl.solve()
and then in zoo.lp I get
Minimize
obj: 500 nbBus40 + 400 nbBus30
Subject To
kids0: 40 nbBus40 >= 350
kids1: 40 nbBus40 + 30 nbBus30 >= 351
kids2: 40 nbBus40 + 60 nbBus30 >= 352
kids3: 40 nbBus40 + 90 nbBus30 >= 353
kids4: 40 nbBus40 + 120 nbBus30 >= 354
kids5: 40 nbBus40 + 150 nbBus30 >= 355
kids6: 40 nbBus40 + 180 nbBus30 >= 356
kids7: 40 nbBus40 + 210 nbBus30 >= 357
kids8: 40 nbBus40 + 240 nbBus30 >= 358
kids9: 40 nbBus40 + 270 nbBus30 >= 359
Bounds
Generals
nbBus40 nbBus30
End

Simple way to request a factorization over the Gaussians

I work in the Gaussian integers and use factor on them with success. However, occasionally the imaginary part can vanish, but I still want a factorization in the Gaussian integers.
As an example, the program for(j=-3, 3, print(j,": ",factor(17+j*I))) writes:
-3: [-I, 1; 1 + I, 1; 10 + 7*I, 1]
-2: [-I, 1; 2 + 17*I, 1]
-1: [-1, 1; 1 + I, 1; 1 + 2*I, 1; 2 + 5*I, 1]
0: Mat([17, 1])
1: [-I, 1; 1 + I, 1; 2 + I, 1; 5 + 2*I, 1]
2: Mat([17 + 2*I, 1])
3: [-I, 1; 1 + I, 1; 7 + 10*I, 1]
I would like the middle line in the output to be different:
-3: [-I, 1; 1 + I, 1; 10 + 7*I, 1]
-2: [-I, 1; 2 + 17*I, 1]
-1: [-1, 1; 1 + I, 1; 1 + 2*I, 1; 2 + 5*I, 1]
0: [-I, 1; 4 + I, 1; 1 + 4*I, 1]
1: [-I, 1; 1 + I, 1; 2 + I, 1; 5 + 2*I, 1]
2: Mat([17 + 2*I, 1])
3: [-I, 1; 1 + I, 1; 7 + 10*I, 1]
Is there some setting to do that? Or will I have to write my own "wrapper" that treats this case specially?
Function factor(x, {D}) receives an optional parameter D indicating the factorisation domain. So just specify the target domain in call factor(x, I):
> for(j=-3, 3, print(j,": ",factor(17+j*I, I)))
-3: [-I, 1; 1 + I, 1; 10 + 7*I, 1]
-2: [-I, 1; 2 + 17*I, 1]
-1: [-1, 1; 1 + I, 1; 1 + 2*I, 1; 2 + 5*I, 1]
0: [-I, 1; 4 + I, 1; 1 + 4*I, 1]
1: [-I, 1; 1 + I, 1; 2 + I, 1; 5 + 2*I, 1]
2: Mat([17 + 2*I, 1])
3: [-I, 1; 1 + I, 1; 7 + 10*I, 1]

Rounding Non-LinearExpr with google or-tools SAT solver

Using CP-SAT of google or-tools I'm trying to write this constraint:
q >= (50x + 100y + 150z + 200k + 250p + 300v) / (x + y + z + k + p + v)
Where q is a simple integer.
The thing is I need to round the right side of the equation (let's call it expression) as follows:
if(expression < 75) {
expression = 50;
} else if(expression < 125) {
expression = 100;
} else if(expression < 175) {
expression = 150;
} else if(expression < 225) {
expression = 200;
} else if(expression < 275) {
expression = 250;
} else {
expression = 300;
}
So I need to round the expression
(50x + 100y + 150z + 200k + 250p + 300v) / (x + y + z + k + p + v)
So that it gets one of the following values:
{50, 100, 150, 200, 250, 300}
Let's review 2 cases:
Case 1
q = 180 and expression = 176.
Although the condition 180 >= 176 is true, after rounding up 176 to 200 the tested condition should be 180 >= 200 which is false.
So for q = 180 and expression = 176 I would like the condition to return false.
Case 2
q = 210 and expression = 218.
Although the condition 210 >= 218 is false, after rounding down 218 to 200 the tested condition should be 210 >= 200 which is true.
So for q = 210 and expression = 218 I would like the condition to return true.
I got a great answer here for resolving this challenge over a linear expression but now I need to resolve it for a non-linear expression.
Any suggestions?
Let's rephrase
you have an integer variable e with a value between 0 and 300.
You want to round it to the nearest multiple of 50
if you do:
(e div 50) * 50
you will get the max multiple of 50 less or equal to e
(70 / 50) * 50 -> 50
(99 / 50) * 50 -> 50
(102 / 50) * 50 -> 100
To get a round to nearest, you need to add 25 to e before the division
((e + 25) div 50) * 50
Which will do the correct rounding
((70 + 25) / 50) * 50 -> 50
((99 + 25) / 50) * 50 -> 100
((102 + 25) / 50) * 50 -> 100
with the correct or-tools CP-SAT python code:
numerator = model.NewIntVar(...)
model.Add(numerator == 50x + 100y + 150z + 200k + 250p + 300v)
denom = model.NewIntVar(...)
model.Add(denom == 50x + 100y + 150z + 200k + 250p + 300v)
e = model.NewIntVar(0, 300, 'e')
model.AddDivisionEquality(e, numerator, denom)
shifted_e = model.NewIntVar(25, 325, 'shifted_e')
model.Add(shifted_e == e + 25)
multiple_of_fifty = model.NewIntVar(0, 6, 'multiple_of_fifty')
model.AddDivisionEquality(multiple_of_fifty, shifted_e, 50)
result = model.NewIntVar(0, 300, 'result')
model.Add(result = multiple_of_fifty * 50)
if a and b are positive then
a div b >= q
is equivalent to
a >= q * b
now, your example does not specify how to round (nearest or down)
if you want to round down
q * (x + y + z + k + p + v) <= (50x + 100y + 150z + 200k + 250p + 300v)
If you want to round to nearest, you need to add q / 2 in the right place
q * (x + y + z + k + p + v) <= (50x + 100y + 150z + 200k + 250p + 300v + q / 2)
Now, if you want the other direction
a div b <= q
is equivalent to
a <= q * b + q - 1
The rest of the transformation is the same.

algorithm to deal with series of values

With a series with a START, INCREMENT, and MAX:
START = 100
INCREMENT = 30
MAX = 315
e.g. 100, 130, 160, 190, 220, 250, 280, 310
Given an arbitrary number X return:
the values remaining in the series where the first value is >= X
the offset Y (catch up amount needed to get from X to first value of the series).
Example
In:
START = 100
INCREMENT = 30
MAX = 315
X = 210
Out:
Y = 10
S = 220, 250, 280, 310
UPDATE -- From MBo answer:
float max = 315.0;
float inc = 30.0;
float start = 100.0;
float x = 210.0;
float k0 = ceil( (x-start) / inc) ;
float k1 = floor( (max - start) / inc) ;
for (int i=k0; i<=k1; i++)
{
NSLog(#" output: %d: %f", i, start + i * inc);
}
output: 4: 220.000000
output: 5: 250.000000
output: 6: 280.000000
output: 7: 310.000000
MBo integer approach will be nicer.
School math:
Start + k0 * Inc >= X
k0 * Inc >= X - Start
k0 >= (X - Start) / Inc
Programming math:
k0 = Ceil(1.0 * (X - Start) / Inc)
k1 = Floor(1.0 * (Max - Start) / Inc)
for i = k0 to k1 (including both ends)
output Start + i * Inc
Integer math:
k0 = (X - Start + Inc - 1) / Inc //such integer division makes ceiling
k1 = (Max - Start) / Inc //integer division makes flooring
for i = k0 to k1 (including both ends)
output Start + i * Inc
Example:
START = 100
INCREMENT = 30
MAX = 315
X = 210
k0 = Ceil((210 - 100) / 30) = Ceil(3.7) = 4
k1 = Floor((315 - 100) / 30) = Floor(7.2) = 7
first 100 + 4 * 30 = 220
last 100 + 7 * 30 = 310
Solve the inequation
X <= S + K.I <= M
This is equivalent to
K0 = Ceil((X - S) / I) <= K <= Floor((M - S) / I) = K1
and
Y = X - (S + K0.I).
Note that it is possible to have K0 > K1, and there is no solution.

Project Euler #1 - Lasso

I've been working on Project Euler questions as part of learning how to code in Lasso and am wondering if my solution can be improved upon. Here is what I've got below for question #1 in Lasso 8 code, and it returns the correct answer:
var ('total' = 0);
loop(1000-1);
loop_count % 3 == 0 || loop_count % 5 == 0 ? $total += loop_count;
/loop;
output($total);
My question: is there a better or faster way to code this? Thanks!
Actually Chris it looks like my L9 code answer was almost exactly the same. However what I had to do to time is was wrap it in a loop to time it 1000 times.
Lasso 9 can do Microseconds, whereas versions prior can only time in milliseconds.
Below are 3 ways - the first is yours, then my two versions.
define br => '<br>'
local(start_time = micros)
loop(1000)=>{
var ('total' = 0);
loop(1000-1);
loop_count % 3 == 0 || loop_count % 5 == 0 ? $total += loop_count;
/loop;
$total;
}
'Avg (L8 code in 9): '+(micros - #start_time)/1000+' micros'
br
br
local(start_time = micros)
loop(1000)=>{
local(sum = 0)
loop(999)=>{ loop_count % 3 == 0 || loop_count % 5 == 0 ? #sum += loop_count }
#sum
}
'Avg (incremental improvement): '+(micros - #start_time)/1000+' micros'
br
br
local(start_time = micros)
loop(1000)=>{
local(sum = 0)
loop(999)=>{ not (loop_count % 3) || not(loop_count % 5) ? #sum += loop_count }
#sum
}
'Avg using boolean not: '+(micros - #start_time)/1000+' micros'
The output is:
Avg (L8 code in 9): 637 micros
Avg (incremental improvement): 595 micros
Avg using boolean not: 596 micros
Note that I didn't use "output" as it's redundant in many situations in 8 and completely redundant 9 :)
There is a fun story about how Gauss once summed numbers, which involves a strategy which can help to avoid the loop.
local('p' = 3);
local('q' = 5);
local('n' = 1000);
local('x' = integer);
local('before');
local('after');
#before = micros
loop(1000) => {
/* In the tradition of Gauss */
local('n2' = #n - 1)
local('pq' = #p * #q)
local('p2' = #n2 / #p)
local('q2' = #n2 / #q)
local('pq2' = #n2 / #pq)
local('p3' = (#p2 + 1) * (#p2 / 2) + (#p2 % 2 ? #p2 / 2 + 1 | 0))
local('q3' = (#q2 + 1) * (#q2 / 2) + (#q2 % 2 ? #q2 / 2 + 1 | 0))
local('pq3' = (#pq2 + 1) * (#pq2 / 2) + (#pq2 % 2 ? #pq2 / 2 + 1 | 0))
#x = #p * #p3 + #q * #q3 - #pq * #pq3
}
#after = micros
'Answer: ' + #x + '<br/>\n'
'Average time: ' + ((#after - #before) / 1000) + '<br/>\n'
/* Different numbers */
#p = 7
#q = 11
#before = micros
loop(1000) => {
/* In the tradition of Gauss */
local('n2' = #n - 1)
local('pq' = #p * #q)
local('p2' = #n2 / #p)
local('q2' = #n2 / #q)
local('pq2' = #n2 / #pq)
local('p3' = (#p2 + 1) * (#p2 / 2) + (#p2 % 2 ? #p2 / 2 + 1 | 0))
local('q3' = (#q2 + 1) * (#q2 / 2) + (#q2 % 2 ? #q2 / 2 + 1 | 0))
local('pq3' = (#pq2 + 1) * (#pq2 / 2) + (#pq2 % 2 ? #pq2 / 2 + 1 | 0))
#x = #p * #p3 + #q * #q3 - #pq * #pq3
}
#after = micros
'Answer: ' + #x + '<br/>\n'
'Average time: ' + ((#after - #before) / 1000) + '<br/>\n'
The output is:
Answer: 233168<br/>
Average time: 3<br/>
Answer: 110110<br/>
Average time: 2<br/>
Although the first time I ran it, that first average time was 18 instead of 3. Maybe Lasso is doing something smart for subsequent runs, or maybe it was just bad luck.
n = input number
x = (n-1)/3 = count of 3 divisible numbers.*
sum3 = (3*x*(x+1)) / 2 = sum of those numbers.**
y = (n-1)/5 = count of 5 divisible numbers.
sum5 = (5*y*(y+1)) / 2 = sum of those numbers.
half_Ans = sum3 + sum5
but 15, 30, 45... count twice (in both sum3 & sum5).
so remove it one time, so only they count once.
z = (n-1)/15 = count of 15 divisible numbers.
sum15 = (15*z*(z+1)) / 2 = sum of those numbers.
Answer = half_Ans - sum15
* => (n-1)/3 gives count of 3 divisible numbers.
if n = 100 we need to count of (3, 6, 9, ..., 99)
3 is 1st, 6 is 2nd, .... so on 99 is 33rd
so total count of those number is gain by last number / 3
last number is near to our input n (specifically less than input n)
if n = 99 we must not count 99, because statement is "find the sum of all the multiples of 3 or 5 below n".
so w/o subtract 1 last unwanted number also count, if n is divisible by 3.
** => (3*x*(x+1)) / 2 gives sum of those numbers
if n = 100 sum id 3 + 6 + 9 + ... + 99
all component are multiple of 3.
so 3 + 6 + 9 + ... + 99 = 3*(1 + 2 + 3 + ... + 33)
sum of 1 to m is (m*(m+1)) / 2
so 3 + 6 + 9 + ... + 99 = (3*33*(33+1)) / 2
here m for 1 to m is last number or total number of that sequence
or length of sequence that's why we find count of divisible numbers.