'LpAffineExpression' object has no attribute 'solve' in pulp Lp problem- Optimization - python

import pulp as p
import numpy as np
a1=np.array([1000,2000,3000,7000,8000,13000,223000,32000,35000,369000,38000,3885000])
x=p.LpVariable('x', lowBound=5000, cat='Continuous')
y=p.LpVariable('y', lowBound=8000,cat='Continuous')
Lp_prob=(((y-x)*1.3+x)*0.014428)+((a1-y)*1.5*0.014428)
Lp_prob.solve()
I try to do linear programming in pulp. But I have 'LpAffineExpression' object has no attribute 'solve' error.
How can I fix it? Thanks.

I would suggest to first study this example: https://www.coin-or.org/PuLP/CaseStudies/a_blending_problem.html. It has all the ingredients to cover your example.
So a working model can look like:
import pulp as p
import numpy as np
a1=np.array([1000,2000,3000,7000,8000,13000,223000,32000,35000,369000,38000,3885000])
x=p.LpVariable('x', lowBound=5000, cat='Continuous')
y=p.LpVariable('y', lowBound=8000,cat='Continuous')
Lp_prob = p.LpProblem("This_Example_Works",p.LpMaximize)
Lp_prob += (((y-x)*1.3+x)*0.014428)+((a1-y)*1.5*0.014428)
Lp_prob.solve()
print("Status:", p.LpStatus[Lp_prob.status])
Note that PuLP interprets this as:
MAXIMIZE
-0.0043284000000000005*x + -0.24094759999999996*y + 99899.472
VARIABLES
5000 <= x Continuous
8000 <= y Continuous
The very strange construct a1-y is interpreted here as sum(a1-y)=sum(a1)-n*y where n=a1.size. I would suggest not to use NumPy arrays this way in a PuLP model.

Related

Can we add numpy object pulp objective function

