OR Tools Constraint that requires equility of variables [ortools] - or-tools

I want create a linear solver model using OR-Tools. I have two numVars and one of my constraints is the equility of these two variables. But I could not find a way to set a constraint that takes a variable. I can do this with gurobi library. Below are the codes for both libraries. Is there a way to pass variables to both sides of a constraint such as xa==xb?
Thanks in advance.
Gurobi Code:
from gurobipy import Model, GRB
m = Model('rafinery')
xa = m.addVar(vtype=GRB.CONTINUOUS)
xb = m.addVar(vtype=GRB.CONTINUOUS)
# production constraint
m.addConstr(xa*400 + xb*300 >= 25000)
m.addConstr(xa*300 + xb*400 >= 27000)
m.addConstr(xa*200 + xb*500 >= 30000)
m.addConstr(xa>=0)
m.addConstr(xb>=0)
m.addConstr(xa==xb)
m.setObjective(xa * 20000 + xb * 25000, GRB.MINIMIZE)
m.update()
m.setObjective(xa + xb, GRB.MINIMIZE)
m.update()
m.optimize()
for v in m.getVars():
print(v.varName, v.x)
print("Cost:", m.objVal)
OR-Tools Code:
from ortools.linear_solver import pywraplp
solver = pywraplp.Solver('SolveSimpleSystem', pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
# Create Variables
xa = solver.NumVar(0, solver.infinity(),'xa')
xb = solver.NumVar(0, solver.infinity(),'xb')
# Create Constraints
# xa*400 + xb*300 >= 25000
high = solver.Constraint(25000, solver.infinity())
high.SetCoefficient(xa, 400)
high.SetCoefficient(xb, 300)
# xa*300 + xb*400 >= 27000
middle = solver.Constraint(27000, solver.infinity())
middle.SetCoefficient(xa,300)
middle.SetCoefficient(xb,400)
# xa*200 + xb*500 >= 30000
high = solver.Constraint(30000, solver.infinity())
high.SetCoefficient(xa, 200)
high.SetCoefficient(xb, 500)
# another constraint that factories work for same days
# ******************** get error here ****************
noidle = solver.Constraint(xa,xa)
noidle.SetCoefficient(xb,1)
# obj = minimize production cost which is
# xa * 20000 + xb * 25000
obj = solver.Objective()
obj.SetCoefficient(xa, 20000)
obj.SetCoefficient(xb, 25000)
obj.SetMinimization()
solver.Solve()
print("Rafinery Solution:")
print("Rafinery A work days:", xa.solution_value())
print("Rafinery B work days:", xb.solution_value())
print("Cost : ", solver.Objective().Value())

from ortools.linear_solver import pywraplp
solver = pywraplp.Solver('SolveSimpleSystem', pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
# Create Variables
xa = solver.NumVar(0, solver.infinity(),'xa')
xb = solver.NumVar(0, solver.infinity(),'xb')
# production constraint
solver.Add(xa*400 + xb*300 >= 25000)
solver.Add(xa*300 + xb*400 >= 27000)
solver.Add(xa*200 + xb*500 >= 30000)
solver.Add(xa>=0)
solver.Add(xb>=0)
solver.Add(xa==xb)
solver.Minimize(xa * 20000 + xb * 25000)
solver.Solve()
print("Rafinery Solution:")
print("Rafinery A work days:", xa.solution_value())
print("Rafinery B work days:", xb.solution_value())
print("Cost : ", solver.Objective().Value())

Related

How to convert from Pinescript version 2 to version 5

I have tried to convert the following from version 2 to version 5 without success. I have been getting various errors showing up. Also, the current converter on the Pine Script v5 User Manual doesn't go below Version 3. I would appreciate any help to do this. Much appreciated and thanks.
//#version=2
//Both fisher and macdl MTF
resCustom = input(title="Timeframe", type=resolution, defval="60" )
//--------macdl
src=close
shortLength = input(12, title="Fast Length")
longLength = input(26, title="Slow Length")
sigLength = input(9, title="Signal Length")
ma(s,l) => ema(s,l)
sema = ma( src, shortLength )
lema = ma( src, longLength )
i1 = sema + ma( src - sema, shortLength )
i2 = lema + ma( src - lema, longLength )
macdl = i1 - i2
macdl2 = security(tickerid, resCustom,macdl)
macd=sema-lema
//-------end
//---------fisher
len = input(34, minval=1, title="Fisher")
round_(val) => val > .99 ? .999 : val < -.99 ? -.999 : val
high_ = highest(hl2, len)
low_ = lowest(hl2, len)
value = round_(.66 * ((hl2 - low_) / max(high_ - low_, .001) - .5) + .67 * nz(value[1]))
fish1 = .5 * log((1 + value) / max(1 - value, .001)) + .5 * nz(fish1[1])
fish2 = security(tickerid, resCustom,fish1)
//------------end
sw1=iff(fish2<-6 and macdl2>macdl2[1],1,0)
sw2=iff(fish2>6 and macdl2<macdl2[1],-1,0)
final=sw1+sw2
swap=final==1 or final==-1?fuchsia:green
plot(fish2, color=swap, title="Fisher",style=histogram)
hline(0, color=orange)

ORTOOLS - CPSAT - Objective to minimize a value by intervals

I my model in ORTools CPSAT, I am computing a variable called salary_var (among others). I need to minimize an objective. Let’s call it « taxes ».
to compute the taxes, the formula is not linear but organised this way:
if salary_var below 10084, taxes corresponds to 0%
between 10085 and 25710, taxes corresponds to 11%
between 25711 and 73516, taxes corresponds to 30%
and 41% for above
For example, if salary_var is 30000 then, taxes are:
(25710-10085) * 0.11 + (30000-25711) * 0.3 = 1718 + 1286 = 3005
My question: how can I efficiently code my « taxes » objective?
Thanks for your help
Seb
This task looks rather strange, there is not much context and some parts of the task might touch some not-so-nice areas of finite-domain based solvers (large domains or scaling / divisions during solving).
Therefore: consider this as an idea / template!
Code
from ortools.sat.python import cp_model
# Data
INPUT = 30000
INPUT_UB = 1000000
TAX_A = 11
TAX_B = 30
TAX_C = 41
# Helpers
# new variable which is constrained to be equal to: given input-var MINUS constant
# can get negative / wrap-around
def aux_var_offset(model, var, offset):
aux_var = model.NewIntVar(-INPUT_UB, INPUT_UB, "")
model.Add(aux_var == var - offset)
return aux_var
# new variable which is equal to the given input-var IFF >= 0; else 0
def aux_var_nonnegative(model, var):
aux_var = model.NewIntVar(0, INPUT_UB, "")
model.AddMaxEquality(aux_var, [var, model.NewConstant(0)])
return aux_var
# Model
model = cp_model.CpModel()
# vars
salary_var = model.NewIntVar(0, INPUT_UB, "salary")
tax_component_a = model.NewIntVar(0, INPUT_UB, "tax_11")
tax_component_b = model.NewIntVar(0, INPUT_UB, "tax_30")
tax_component_c = model.NewIntVar(0, INPUT_UB, "tax_41")
# constraints
model.AddMinEquality(tax_component_a, [
aux_var_nonnegative(model, aux_var_offset(model, salary_var, 10085)),
model.NewConstant(25710 - 10085)])
model.AddMinEquality(tax_component_b, [
aux_var_nonnegative(model, aux_var_offset(model, salary_var, 25711)),
model.NewConstant(73516 - 25711)])
model.Add(tax_component_c == aux_var_nonnegative(model,
aux_var_offset(model, salary_var, 73516)))
tax_full_scaled = tax_component_a * TAX_A + tax_component_b * TAX_B + tax_component_c * TAX_C
# Demo
model.Add(salary_var == INPUT)
solver = cp_model.CpSolver()
status = solver.Solve(model)
print(list(map(lambda x: solver.Value(x), [tax_component_a, tax_component_b, tax_component_c, tax_full_scaled])))
Output
[15625, 4289, 0, 300545]
Remarks
As implemented:
uses scaled solving
produces scaled solution (300545)
no fiddling with non-integral / ratio / rounding stuff BUT large domains
Alternative:
Maybe something around AddDivisionEquality
Edit in regards to Laurents comments
In some scenarios, solving the scaled problem but being able to reason about the real unscaled values easier might make sense.
If i interpret the comment correctly, the following would be a demo (which i was not aware of and it's cool!):
Updated Demo Code (partial)
# Demo -> Attempt of demonstrating the objective-scaling suggestion
model.Add(salary_var >= 30000)
model.Add(salary_var <= 40000)
model.Minimize(salary_var)
model.Proto().objective.scaling_factor = 0.001 # DEFINE INVERSE SCALING
solver = cp_model.CpSolver()
solver.parameters.log_search_progress = True # SCALED BACK OBJECTIVE PROGRESS
status = solver.Solve(model)
print(list(map(lambda x: solver.Value(x), [tax_component_a, tax_component_b, tax_component_c, tax_full_scaled])))
print(solver.ObjectiveValue()) # SCALED BACK OBJECTIVE
Output (excerpt)
...
...
#1 0.00s best:30 next:[30,29.999] fixed_bools:0/1
#Done 0.00s
CpSolverResponse summary:
status: OPTIMAL
objective: 30
best_bound: 30
booleans: 1
conflicts: 0
branches: 1
propagations: 0
integer_propagations: 2
restarts: 1
lp_iterations: 0
walltime: 0.0039022
usertime: 0.0039023
deterministic_time: 8e-08
primal_integral: 1.91832e-07
[15625, 4289, 0, 300545]
30.0

Optimal dispatch of power generators

I want to write a matlab code that can optimally dispatch power generators to satisfy electric demand by considering profit too. I used below code that is in matlab website. https://ww2.mathworks.cn/help/optim/examples/optimal-dispatch-of-power-generators.html?requestedDomain=en
But in this code they are not considering the demand.
My target is , there are 20 power plants and I want to schedule this plants to satisfy demand. And the running power level can be any value in between the max and minimum power value of each power plant. High cost power plants should dispatch too.
name = 'generationcost.xlsx';
poolPrice = xlsread(name,'AD3:AD50'); % Revenue in dollars per MWh in interval
demand = xlsread(name,'AC3:AC52');
month = numel(demand);
e = xlsread(name,'W2:W4')'; %Cost for a unit of fuel
fuelPrice = repmat(e,1,1,2);
nPeriods = length(poolPrice);
nGens = 3;
genhigh = xlsread(name,'F2:F4');
genlow = xlsread(name,'Q2:Q4');
gen = [genlow(:),genhigh(:),]; %MW
fuel = [50,330;45,325;55,750]; % Fuel consumption for generator
startCost = [10000;10000;10000]; %Cost in dollars to start a generator after it has been off
y = optimvar('y',nPeriods,nGens,{'Low','High'},'Type','integer','LowerBound',0,'UpperBound',1);
z = optimvar('z',nPeriods,nGens,'Type','integer','LowerBound',0,'UpperBound',1);
powercons = y(:,:,'Low') + y(:,:,'High') <= 1;
yFuel = zeros(nPeriods,nGens,2);
yFuel(:,1,1) = fuel(1,1);
yFuel(:,1,2) = fuel(1,2);
yFuel(:,2,1) = fuel(2,1);
yFuel(:,2,2) = fuel(2,2);
yFuel(:,3,1) = fuel(3,1);
yFuel(:,3,2) = fuel(3,2);
fuelUsed = sum(reshape((sum(y.*yFuel)),[3 2])');
%fuelcons = fuelUsed <= totalFuel;
w = optimexpr(nPeriods,nGens);
idx = 1:(nPeriods-1);
w(idx,:) = y(idx+1,:,'Low') - y(idx,:,'Low') + y(idx+1,:,'High') -
y(idx,:,'High');
w(nPeriods,:) = y(1,:,'Low') - y(nPeriods,:,'Low') + y(1,:,'High') -
y(nPeriods,:,'High');
switchcons = w - z <= 0;
generatorlevel = zeros(size(yFuel));
generatorlevel(:,1,1) = gen(1,1);
generatorlevel(:,1,2) = gen(1,2);
generatorlevel(:,2,1) = gen(2,1);
generatorlevel(:,2,2) = gen(2,2);
generatorlevel(:,3,1) = gen(3,1);
generatorlevel(:,3,2) = gen(3,2);
revenue = optimexpr(size(y));
for ii = 1:nPeriods
revenue(ii,:,:) = poolPrice(ii)*y(ii,:,:).*generatorlevel(ii,:,:);
end
val = optimexpr(size(y));
demands = optimexpr(nPeriods,1);
id = 1:nPeriods;
val(id,:,:)= y(id,:,:).*generatorlevel(id,:,:);
demands(id,:)= sum(sum(val,3),2);
demandcons = demands-demand ;
fuelCost = sum(sum(fuelPrice.*sum(y.*yFuel)));
startingCost = z*startCost;
profit = sum(sum(sum(revenue))) - fuelCost - sum(startingCost);
dispatch = optimproblem('ObjectiveSense','maximize');
dispatch.Objective = profit;
dispatch.Constraints.powercons = powercons;
dispatch.Constraints.demandcons = demands - demand <= 0 ;
options = optimoptions('intlinprog','Display','final');
[dispatchsol,fval,exitflag,output] = solve(dispatch,'options',options);
subplot(5,1,1)
bar(dispatchsol.y(:,1,1)*gen(1,1)+dispatchsol.y(:,1,2)*gen(1,2),.5,'g')
xlim([.5,48.5])
ylabel('MW')
title('Generator 1 Optimal Schedule','FontWeight','bold')
subplot(5,1,2)
bar(dispatchsol.y(:,2,1)*gen(2,1)+dispatchsol.y(:,2,2)*gen(2,2),.5,'c')
title('Generator 2 Optimal Schedule','FontWeight','bold')
xlim([.5,48.5])
ylabel('MW')
subplot(5,1,3)
bar(dispatchsol.y(:,3,1)*gen(3,1)+dispatchsol.y(:,3,2)*gen(3,2),.5,'c')
title('Generator 3 Optimal Schedule','FontWeight','bold')
xlim([.5,48.5])
ylabel('MW')
subplot(5,1,4)
bar(demand,.5)
xlim([.5,48.5])
title('Daily Demand','FontWeight','bold')
xlabel('Period')
ylabel('MW')
starttimes = find(round(dispatchsol.z) == 1);
[theperiod,thegenerator] = ind2sub(size(dispatchsol.z),starttimes)
This code is not satisfying Demand. The output demand value is more lesser than the actual demand value. And also here only use 'High' or 'Low' power levels only. In between power values not using.

Implementing Adam in Pytorch

I’m trying to implement Adam by myself for a learning purpose.
Here is my Adam implementation:
class ADAMOptimizer(Optimizer):
"""
implements ADAM Algorithm, as a preceding step.
"""
def __init__(self, params, lr=1e-3, betas=(0.9, 0.99), eps=1e-8, weight_decay=0):
defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay)
super(ADAMOptimizer, self).__init__(params, defaults)
def step(self):
"""
Performs a single optimization step.
"""
loss = None
for group in self.param_groups:
#print(group.keys())
#print (self.param_groups[0]['params'][0].size()), First param (W) size: torch.Size([10, 784])
#print (self.param_groups[0]['params'][1].size()), Second param(b) size: torch.Size([10])
for p in group['params']:
grad = p.grad.data
state = self.state[p]
# State initialization
if len(state) == 0:
state['step'] = 0
# Momentum (Exponential MA of gradients)
state['exp_avg'] = torch.zeros_like(p.data)
#print(p.data.size())
# RMS Prop componenet. (Exponential MA of squared gradients). Denominator.
state['exp_avg_sq'] = torch.zeros_like(p.data)
exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq']
b1, b2 = group['betas']
state['step'] += 1
# L2 penalty. Gotta add to Gradient as well.
if group['weight_decay'] != 0:
grad = grad.add(group['weight_decay'], p.data)
# Momentum
exp_avg = torch.mul(exp_avg, b1) + (1 - b1)*grad
# RMS
exp_avg_sq = torch.mul(exp_avg_sq, b2) + (1-b2)*(grad*grad)
denom = exp_avg_sq.sqrt() + group['eps']
bias_correction1 = 1 / (1 - b1 ** state['step'])
bias_correction2 = 1 / (1 - b2 ** state['step'])
adapted_learning_rate = group['lr'] * bias_correction1 / math.sqrt(bias_correction2)
p.data = p.data - adapted_learning_rate * exp_avg / denom
if state['step'] % 10000 ==0:
print ("group:", group)
print("p: ",p)
print("p.data: ", p.data) # W = p.data
return loss
I think I implemented everything correct however the loss graph of my implementation is very spiky compared to that of torch.optim.Adam.
My ADAM implementation loss graph (below)
torch.optim.Adam loss graph (below)
If someone could tell me what I am doing wrong, I’ll be very grateful.
For the full code including data, graph (super easy to run): https://github.com/byorxyz/AMS_pytorch/blob/master/AdamFails_1dConvex.ipynb

programming a range of data : Matlab

I have this program, something related with statistic.
maximo = max(muestra);
minimo = min(muestra);
rango = maximo - minimo;
num_intervalo = round(1 + 3.322*log(length(muestra)));
amplitud = rango/num_intervalo;
rango_intervalo = [];
for i=1 : num_intervalo + 1
if i == 1
rango_intervalo(i: num_intervalo + 1) = minimo;
else
rango_intervalo(i: num_intervalo + 1) = rango_tabulado(i) + amplitud;
end
if i == num_intervalo + 1
rango_intervalo(i: num_intervalo + 1) = maximo;
end
end
rango_intervalo = rango_intervalo';
the intention is to create nine (or k intervals) intervals, where each interval has it ranges:
[1.580 - 2.587]
[2.587 - 3.594]
.
.
[9.636 - 10.650]
With code that I've programmed, it is resulting in 10 data not nine as per the intention.
Any idea, the improve this code?
Thanks.
How about:
intervals = linspace(minimo, maximo, num_intervalo + 1 );
intervals = [ intervals(1:end-1); intervals(2:end) ]';