How to call Python function in Pyomo - python

I have a python function which in turn has many other forton/c++ dlls calling to generate the output value. Now I want to call that function in Pyomo model as expression. Any help on that?
The example I have is:
def mult(a,b):
c = a * b
return(c)
model.a = Var(initialize=1)
model.y = Param(initialize = 6)
def add(model):
x = mult(value(model.a),3)
return(x)
model.value1 = Expression(rule=add)
modelinit_cond1 = Constraint(expr=(model.value1 == model.y))
opt = SolverFactory('ipopt');
results = opt.solve(model, tee=True)
results.write()
Expectation is; ipopt would try finding the value of model.a given that the constraint is satisfied.
Note: The code above is simpler in order simplify the explanation but the real problem on similar grounds.
Many Thanks for help in advance.

Related

How to fix attribute Error in Pyomo model python

I am trying to write a pyomo model in python3, but I am facing this error that I can't seem to figure out - 'list' object has no attribute 'is_expression_type'. Below is my pyomo model, any help would be appreciated.
R_avg_tolist = [[0.00043159478649482775,
0.00045388639592182584,
0.0006735271301199177,
0.00044026758948786,
0.0037176592984565836]]
Cov_list = [[5.884677519869241e-05,
5.756542207262417e-05,
6.017027849080026e-05,
6.180151597797322e-05,
-0.0005074353586106837],
[5.756542207262417e-05,
6.0380562653096757e-05,
6.613608499966434e-05,
6.737370769879904e-05,
-0.0005362752804115953],
[6.017027849080026e-05,
6.613608499966434e-05,
8.206495000024503e-05,
8.01694525889321e-05,
-0.0005958716888916681],
[6.180151597797322e-05,
6.737370769879904e-05,
8.01694525889321e-05,
0.00010129901491226823,
-0.000608829853150321],
[-0.0005074353586106837,
-0.0005362752804115953,
-0.0005958716888916681,
-0.000608829853150321,
0.007373689071617548]]
import pyomo.environ as pyo
# Optimization Problem
def create_model(rho,R_avg,Cov):
m = pyo.ConcreteModel()
init_x = {}
m.idx = pyo.Set(initialize=[0,1,2,3,4])
for i in m.idx:
init_x[i] = 0
m.x = pyo.Var(m.idx,initialize=init_x,bounds=(0,None))
def Obj_func(m):
b = []
mult_result = 0
for i in m.idx:
a = 0
for j in m.idx:
a+= m.x[j]*Cov[j][i]
b.append(a)
for i in m.idx:
mult_result += b[i]*m.x[i]
return mult_result
m.OBJ = pyo.Objective(rule=Obj_func)
def constraint1(m):
sum=0
for i in m.idx:
sum+=m.x[i]
return sum ==100
m.C1 = pyo.Constraint(rule=constraint1(m))
def constraint2(m):
sum=0
for i in m.idx:
sum += R_avg_tolist[i]*m.x[i]
return sum >=0.08
m.C2 = pyo.Constraint(rule=constraint2(m))
return m
When I run model using below code, I face the attribute error - 'list' object has no attribute 'is_expression_type'.
rho = 0.0008
model1 = create_model(rho,R_avg_tolist,Cov_list)
solver = SolverFactory('ipopt')
results = solver.solve(model1, tee = True)
Probably not what you want to hear, but your model has many syntax probs. It's obviously a course assignment... Do you have somebody (instructor/TA) to go over this with who can advise a bit?
You didn't include enough info about which line of code caused the issue, but there are several problem areas. I've posted many simple pyomo examples if you scan through some of them, you'll get some ideas, along with the documentation and whatever you have from your course notes....
A few pointers may help:
Do NOT overwrite keywords/functions by using them as variables. When you write:
sum = 0
sum ....
you are nuking the python function sum by making that name a variable and assigning it the value of 0. You should be using sum in several of your functions with verbiage like:
sum(m.X[i] for i in m.idx) # or similar
You seem to be confused on making valid pyomo expressions. That is the core job of pyomo ... to make expressions and fill the model. For example, in your constraint1, you can just make an expression (without a function) and add it to your model. You can do a 1-liner there because the constraint is not a "for each". You could:
m.C1 = pyo.Constraint(expr=sum(m.x[i] for x in m.idx) == 100)
In general, when you are starting:
Add 1 thing to your model, and then print the model:
model.pprint()
See if it looks right, if not, fix it. Then repeat!

Python scipy minimize "numpy.float64 object is not callable