I came across following code:
from pulp import *
import numpy as np
prob = LpProblem("lp_prob", LpMinimize)
decision_variables = LpVariable.dicts('x', range(5))
prob += np.sum(decision_variables.values())
When I tried same code on my machine, it gave following error on last line:
TypeError: Can only add LpConstraintVar, LpConstraint, LpAffineExpression or True objects
Cant I add numpy array to LpProblem. Now I am guessing if the given code is incorrect? Also is there any other way / version (of python and/or numpy and/or pulp) in which adding numpy object to LpProblem works?
decision_variables is not a numpy array. It is a dictionary and that's why you can do decision_variables.values().
decision_variables.values() is not a numpy array either, it's a dictvalues object.
the result of np.sum is not a numpy array. When applied to a numpy array it should return a scalar value. But for a dictvalues object it does nothing (no sum, at least).
I'm not sure why you would need to use np.sum at all here.
In pulp, the sum of a set of pulp variables (list, dictvalues, dictkeys, etc.) is done with the lpSum function (https://www.coin-or.org/PuLP/pulp.html#pulp.lpSum).
prob += lpSum(decision_variables.values())

How to use log base 2 with GEKKO (Python)

I'm trying to solve an optimization problem with GEKKO using python, I'm trying to develop some mathematical function with log and sqrt and I figure out that I should use gekko operator instead of using numpy or math function. I wanted to know how to implement log base 2 instead of log or log10 using gekko.
gk = GEKKO()
gk.log(...) # work
gk.sqrt(...) # work
gk.log2(...) # does not work!
Error :
AttributeError: 'GEKKO' object has no attribute 'log2'
Instead you can change the log base using the rule:
log2(x) = gk.log(x)/gk.log(2)
You can't expect for it to have all of the log bases implemented.
You can create a log2 function in Gekko, especially if you need to use it multiple times throughout your model.
def glog2(x):
return gk.log(x)/np.log(2)
Below is a complete script that demonstrates the use of the new log2 function and shows the agreement with the Numpy log2 function.
from gekko import GEKKO
import numpy as np
# compare with numpy
xnp = np.logspace(-1,4,100)
ynp = np.log2(xnp)
gk = GEKKO(remote=False)
x = gk.Param(xnp)
y,z = gk.Array(gk.Var,2)
# define a new log2 function
def glog2(x):
return gk.log(x)/np.log(2)
gk.Equation(y==glog2(x))
gk.options.IMODE=2; gk.solve(disp=False)
import matplotlib.pyplot as plt
plt.semilogx(xnp,ynp,'b-',lw=4,label=r'$y=\log_2(x)$ Numpy')
plt.semilogx(x.value,y.value,'r--',lw=2,label=r'$y=\log_2(x)$ Gekko')
plt.legend(); plt.xlabel('x'); plt.ylabel('y'); plt.grid(); plt.show()

How to set cvxpy n-dim variable first value?

I'm a beginner at python and I try to use cvxpy library for my optimization project. I try to change the first value of my n dimensional variable But I get an AttributeError
import cvxpy as cp
S = cp.Variable(100)
S[0].value=320000
output:AttributeError: can't set attribute
It works for 1-dim variable
import cvxpy as cp
S = cp.Variable()
S.value=320000
Thanks in advance
The 'Variable' object does not support item assignment. You may enforce your requirement as a constraint:
import cvxpy as cp
S = cp.Variable(100) # Define your variables
objective = ... # Define your objective function
constraints = [] # Create an array of constraints
constraints.append(S[0]==320000) # Make your requirement a constraint
# Add more constraints
prob = Problem(objective, constraints) # Define your optimization problem
prob.solve(verbose=True) # Solve the problem
print(S.value)

scipy.optimize get's trapped in local minima. What can I do?

from numpy import *; from scipy.optimize import *; from math import *
def f(X):
x=X[0]; y=X[1]
return x**4-3.5*x**3-2*x**2+12*x+y**2-2*y
bnds = ((1,5), (0, 2))
min_test = minimize(f,[1,0.1], bounds = bnds);
print(min_test.x)
My function f(X)has a local minima at x=2.557, y=1 which I should be able to find.
The code showed above will only give result where x=1. I have tried with different tolerance and alle three method: L-BFGS-B, TNC and SLSQP.
This is the thread I have been looking at so far:
Scipy.optimize: how to restrict argument values
How can I fix this?
I am using Spyder(Python 3.6).
You just encounterd the problem with local optimization: it strongly depends on the start (initial) values you pass in. If you supply [2, 1] it will find the correct minima.
Common solutions are:
use your optimization in a loop with random starting points inside your boundaries
import numpy as np
from numpy import *; from scipy.optimize import *; from math import *
def f(X):
x=X[0]; y=X[1]
return x**4-3.5*x**3-2*x**2+12*x+y**2-2*y
bnds = ((1,3), (0, 2))
for i in range(100):
x_init = np.random.uniform(low=bnds[0][0], high=bnds[0][1])
y_init = np.random.uniform(low=bnds[1][0], high=bnds[1][1])
min_test = minimize(f,[x_init, y_init], bounds = bnds)
print(min_test.x, min_test.fun)
use an algorithm that can break free of local minima, I can recommend scipy's basinhopping()
use a global optimization algorithm and use it's result as initial value for a local algorithm. Recommendations are NLopt's DIRECT or the MADS algorithms (e.g. NOMAD). There is also another one in scipy, shgo, that I have no tried yet.
Try scipy.optimize.basinhopping. It simply just repeat your minimize procedure multiple times and get multiple local minimums. The minimal one is the global minimum.
minimizer_kwargs = {"method": "L-BFGS-B"}
res=optimize.basinhopping(nethedge,guess,niter=100,minimizer_kwargs=minimizer_kwargs)

using sympy solver and numpy dot doesn't work

I'm trying to solve a long equation using sympy solve. This is a simplified version of the equation but the issue is the same.
This code works fine:
import numpy as np
import sympy as sy
coupons = [0.504452818664, 0.486892427806, 0.47758800215, 100.468050176]
rate = sy.Symbol('rate')
rate_final = (sy.solve(100 - (rate*coupons[0]+rate*coupons[1]+rate*coupons[2]+rate*coupons[3]),rate))
print rate_final
rate-final is [0.980998226948197].
But when Ι try to use numpy.dot inside the equation, it gives an empty list as a result.
import numpy as np
import sympy as sy
coupons = [0.504452818664, 0.486892427806, 0.47758800215, 100.468050176]
rate = sy.Symbol('rate')
rate_final = (sy.solve(100 - np.dot(rate,coupons[:]),rate))
print rate_final
rate_final is [].
Is there something wrong with my code or sympy.solve won't work if np.dot() is inside the equation?
A dot product of scalar rate and vector coupons hardly makes sense. You only get an element-wise multiplication of rate and each element. However, you can do this:
import numpy as np
import sympy as sy
coupons = np.array([0.504452818664, 0.486892427806, 0.47758800215, 100.468050176])
rate = sy.Symbol('rate')
rate_final = sy.solve(100 - np.sum(rate * coupons), rate)
print(rate_final)

Categories

Resources