Modelling if-then-else-logic in MILP/MIP - optimization

I would like to model the following for a mixed-integer linear programming problem:
Let y be a binary and x1 and x2 be continuous variables, whereas k1 is an invariant parameter.
if y == 1 then:
x2 = k1*x1
else (y == 0):
x2 = 0
First idea that comes to mind is to do something like:
x2 >= k1*x1 - M*(1-y)
x2 <= k1*x1 - M*(1-y)
But here M would have to be k1*x1 and is therefore not an invariant parameter anymore. Does anyone have a better idea. Thank you!

Per your problem :
y : binary_variable
x1 : continous_variable
x2 : continous_variable
Please see equations below:
x2 <= u*y
x2 <= k1*x1
x2 >= k1*x1 − u*(1 − y)
x2 >= 0
u is the upper bound on k1*x1
0 <= k1*x1 <= u
you don't require a big M over here.
when y == 1 => x2 == k1*x1
when y == 0 => x2 == 0

Related

Simulate data for repeated binary measures

I can generate a binary variable y as follows:
clear
set more off
gen y =.
replace y = rbinomial(1, .5)
How can I generate n variables y_1, y_2, ..., y_n with a correlation of rho?
This is #pjs's solution in Stata for generating pairs of variables:
clear
set obs 100
set seed 12345
generate x = rbinomial(1, 0.7)
generate y = rbinomial(1, 0.7 + 0.2 * (1 - 0.7)) if x == 1
replace y = rbinomial(1, 0.7 * (1 - 0.2)) if x != 1
summarize x y
Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
x | 100 .72 .4512609 0 1
y | 100 .67 .4725816 0 1
correlate x y
(obs=100)
| x y
-------------+------------------
x | 1.0000
y | 0.1781 1.0000
And a simulation:
set seed 12345
tempname sim1
tempfile mcresults
postfile `sim1' mu_x mu_y rho using `mcresults', replace
forvalues i = 1 / 100000 {
quietly {
clear
set obs 100
generate x = rbinomial(1, 0.7)
generate y = rbinomial(1, 0.7 + 0.2 * (1 - 0.7)) if x == 1
replace y = rbinomial(1, 0.7 * (1 - 0.2)) if x != 1
summarize x, meanonly
scalar mean_x = r(mean)
summarize y, meanonly
scalar mean_y = r(mean)
corr x y
scalar rho = r(rho)
post `sim1' (mean_x) (mean_y) (rho)
}
}
postclose `sim1'
use `mcresults', clear
summarize *
Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
mu_x | 100,000 .7000379 .0459078 .47 .89
mu_y | 100,000 .6999094 .0456385 .49 .88
rho | 100,000 .1993097 .1042207 -.2578483 .6294388
Note that in this example I use p = 0.7 and rho = 0.2 instead.
This is #pjs's solution in Stata for generating a time-series:
clear
set seed 12345
set obs 1
local p = 0.7
local rho = 0.5
generate y = runiform()
if y <= `p' replace y = 1
else replace y = 0
forvalues i = 1 / 99999 {
set obs `= _N + 1'
local rnd = runiform()
if y[`i'] == 1 {
if `rnd' <= `p' + `rho' * (1 - `p') replace y = 1 in `= `i' + 1'
else replace y = 0 in `= `i' + 1'
}
else {
if `rnd' <= `p' * (1 - `rho') replace y = 1 in `= `i' + 1'
else replace y = 0 in `= `i' + 1'
}
}
Results:
summarize y
Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
y | 100,000 .70078 .4579186 0 1
generate id = _n
tsset id
corrgram y, lags(5)
-1 0 1 -1 0 1
LAG AC PAC Q Prob>Q [Autocorrelation] [Partial Autocor]
-------------------------------------------------------------------------------
1 0.5036 0.5036 25366 0.0000 |---- |----
2 0.2567 0.0041 31955 0.0000 |-- |
3 0.1273 -0.0047 33576 0.0000 |- |
4 0.0572 -0.0080 33903 0.0000 | |
5 0.0277 0.0032 33980 0.0000 | |
Correlation is a pairwise measure, so I'm assuming that when you talk about binary (Bernoulli) values Y1,...,Yn having a correlation of rho you're viewing them as a time series Yi: i = 1,...,n, of Bernoulli values having a common mean p, variance p*(1-p), and a lag 1 correlation of rho.
I was able to work it out using the definition of correlation and conditional probability. Given it was a bunch of tedious algebra and stackoverflow doesn't do math gracefully, I'm jumping straight to the result, expressed in pseudocode:
if Y[i] == 1:
generate Y[i+1] as Bernoulli(p + rho * (1 - p))
else:
generate Y[i+1] as Bernoulli(p * (1 - rho))
As a sanity check you can see that if rho = 0 it just generates Bernoulli(p)'s, regardless of the prior value. As you already noted in your question, Bernoulli RVs are binomials with n = 1.
This works for all 0 <= rho, p <= 1. For negative correlations, there are constraints on the relative magnitudes of p and rho so that the parameters of the Bernoullis are always between 0 and 1.
You can analytically check the conditional probabilities to confirm correctness. I don't use Stata, but I tested this pretty thoroughly in the JMP statistical software and it works like a charm.
IMPLEMENTATION (Python)
import random
def Bernoulli(p):
return 1 if random.random() <= p else 0 # yields 1 w/ prob p, 0 otherwise
N = 100000
p = 0.7
rho = 0.5
last_y = Bernoulli(p)
for _ in range(N):
if last_y == 1:
last_y = Bernoulli(p + rho * (1 - p))
else:
last_y = Bernoulli(p * (1 - rho))
print(last_y)
I ran this and redirected the results to a file, then imported the file into JMP. Analyzing it as a time series produced:
The sample mean was 0.69834, with a standard deviation of 0.4589785 [upper right of the figure]. The lag-1 estimates for autocorrelation and partial correlation are 0.5011 [bottom left and right, respectively]. These estimated values are all excellent matches to a Bernoulli(0.7) with rho = 0.5, as specified in the demo program.
If the goal is instead to produce (X,Y) pairs with the specified correlation, revise the loop to:
for _ in range(N):
x = Bernoulli(p)
if x == 1:
y = Bernoulli(p + rho * (1 - p))
else:
y = Bernoulli(p * (1 - rho))
print(x, y)

Axiomatic Semantics - How to calculate a weakest precondition

Here is example:
x = y + 1;
y = y - 2;
{y < 3}
What is weakest precondition of this example?
I think maybe y < 3 is an answer.
If not, can you tell me why, in detail?
Here is my first mistaken attempt at an answer based on a quick read of Predicate transformer semantics
WP( x := y + 1; y := y - 2, y < 3 ) # Initial problem
= WP( x := y + 1, WP( y := y - 2, y < 3 ) ) # Sequence rule
= WP( x := y + 1, y < 5 ) # Assignment rule
= WP( x - 1 = y, y < 5 ) # solve for y <--- this is wrong!
= WP( x - 1 < 5 ) # Assignment rule
= x < 6 # solve for x
However as pointed out by Kris since x := y + 1 is an assignment to x which doesn't affect y the weakest precondition for y should just be y < 5 so the correct answer should be
WP( x := y + 1; y := y - 2, y < 3 ) # Initial problem
= WP( x := y + 1, WP( y := y - 2, y < 3 ) ) # Sequence rule
= WP( x := y + 1, y < 5 ) # Assignment rule
= y < 5
Thanks also to philipxy for identifying errors in my syntax especially := vs = since that made it easier to mistake assignments for equations which was part of my initial confusion.

Minimum of a variable and a constant in PULP python integer programming

I am stuck with a problem in Integer Programming constraint using PULP in python. I have 2 variables x1, x2 and a constant y. How do i write a constraint on x1 = min(x2 ,y1).
I have written below two condition:
x1 < y1;
x1 < x2
But it is giving me x1 = 0 for my problem.
It should take one of the values from x2 and y1
Thanks in advance. Will really appreciate your help.
Code used:
*import pandas as pd
from pulp import *
data = pd.read_csv("Test.csv")
limit = LpVariable("limit",0, 1000, cat='Integer')
sales = LpVariable.dicts("Sales", (i for i in data.index), lowBound=0, cat="Integer")
####### Defining the Problem
prob = pulp.LpProblem("Profit", pulp.LpMaximize)
prob += pulp.lpSum((1-data.loc[i,'Prize']) * sales[i] for i in data.index)
####### Constraints
for idx in data.index:
max_sales = data.loc[idx, 'Sales'] + data.loc[idx, 'Rejec']
prob += sales[idx] <= max_sales
prob += sales[idx] <= limit
###### Getting the output
prob.solve()
for v in prob.variables():
print v.name,v.varValue
print value(prob.objective)
Data Used (try.csv)
enter image description here

How to prove image equality for functions: x = y -> f x = f y in Coq?

Intuitively, I know that if x = y then f x = f y, for any function f. But I don't know how to prove this in Coq. What I have so far is:
Theorem eq_img: forall {X:Type} (f: X->X) (x y :X), x = y -> f x = f y.
Proof. intros X f x y eq1.
and the state is:
1 subgoals
X : Type
f : X -> X
x : X
y : X
eq1 : x = y
______________________________________(1/1)
f x = f y
Any pointers on how should I proceed?
Thanks.
I figured it out. Just needed to use rewrite to eliminate x or y, then it's reflexivity.
Theorem eq_img: forall {X:Type} (f: X->X) (x y :X), x = y -> f x = f y.
Proof. intros X f x y eq1. rewrite <- eq1. reflexivity. Qed.

NLopt error in Julia and Ipopt alternative

I have the following simple problem that I want to solve with NLopt:
using JuMP
using NLopt
"""
min_x = x1 * x4* (x1 + x2 + x3) + x3
s.t.
x1 * x2 * x3 * x4 >= 25
x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40
1 <= x1,x2,x3,x4 <= 5
starting values: vec(x) = (x1 = 1, x2 = 5, x3 = 5, x4 = 1)
"""
tic()
m = Model(solver=NLoptSolver(algorithm=:LD_MMA))
#defVar(m, 1 <= x1 <= 5)
#defVar(m, 1 <= x2 <= 5)
#defVar(m, 1 <= x3 <= 5)
#defVar(m, 1 <= x4 <= 5)
#setNLObjective(m, Min, x1 * x4 * (x1 + x2 + x3) + x3)
#addNLConstraint(m, x1^2 + x2^2 + x3^2 + x4^2 == 40)
#addNLConstraint(m, x1 * x2 * x3 * x4 >= 25)
setValue(x1, 1)
setValue(x2, 5)
setValue(x3, 5)
setValue(x4, 1)
status = solve(m)
println("got ", getObjectiveValue(m), " at ", [getValue(x1),getValue(x2), getValue(x3), getValue(x4)])
toc()
However I get an argument error. Is there any way to make this work with NLopt and if not how this code can change so as to use it with the other free optimizers that can be installed in Julia (maybe Ipopt but not Gurobi)?
Well, I was unable to solve the problem using NLopt, but instead I managed to solve it with Ipopt.
The solution is simple for using Ipopt. Firstly you have to download Ipopt (I used the Windows version for now and I will also try in Linux) from this site and put it in the path (if you put it in the path and go to the command line and type ipopt it must show no error-it will actually show ipopt options). Just go at the very end to find the newest version.
Then I sliglty modified the code that I provided before to account for Ipopt in this way:
using JuMP
using Ipopt
"""
The problem that I want to solve has 4 variables and 6 constraints.
It is the following:
min_x = x1x4(x1+x2+x3) + x3
s.t.
x1*x2*x3*x4 >= 25
x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40
1 <= x1,x2,x3,x4 <= 5
starting values: x0 = (x1 = 1, x2 = 5, x3 = 5, x4 = 1)
"""
tic()
m = Model(solver=IpoptSolver())
#defVar(m, 1 <= x1 <= 5)
#defVar(m, 1 <= x2 <= 5)
#defVar(m, 1 <= x3 <= 5)
#defVar(m, 1 <= x4 <= 5)
#setNLObjective(m, Min, x1 * x4 * (x1 + x2 + x3) + x3)
#addNLConstraint(m, x1^2 + x2^2 + x3^2 + x4^2 == 40)
#addNLConstraint(m, x1 * x2 * x3 * x4 >= 25)
setValue(x1, 1)
setValue(x2, 5)
setValue(x3, 5)
setValue(x4, 1)
status = solve(m)
println("got ", getObjectiveValue(m), " at ", [getValue(x1),getValue(x2),
getValue(x3), getValue(x4)])
toc()
More information about the right name of the solvers etc. can be found here: https://jump.readthedocs.org/en/latest/installation.html#getting-solvers