Show constraints values ​after solving - pulp

I have this simple product mix L.P :
from pulp import *
x = pulp.LpVariable("x", lowBound=0)
y = pulp.LpVariable("y", lowBound=0)
problem = pulp.LpProblem("A simple max problem", pulp.LpMaximize)
problem += 300*x + 250*y, "The objective function"
# Constraints
problem += 1.4*x + y <= 35000, "1st constraint"
problem += 0.51*x + y <= 17000, "2nd constraint"
problem += x <= 22500, "3rd constraint"
problem += y <= 15000, "4th constraint"
problem.solve()
print "Optimal Result:"
for variable in problem.variables():
print variable.name, "=", variable.varValue
print "Total net max profit:"
print value(problem.objective)
Optimal Result:
x = 20224.719
y = 6685.3933
Total net max profit:
7738764.025
How can I display the "filled" constraints calculated solutions ? :
Let's take the 1st constraint, I need to do this calculation and to display it, I replace x and y by the optimal values:
1.4*20224.719 + 6685.3933 = 34999,9999
What I need is to output is something like this ,listing each constraints "left side calculation":
{"1st constraint solution" : 34999,9999 ,
"2nd constraint solution" : 16999,9999 ,
"3rd constraint" solution" :20224.719 ,
"4th constraint" solution" : 6685.3933 }
etc ...
In this example, values are pretty close, but It's not always the case ...
I think It's called ' the left side'
Thanks a lot, I can't find any doc about this, is there any code ready for doing this?

Welcome to the site.
I've augmented your example (below) to show how to access the constraint values and slack in pulp. Your example appears to be written in earlier version (pre 3.0) of python as evidenced by lack of parens in print statement. You should move to a more modern installation, if at all possible.
To find these functions in pulp I find that sometimes the dox are good, but often times, I just dive into an interactive environment (ipython) and use the auto-complete functionality to see what is offered and go exploring. :) You named your constraints so this below works well with the names. It should work fine without the names as well as you could just print the constraint value out of the dictionary, which is the expression.
Code
from pulp import *
x = LpVariable("x", lowBound=0)
y = LpVariable("y", lowBound=0)
problem = pulp.LpProblem("A simple max problem", LpMaximize)
problem += 300*x + 250*y, "The objective function"
# Constraints
problem += 1.4*x + y <= 35000, "1st constraint"
problem += 0.51*x + y <= 17000, "2nd constraint"
problem += x <= 22500, "3rd constraint"
problem += y <= 15000, "4th constraint"
problem.solve()
print ("Optimal Result:")
for variable in problem.variables():
print (variable.name, "=", variable.varValue)
print ("Total net max profit:")
print (value(problem.objective))
constraints = problem.constraints
print(f'The constraints are held in a {type(constraints)}')
for name in constraints.keys():
value = constraints.get(name).value()
slack = constraints.get(name).slack
print(f'constraint {name} has value: {value:0.2e} and slack: {slack:0.2e}')
Yields:
...
Optimal Result:
x = 20224.719
y = 6685.3933
Total net max profit:
7738764.025
The constraints are held in a <class 'collections.OrderedDict'>
constraint 1st_constraint has value: -1.00e-04 and slack: -0.00e+00
constraint 2nd_constraint has value: -1.00e-05 and slack: -0.00e+00
constraint 3rd_constraint has value: -2.28e+03 and slack: 2.28e+03
constraint 4th_constraint has value: -8.31e+03 and slack: 8.31e+03

Related

Find the point on the top or bottom of a sequence of numbers

I have a problem like this and i would like to write a snippet of code to solve this problem.
Sequences like: [1,2,3,2], [1,3,2], [1,3,2,1] -> i want to output 3 (maximum) because the sequence increases to 3 and then decreases again
Sequences like [3,2,1,2], [3,1,2], [3,1,2,3] -> i want to output 1 (minimum) because the sequence decreases to 1 and then increases again
Any idea on how to do this automatically?
Try getting local maximas and/or local minimas:
import numpy as np
from scipy.signal import argrelextrema
a = np.array([3,2,1,3])
res=a[np.hstack([argrelextrema(a, np.greater),argrelextrema(a, np.less)]).ravel()]
This will return both local maximas and minimas. You can mark them somehow separately, if it's better for your use case. From your question I assumed it can be just one extremum. Also - depending on your data you might consider using np.less_equal or np.greater_equal instead of np.less or np.greater respectively.
I found it interesting to implement this algorithm in Python 3.
The basic idea is practically to find the minimum and maximum given a sequence of numbers. A sequence, however, can have several maximum points and several minimum points to be taken into consideration. However this is the algorithm I implemented.
I hope it's useful.
sequence = [1,2,3,4,5,4,3,2,8,10,1]
index = 1
max_points = [] #A sequence may have multiple points of relatives max
relative_maximum = sequence[0]
for element in range(len(sequence)):
if(index == len(sequence)):
break
if(sequence[element] < sequence[index]):
relative_maximum = sequence[index]
change_direction = True
else:
if(change_direction == True):
max_points.append(relative_maximum)
change_direction = False
index = index + 1
index = 1
min_points = [] #A sequence may have multiple points of relatives min
relative_minimum = sequence[0]
for element in range(len(sequence)):
if(index == len(sequence)):
break
if(sequence[element] > sequence[index]):
relative_minimum = sequence[index]
change_direction = True
else:
if(change_direction == True):
min_points.append(relative_minimum)
change_direction = False
index = index + 1
print("The max points: " + str(max_points))
print("The min points: " + str(min_points))
Result: The max points: [5, 10] The min points: [2]