I have been trying to get over this error for a while and can't quite find a way to fix it. I'm trying to minimize a function, but whenever I call it I get the error in the title. I've looked at several other posts and have tried several different tactics, but no dice. here's the snippet in question here:
def objective_func(a, x_sum,y_sum):
alpha_sum = np.sum(a)
alpha_dot_sum= np.sum(np.dot(a[i],a[j]) for i in range(len(a)) for j in range(len(a)))
return (1/2) * (x_sum*y_sum*alpha_dot_sum)-alpha_sum
def Dual_SVM(data,c,a):
inputs = []
for example in data:
inputs.append(example[0:5])
outputs = []
for example in data:
outputs.append(example[len(example)-1])
bound = [(0,c)]
cons_function = np.sum(a*outputs)
cons = ({'type':'eq','fun':cons_function})
# inputs = []
x_sum= np.sum(np.dot(inputs[i],inputs[j]) for i in range(len(inputs)) for j in range(len(inputs)))
y_sum= np.sum(np.dot(outputs[i],outputs[j]) for i in range(len(outputs)) for j in range(len(outputs)))
sol = minimize(objective_func,x0=a,args=(x_sum,y_sum,),method='SLSQP',constraints=cons,bounds=bound)
return sol
Any feedback on this would be greatly appreciated. I know that the first argument needs to be a function and not just a function call, but I feel like I'm following the proper syntax. Not sure what to do here.
Fixed it. The problem was that cons_function was returning as a float, and not a function. A lambda function in its place fixed the problem.

Solve Python Pulp without variables

I have a python pulp linear program which is minimizing costs. In the degenerate case where there are no ways to reduce costs I would like it to return the fixed cost. However pulp seems to add a __dummy variable in the case of no variables, which has a value of None. I have added a minimal working example below.
from pulp import *
model = LpProblem("Degenerate_Model",LpMinimize)
fixed_cost = 10
model += fixed_cost
print(model) #Prints MINIMIZE 10
model.solve()
print(model.objective) #prints 0*__dummy + 10
print(value(model.objective)) #returns None. Desired output is 10
My desired output in the above example would be to return 10. Any help is greatly appreciated
You're absolutely right. This happens because __dummy has a varValue of None, while you didn't expect it to be included at all. I would file a bug report to ask them to exclude dummy variables from LpAffineExpression.value() - since pulp.value(model.objective) is a shortcut for model.objective.value().
For now, I'd use the following workaround: model.objective.valueOrDefault().
You could declare the fixed cost as a variable with a fixed value.
>>> model = LpProblem("Degenerate_Model",LpMinimize)
>>> fixed_cost = LpVariable('fixed cost', lowBound=10, upBound=10)
>>> model += fixed_cost
>>> model.solve()
>>> print(value(model.objective))
10.0

couldn't pass `gurobi.GenExpr` into `model.setObjective`

from gurobipy import *
global_model = Model("_")
schedule = [global_model.addVar(name=x) for x in ["alpha", "beta"]]
maxtime = max_(schedule)
global_model.update()
global_model.setObjective(maxtime, GRB.MINIMIZE)
I just init a list of gurobi.Var (schedule) and I want to minimize the max value of them (maxtime). But it seems impossible to simply make maxtime the 1st arg for setObjective:
gurobipy.GurobiError: Unable to convert argument to an expression
How how do I fix it?
It's uncommon to create a list of gurobi variables. In general, better use Model.addVars() to get a gurobi tupledict of your variables. And as far as I remember correctly, you can use max_() only inside the Model.addConstr() and Model.addConstrs() methods.
To sum it up, here's a way to do it:
alpha = global_model.addVar(name="alpha")
beta = global_model.addVar(name="beta")
maxtime = global_model.addVar(name="maxtime")
global_model.update()
global_model.addConstr(maxtime == max_(alpha, beta))
global_model.setObjective(maxtime, sense=GRB.MINIMIZE)

Fenics help: Writing a list of data into Expression for nonlinear part in fenics?

I'm trying to solve a nonlinear problem in fenics. Instead of knowing the nonlinear function as an expression, I only know the values in the form of data.
In other words, if i am solving nabla(k(u).nabla(u)) = C, I do not know k(u) or cannot write it in terms of x[0] etc, I only know corresponding values of k for all values of u.
At the moment i have written some interpolating function and called it into 'k' which can project it to a function space, but it does not seem to work when i put it into the variational form and solve.
Below is some code to clarify the problem: I was using method of manufactured solutions where u=x^2 with k=1+u^2 as a test, where k_data = list of data for u=[0,(1+xmax^2)].
I've been told i can look into subclasses in Expression but i have no idea how to do this without knowing it in terms of x[0]. please help!
u = Function(V)
v = TestFunction(V)
u.interpolate(Expression("x[0]"))
k = interpolate_table(u,kappa_data)
plot(project(k,V))
C = Expression("-2.0-10.0*x[0]*x[0]*x[0]*x[0]")
diff_part = k*inner(grad(u),grad(v))*dx
source_part = C*v*dx
Res = diff_part - source_part
J = derivative(Res,u)
problem = NonlinearVariationalProblem(Res, u, bcs, J)
solver = NonlinearVariationalSolver(problem)
solver.solve()
prm = solver.parameters['newton_solver']
prm['relative_tolerance'] = 1E-6
prm['absolute_tolerance'] = 1E-6
prm['maximum_iterations'] = 100

Categories