I know there is many similar problems on this site, but unfortunately I was not able to fix my own with the existing answer.. I hope you don't mind to help me.
I have a code and am trying to append values to a list while iterating through the code. However, something goes wrong in the process and I end up with value 0.
I am not very good at debugging yet so I can't find the problem.
I made a simpler version of the code with less variables below:
`import math
from pylab import *
import numpy as np
#---------------------------INITIALIZATION-----------------------
#initializing the parameters of the model
Dt = 1
time_step = 50
#initializing the connection weights
w1 = 1
#initializing parameter values for the alogistic function
steepness_SS_a=1
speed_SS_a=1
threshold_SS_a=1
#--------------------THE FUNCTIONS---------------------------
def initialize():
global t, timesteps, WS_a, SS_a, new_WS_a, new_SS_a
#initialize model states
WS_a=1
SS_a=0
# initialize lists to update all states
new_SS_a=np.array([SS_a])
#initializing time list
t=0.
timesteps=[t]
def observe():
global t, timesteps, WS_a, SS_a, new_WS_a, new_SS_a
np.append(SS_a, new_SS_a)
timesteps.append(t)
def update():
global t, timesteps, WS_a, SS_a, new_WS_a, new_SS_a
# for each state activation value, write how to update it in the form of new_WS(a)=function(WS(a))
SS_a = SS_a + speed_SS_a * (((1/(1+math.exp(-steepness_SS_a * (w1 * WS_a - threshold_SS_a))))-(1/(1+math.exp(steepness_SS_a *threshold_SS_a))))* (1+math.exp(-steepness_SS_a*threshold_SS_a))-SS_a)
# for each state activation value now move the state value to new value
SS_a=new_SS_a
#updating the timestep
t = t + Dt
#--------------------THE PROGRAM-----------------
initialize()
while t<30.:
update()
observe()
#--------------------PLOTTING--------------------
print SS_a
plot(new_SS_a)
show()`
how about this:
import math
import numpy as np
from pylab import plot, show
def model():
Dt = 1
time_step = 50
#initializing the connection weights
w1 = 1
#initializing parameter values for the alogistic function
steepness_SS_a=1
speed_SS_a=1
threshold_SS_a=1
#initialize model states
WS_a=1
SS_a=0
# initialize lists to update all states
new_SS_a=np.array([SS_a])
#initializing time list
t=0.0
timesteps=[t]
while t<30.0:
## update()
# for each state activation value, write how to update it in the form of new_WS(a)=function(WS(a))
new = SS_a + speed_SS_a * (
(
(1/(1+math.exp(-steepness_SS_a * (w1 * WS_a - threshold_SS_a))))
-
(1/(1+math.exp(steepness_SS_a *threshold_SS_a)))
)
*
(1+math.exp(-steepness_SS_a*threshold_SS_a))
-
SS_a
)
new_SS_a = np.append(new_SS_a,new)
# for each state activation value now move the state value to new value
SS_a=new
#updating the timestep
t = t + Dt
##observe()
#np.append(SS_a, new_SS_a)
timesteps.append(t)
print( SS_a )
print( new_SS_a )
print( timesteps )
plot(new_SS_a)
show()
model()
the mayor change is in SS_a = SS_a + speed_SS_a *... first I save that value like new = SS_a + speed_SS_a *... then I add that value to new_SS_a with new_SS_a = np.append(new_SS_a,new) (you need to catch the result of this, otherwise you lose it) and override the old one in SS_a=new
The other thing is that I put all together because the use of globals in this fashion is a bad practice, global should be used as constants and don't be modify, if you need to change it in base to a function result, then make that function return that value and then make the change to the global constant. Also import * is another bad practice because pollute your namespace with unneeded stuff and in some cases that extra stuff can override without your knowledge some other that you need, and is worse is you use multiple of those because make the debugging harder by hiding from were it come each stuff forcing you to make extra lookup to figuring which stuff belong to each library if you don't know or don't remember, so always use explicit imports
Related
This paper describes Pyomo's Differential and Algebraic Equations framework. It also mentions multi-stage problems; however, it does not show a complete example of such a problem. Does such an example exist somewhere?
The following demonstrates a complete minimum working example of a multi-stage optimization problem using Pyomo's DAE system:
#!/usr/bin/env python3
#http://www.gpops2.com/Examples/OrbitRaising.html
from pyomo.environ import *
from pyomo.dae import *
from pyomo.opt import SolverStatus, TerminationCondition
import random
import matplotlib.pyplot as plt
T = 10 #Maximum time for each stage of the model
STAGES = 3 #Number of stages
m = ConcreteModel() #Model
m.t = ContinuousSet(bounds=(0,T)) #Time variable
m.stages = RangeSet(0, STAGES) #Stages in the range [0,STAGES]. Can be thought of as an integer-valued set
m.a = Var(m.stages, m.t) #State variable defined for all stages and times
m.da = DerivativeVar(m.a, wrt=m.t) #First derivative of state variable with respect to time
m.u = Var(m.stages, m.t, bounds=(0,1)) #Control variable defined for all stages and times. Bounded to range [0,1]
#Setting the value of the derivative.
def eq_da(m,stage,t): #m argument supplied when function is called. `stage` and `t` are given values from m.stages and m.t (see below)
return m.da[stage,t] == m.u[stage,t] #Derivative is proportional to the control variable
m.eq_da = Constraint(m.stages, m.t, rule=eq_da) #Call constraint function eq_da for each unique value of m.stages and m.t
#We need to connect the different stages together...
def eq_stage_continuity(m,stage):
if stage==m.stages.last(): #The last stage doesn't connect to anything
return Constraint.Skip #So skip this constraint
else:
return m.a[stage,T]==m.a[stage+1,0] #Final time of each stage connects with the initial time of the following stage
m.eq_stage_continuity = Constraint(m.stages, rule=eq_stage_continuity)
#Boundary conditions
def _init(m):
yield m.a[0,0] == 0 #Initial value (at zeroth stage and zeroth time) of `a` is 0
yield ConstraintList.End
m.con_boundary = ConstraintList(rule=_init) #Repeatedly call `_init` until `ConstraintList.End` is returned
#Objective function: maximize `a` at the end of the final stage
m.obj = Objective(expr=m.a[STAGES,T], sense=maximize)
#Get a discretizer
discretizer = TransformationFactory('dae.collocation')
#Disrectize the model
#nfe (number of finite elements)
#ncp (number of collocation points within finite element)
discretizer.apply_to(m,nfe=30,ncp=6,scheme='LAGRANGE-RADAU')
#Get a solver
solver = SolverFactory('ipopt', keepfiles=True, log_file='/z/log', soln_file='/z/sol')
solver.options['max_iter'] = 100000
solver.options['print_level'] = 1
solver.options['linear_solver'] = 'ma27'
solver.options['halt_on_ampl_error'] = 'yes'
#Solve the model
results = solver.solve(m, tee=True)
print(results.solver.status)
print(results.solver.termination_condition)
#Retrieve the results in a pleasant format
r_t = [t for s in sorted(m.stages) for t in sorted(m.t)]
r_a = [value(m.a[s,t]) for s in sorted(m.stages) for t in sorted(m.t)]
r_u = [value(m.u[s,t]) for s in sorted(m.stages) for t in sorted(m.t)]
plt.plot(r_t, r_a, label="r_a")
plt.plot(r_t, r_u, label="r_u")
plt.legend()
plt.show()
Is there a way of changing the values of a constraint as the solver is running?
Basically, I have a constraint that depends on the value of a variable. The problem is that the constraint is evaluated based on the initial value of the variable, but isn't updated as the variable changes.
Here's a simple example:
from pyomo.environ import *
from pyomo.opt import SolverFactory
import numpy as np
# Setup
model = ConcreteModel()
model.A = Set(initialize = [0,1,2])
model.B = Set(initialize = [0,1,2])
model.x = Var(model.A, model.B, initialize=0)
# A constraint that I'd like to keep updating, based on the value of x
def changing_constraint_rule(model, a):
x_values = list((model.x[a, b].value for b in model.B))
if np.max(x_values) == 0:
return Constraint.Skip
else:
# Not really important what goes here, just as long as it updates the constraint list
if a == 1 : return sum(model.x[a,b] for b in model.B) == 0
else: return sum(model.x[a,b] for b in model.B) == 1
model.changing_constraint = Constraint(model.A, rule = changing_constraint_rule)
# Another constraint that changes the value of x
def bounding_constraint_rule(model, a):
return sum(model.x[a, b] for b in model.B) == 1
model.bounding_constraint = Constraint(
model.A,
rule = bounding_constraint_rule)
# Some objective function
def obj_rule(model):
return(sum(model.x[a,b] for a in model.A for b in model.B))
model.objective = Objective(rule=obj_rule)
# Results
opt = SolverFactory("glpk")
results = opt.solve(model)
results.write()
model.x.display()
If I run model.changing_constraint.pprint() I can see that no constraints have been made, since the initial value of the variable model.x was set to 0.
If it's not possible to change the constraint values while solving, how could I formulate this problem differently to achieve what I'm looking for? I've read this other post but couldn't figure it out from the instructions.
I am giving you the same answer in the other question by #Gabe:
Any if-logic you use inside of rules should not involve the values of
variables (unless it is based on the initial value of a variable, in
which case you would wrap the variable in value() wherever you use it
outside of the main expression that is returned).
for example:
model.x[a, b].value should be model.x[a, b].value()
But still this might not give you the solution what you are looking for.
I am just starting with Pyomo and I have a big problem.
I want to run an Abstract Model without using the terminal. I can do it with a concrete model but I have serious problems to do it in with the abstract one.
I just want to use F5 and run the code.
This ismy program:
import pyomo
from pyomo.environ import *
#
# Model
#
model = AbstractModel()
#Set: Indices
model.Unit = Set()
model.Block = Set()
model.DemBlock = Set()
#Parameters
model.EnergyBid = Param(model.Unit, model.Block)
model.PriceBid = Param(model.Unit, model.Block)
model.EnergyDem = Param(model.DemBlock)
model.PriceDem = Param(model.DemBlock)
model.Pmin = Param(model.Unit)
model.Pmax = Param(model.Unit)
#Variables definition
model.PD = Var(model.DemBlock, within=NonNegativeReals)
model.PG = Var(model.Unit,model.Block, within=NonNegativeReals)
#Binary variable
model.U = Var(model.Unit, within = Binary)
#Objective
def SocialWellfare(model):
SocialWellfare = sum([model.PriceDem[i]*model.PD[i] for i in model.DemBlock]) - sum([model.PriceBid[j,k]*model.PG[j,k] for j in model.Unit for k in model.Block ])
return SocialWellfare
model.SocialWellfare = Objective(rule=SocialWellfare, sense=maximize)
#Constraints
#Max and min Power generated
def PDmax_constraint(model,p):
return ((model.PD[p] - model.EnergyDem[p])) <= 0
model.PDmax = Constraint(model.DemBlock, rule=PDmax_constraint)
def PGmax_constraint(model,n,m):
return ((model.PG[n,m] - model.EnergyBid[n,m])) <= 0
model.PGmax = Constraint(model.Unit, model.Block,rule = PGmax_constraint)
def Power_constraintDW(model,i):
return ((sum(model.PG[i,k] for k in model.Block))-(model.Pmin[i] * model.U[i]) ) >= 0
model.LimDemandDw = Constraint(model.Unit, rule=Power_constraintDW)
def Power_constraintUP(model,i):
return ((sum(model.PG[i,k] for k in model.Block) - (model.Pmax[i])*model.U[i])) <= 0
model.LimDemandaUp = Constraint(model.Unit, rule=Power_constraintUP)
def PowerBalance_constraint(model):
return (sum(model.PD[i] for i in model.DemBlock) - sum(model.PG[j,k] for j in model.Unit for k in model.Block)) == 0
model.PowBalance = Constraint(rule = PowerBalance_constraint)
model.pprint()
instance = model.create('datos_transporte.dat')
## Create the ipopt solver plugin using the ASL interface
solver = 'ipopt'
solver_io = 'nl'
opt = SolverFactory(solver,solver_io=solver_io)
results = opt.solve(instance)
results.write()
Any help with the last part??
Thanks anyway,
I think your example is actually working. Starting in Pyomo 4.1, the solution returned from the solver is stored directly into the instance that was solved, and is not returned in the solver results object. This change was made because generating the representation of the solution in the results object was rather expensive and was not easily parsed by people. Working with the model instance directly is more natural.
It is unfortunate that the results object reports the number of solutions: 0, although this is technically correct: the results object holds no solutions ... but the Solver section should indicate that a solution was returned and stored into the model instance.
If you want to see the result returned by the solver, you can print out the current status of the model using:
instance.display()
after the call to solve(). That will report the current Var values that were returned from the solver. You will want to pay attention to the stale column:
False indicates the value is not "stale" ... that is, it was either set by the user (before the call to solve()), or it was returned from the solver (after the call to solve()).
True indicates the solver did not return a value for that variable. This is usually because the variable was not referenced by the objective or any enabled constraints, so Pyomo never sent the variable to the solver.
[Note: display() serves a slightly different role than pprint(): pprint() outputs the model structure, whereas display() outputs the model state. So, for example, where pprint() will output the constraint expressions, display() will output the numerical value of the expression (using the current variable/param values).]
Edited to expand the discussion of display() & pprint()
I have run genetic algorithm model on antimicrobacterial resistance (amr) but it turns out an error like this :amr() takes exactly 3 arguments (2 given). Hopefully someone can help me to trace the error as Im desperately need to solve this in two days time. Thank you. My code is embedded below :
# First code to run
# imports relevant modules
# then defines functions for the Levenberg-Marquardt algorithm
import numpy as np
import matplotlib.pyplot as plt
#from scipy.optimize import leastsq
%matplotlib inline
time = np.arange(0.0, 3000.1,1.0)
pop = np.array([2,27,43,36,39,32,27,22,10,14,14,4,4,7,3,3,1])
def amr(pars,t):
beta,gamma,sigma_A,A,H,MIC_S,MIC_R,H,r = pars
E_S = 1-Emax*A**H/(MIC_S**H + A**H)
E_R = 1-Emax*A**H/(MIC_R**H + A**H)
derivs = [r*(1-(R+S)/Nmax)*E_S*S - sigma_S*S - beta*S*R/(R+S),
r*(1-gamma)*(1-(R+S)/Nmax)*E_R*R - sigma_R*R + beta*S*R/(R+S),
-sigma_A*A]
return derivs
def amr_resid(pars,t,data):
return amr(pars,t)-data
# code for the genetic algorithm. Relies on data set up above
# define a sum of squares function that we will use as fitness
def amr_ss(pars,t,data):
return sum(amr_resid(pars,t,data)**2)
# Parameter values
npars = 3
popsize = 60 # this needs to be a multiple of 3
elitism = popsize/3
# strength of mutation: the higher the number the larger the mutations can be, and vice versa
psigma = 0.08
ngenerations = 100
#set up initial population with parameters at log normal distribution around (1,1,1)
population = 10**np.random.normal(0,psigma,size=(popsize,npars))
newpop = population
# Matrices into which we put results
best = np.zeros(shape=(ngenerations,npars))
bestfitness = np.zeros(ngenerations)
fitnesses = np.zeros(shape=(popsize,ngenerations))
# Genetic algorithm code
for j in range(ngenerations):
# work out fitness
for i in range(popsize):
fitnesses[i,j] = amr_ss(population[i,:],time,pop)
# find the best and copy them into the next generation: we use the top 1/3rd
newpop[range(elitism),:]=population[np.argsort(fitnesses[:,j])[range(elitism)],:]
best[j,:]=newpop[0,:]
bestfitness[j]=np.sort(fitnesses[:,j])[0]
#create some mutants
for i in range(elitism):
# mutants have multiplicative change so that the change is a fixed proportion of the parameter value
newpop[elitism+i,:] = newpop[i,:] * 10**np.random.normal(0,psigma,npars)
# now create some recombinants: the gene values also mutate
for i in range(elitism):
parents = np.random.choice(elitism,2,replace=False)
# first gene from first parent
newpop[2*elitism+i,0]=newpop[parents[0],0] * 10**np.random.normal(0,psigma)
# second gene at random from first or second parent: depends on recombination position
if (np.random.rand()<0.5):
newpop[2*elitism+i,1]=newpop[parents[0],1] * 10**np.random.normal(0,psigma)
else:
newpop[2*elitism+i,1]=newpop[parents[1],1] * 10**np.random.normal(0,psigma)
# third gene from second parent
newpop[2*elitism+i,2]=newpop[parents[1],2] * 10**np.random.normal(0,psigma)
#update population
population = newpop
plt.boxplot(fitnesses) ;
I am currently coding an Multiple Gradient Descent algorithm, where I use kriged functions.
My problem is that I can't find how to obtain the gradient of the kriged function (I tried to use linearize but I don't know how to make it work).
from __future__ import print_function
from six import moves
from random import shuffle
import sys
import numpy as np
from numpy import linalg as LA
import math
from openmdao.braninkm import F, G, DF, DG
from openmdao.api import Group, Component,IndepVarComp
from openmdao.api import MetaModel
from openmdao.api import KrigingSurrogate, FloatKrigingSurrogate
def rand_lhc(b, k):
# Calculates a random Latin hypercube set of n points in k dimensions within [0,n-1]^k hypercube.
arr = np.zeros((2*b, k))
row = list(moves.xrange(-b, b))
for i in moves.xrange(k):
shuffle(row)
arr[:, i] = row
return arr/b*1.2
class TrigMM(Group):
''' FloatKriging gives responses as floats '''
def __init__(self):
super(TrigMM, self).__init__()
# Create meta_model for f_x as the response
F_mm = self.add("F_mm", MetaModel())
F_mm.add_param('X', val=np.array([0., 0.]))
F_mm.add_output('f_x:float', val=0., surrogate=FloatKrigingSurrogate())
# F_mm.add_output('df_x:float', val=0., surrogate=KrigingSurrogate().linearize)
#F_mm.linearize('X', 'f_x:float')
#F_mm.add_output('g_x:float', val=0., surrogate=FloatKrigingSurrogate())
print('init ok')
self.add('p1', IndepVarComp('X', val=np.array([0., 0.])))
self.connect('p1.X','F_mm.X')
# Create meta_model for f_x as the response
G_mm = self.add("G_mm", MetaModel())
G_mm.add_param('X', val=np.array([0., 0.]))
G_mm.add_output('g_x:float', val=0., surrogate=FloatKrigingSurrogate())
#G_mm.add_output('df_x:float', val=0., surrogate=KrigingSurrogate().linearize)
#G_mm.linearize('X', 'g_x:float')
self.add('p2', IndepVarComp('X', val=np.array([0., 0.])))
self.connect('p2.X','G_mm.X')
from openmdao.api import Problem
prob = Problem()
prob.root = TrigMM()
prob.setup()
u=4
v=3
#training avec latin hypercube
prob['F_mm.train:X'] = rand_lhc(20,2)
prob['G_mm.train:X'] = rand_lhc(20,2)
#prob['F_mm.train:X'] = rand_lhc(10,2)
#prob['G_mm.train:X'] = rand_lhc(10,2)
#prob['F_mm.linearize:X'] = rand_lhc(10,2)
#prob['G_mm.linearize:X'] = rand_lhc(10,2)
datF=[]
datG=[]
datDF=[]
datDG=[]
for i in range(len(prob['F_mm.train:X'])):
datF.append(F(np.array([prob['F_mm.train:X'][i]]),u))
#datG.append(G(np.array([prob['F_mm.train:X'][i]]),v))
data_trainF=np.fromiter(datF,np.float)
for i in range(len(prob['G_mm.train:X'])):
datG.append(G(np.array([prob['G_mm.train:X'][i]]),v))
data_trainG=np.fromiter(datG,np.float)
prob['F_mm.train:f_x:float'] = data_trainF
#prob['F_mm.train:g_x:float'] = data_trainG
prob['G_mm.train:g_x:float'] = data_trainG
Are you going to be writing a Multiple Gradient Descent driver? If so, then OpenMDAO calculates the gradient from a param to an output at the Problem level using the calc_gradient method.
If you take a look at the source code for the pyoptsparse driver:
https://github.com/OpenMDAO/OpenMDAO/blob/master/openmdao/drivers/pyoptsparse_driver.py
The _gradfunc method is a callback function that returns the gradient of the constraints and objectives with respect to the design variables. The Metamodel component has built-in analytic gradients for all (I think) of our surrogates, so you don't even have to declare any there.
If this isn't what you are trying to do, then I may need a little more information about your application.