How to prevent numbers from getting too low/high in python?

I'm currently working on a "Hunger Games"-Simulator and every player has 17 traits. The traits of the winning person get changed the least and the traits of the worst person get changed much. But after I change the traits they often go below zero or above 1000 (should be max) even though I even coded a backup for this.
I already tried to just set them back into the range 1-1000 and give the leftover trait-points to another trait. It also just happens after multiple iterations.
This is the code to change the traits:
List "pl" is looking like this: [trait1, trait2, ..., trait18]
"count" is the rank.
while again == True:
for k in range(int(count/2)):
randnum = random.randint(0,20)
randnum2 = random.randint(0,15)
randnum3 = random.randint(0,15)
pl[randnum2] += randnum
pl[randnum3] -= randnum
for y in pl:
if y > 1000:
over = abs(y - 1000)
randnum = random.randint(0,15)
if pl[randnum] > 1000 - over:
break
else:
y = 1000
pl[random.randint(0,15)] += over
if y < 0:
over = abs(y)+1
randnum = random.randint(0,15)
if pl[randnum] < over:
break
else:
y = 1
pl[randnum] -= over
for y in pl:
if y > 1000 or y < 1:
again = True
break
else:
again = False
I expected that the traits get updated so that if you add all trait-points together you always get the same result with every player. But it seems like they either get really big or really small and don't have the same sum all the time.
Thanks! :)
use special list-like class with method:
def __setitem__(self, name, value):
if minValue < value < maxValue:
super().__setitem__(name, value)
and define other methods (__add__, append, ...) using that

Can't assign to function call syntax error when trying to subtract variables in python

I'm attempting to create a rudimentary stock trading algorithm. One thing included in that algorithm is, after deciding how many of a stock to buy, subtracting the correct amount of money from the user's total. The problem occurs on the line "int(money_data) -= int(round(float(stockamounts[i]) * float(prices[i])))". The syntax error points to "int(money_data). "I hope I explained the problem in a way that makes sense. Thank you for any help.
for i in stock_symbols:
stock_url = "https://www.nasdaq.com/symbol/" + str(i)
stock_data = requests.get(stock_url)
file = open("data.txt", "w")
file.write(str(stock_data.content))
file.close()
file = open("data.txt", "r")
stock_data = file.read()
file.close()
stock_data = re.findall(r'<div id="qwidget_lastsale" class="qwidget-dollar">(.*?)</div>', str(stock_data))
for i in stock_data:
print(str(i.strip('$')))
price = i.strip('$')
prices.append(price)
stock_amounts = []
print(str(stock_symbols[0]) + " | " + str(round(float(money_amount) / float(prices[0]))))
stock_amounts.append(round(float(money_amount) / float(prices[0])))
for x in range(len(prices)):
print(str(stock_symbols[x]) + " | " + str(round(float(money_amount) / float(prices[x]))))
stock_amounts.append(round(float(money_amount) / float(prices[x])))
print(len(stock_amounts))
for i in stock_amounts:
print(stock_amounts[i])
int(money_data) -= int(round(float(stock_amounts[i]) * float(prices[i])))
print(money_data)
As the error says, you
can't assign to [a] function call
Why?
Say you have a function f:
>>> def f(x);
... return 3*x+4
When you
>>> f(4) = 5
what do you actually mean? You can't logically explain what should happen in a case like this, because basically (and in this example), that's like saying 16 = 5, which, I hope you agree, doesn't make sense.
"But, I did something different"
Yes, you used a variable in the call and used the -= operator.
Still, the a -= b operator is short for a = a-b (although you could overload them to do different stuff), and that's clearly an assignment (even if you overload, it remains an assignment).
How do I fix this?
You have two (and a half) possibilities:
use a normal assignment: just expand to a longer form as in val = int(val-to_sub)
add an extra line val -= to_sub; val = int(val) (please actually add an extra line and don't use ;)
(1/2) leave the int() away. If you are careful to only add, subtract, multiply with or divide through ints (or use // for divisions), you are sure that the value stays an int

number as an object, or storing properties of a number

in designing an algebraic equation modelling system, I had this dilemma: we cannot associate properties to a number, if I turn the number to a table with a field "value" for example, I can overload arithmetic operators, but not the logic operator since that only works when both operands have same metatable, while my users will compare "x" with numbers frequently.
For example, here is a minimal equation solver system:
x = 0
y = 0
eq1 = {function() return 2*x + 3*y end, rhs = 1 }
eq2 = {function() return 3*x + 2*y end, rhs = 2 }
p = {{x,y},{eq1, eq2}}
solve(p)
The "solve()" will process table "p" to get all coefficients of the equation system and rhs. However, it is essential, a user can associate properties to "x" and "y", for example, lower bound, upper bound. I tries using table,
x = {val=0, lb=0, ub=3}
y = {val=1,lb=3,ub=5}
....
and write metamethods for "x" and "y" such that arithmetic operating will act on x.val and y.val. However, in a scripting environment, we also need to compare "x" with numbers, i.e., "if x>0 then ...". And I stuck here. An ugly solution is to ask users to use x.val, y.val everywhere in modelling the equation and scripting. Does anyone here has similar need to associate properties to a number, and the number can still be used in arithmetic/logic operations?
Something like this could work:
x = {val = 10}
mt = {}
mt.__lt = function (op1, op2)
if (type(op1) == 'table') then a = op1.val else a = op1 end
if (type(op2) == 'table') then b = op2.val else b = op2 end
return a < b
end
setmetatable(x, mt)
print(x < 5) -- prints false
print(x < 15) -- prints true
print(x < x) -- prints false
print(5 < x) -- prints true
Of course, you would write similar methods for the other operators (__add, __mul, __eq and so on).
If you'd rather not use type()/reflection, you can use an even dirtier trick that takes advantage of the fact that unary minus is well, unary:
mt = {}
mt.__unm = function (num) return -(num.val) end
mt.__lt = function (a, b) return -(-a) < -(-b) end
This is rather simple if you have access to the debug library, do you?
debug.setmetatable(0, meta)
meta will be the metatable of ALL numbers. This will solve your logical overloading problem.
However if you would prefer assigning properties to numbers, there is a way you could do this, I wrote a quick example on how one would do so:
local number_props = {
{val="hi"},
{val="hi2"}
}
debug.setmetatable(0,{__index=function(self,k)return number_props[self][k]end})
print((1).val, (2).val)

Why am i getting a list index out of range error in my code?

The error occurs in line if data[l][0] == value:
def binary_pairs(data, value):
l = 0
h = len(data) - 1
while l < h and data[l]!= value:
m = (h + l) // 2
if data[m][0] == value:
l = m
elif data[m][0] < value:
l = m + 1
else:
h = m - 1
print("done")
if data[l][0] == value:
return l
else:
return -1
example input:
[ [ "dead", ["brian.txt","grail.txt"] ],
[ "eunt", ["brian.txt"] ],
[ "spank", ["grail.txt"] ]
]
I can see two potential issues with your code:
It seems odd that you use both data[l] and data[l][0] in comparisons.
If, for example, l==0 and h==1 and you end up taking the else (h = m - 1), you'd end up with h==-1, which is out of bounds. There could be other similar issues.
I can't run your code right now but here are a few ideas.
If you are trying to solve a problem, rather than trying to learn to write a binary search, consider using Python's bisect module.
http://docs.python.org/2/library/bisect.html
It is best practice in Python to comply with the coding standard called PEP 8; this recommends not using lower-case L as a variable name, or upper-case I.
http://www.python.org/dev/peps/pep-0008/
It would be cleaner to have the loop immediately return the index when it finds the value, rather than having the loop test at the top to make sure the value hasn't been found yet, causing the loop to end and then the value to be returned from the bottom of the function. If the loop ends, you can return -1 at the end of the function.
Your loop checks that the index is < h but does not check that the index is I >= 0. I suspect that this could be your problem.
When debugging a loop like this, it is often helpful to add print statements that log what is going on. You should print the value of the index, and print enough other lines to know whether it is being increased or decreased, and by how much.

Resources