How to sum up a two dimensional pulp solution - python

I have following code cutouts:
a = range(0, 30)
b = range (0, 88)
Power_consumption = LpVariable.dicts('Power_consumption', (a,b), lowBound=0, upBound=5, cat='Continuous')
...
result= [[]]
for i in a:
for j in b:
print("i:",3, "j:",3, " = ", Power_consumption[i][j].varValue)
result[i][j] = Power_consumption[i][j].varValue
After getting the optmimal solution of the Linear Programming Model, I would like to sum up the "Power_consumption" on the index i ( i = timestep, j = device) so that I have for every timestep "i" the power consumption of all devices. But when trying I get all the time "IndexError: list assignment index out of range". So I am wondering what I did wrong and whats the best way of doing so ?

I don’t think you are constructing your variable correctly with respect to a and b. Be more explicit there…
a = list(range(30))
b = list(range(88))
ab = [(i, j) for i in a for j in b]
Power = LpVariable.dicts(‘power’, ab, . . . )

Related

PuLP: How to write a multi variable constraint?

I am trying to solve this optimization problem in Python. I have written the following code using PuLP:
import pulp
D = range(0, 10)
F = range(0, 10)
x = pulp.LpVariable.dicts("x", (D), 0, 1, pulp.LpInteger)
y = pulp.LpVariable.dicts("y", (F, D), 0, 1, pulp.LpInteger)
model = pulp.LpProblem("Scheduling", pulp.LpMaximize)
model += pulp.lpSum(x[d] for d in D)
for f in F:
model += pulp.lpSum(y[f][d] for d in D) == 1
for d in D:
model += x[d]*pulp.lpSum(y[f][d] for f in F) == 0
model.solve()
The one-but-last line here returns: TypeError: Non-constant expressions cannot be multiplied. I understand it is returning this since it cannot solve non-linear optimization problems. Is it possible to formulate this problem as a proper linear problem, such that it can be solved using PuLP?
It is always a good idea to start with a mathematical model. You have:
min sum(d, x[d])
sum(d,y[f,d]) = 1 ∀f
x[d]*sum(f,y[f,d]) = 0 ∀d
x[d],y[f,d] ∈ {0,1}
The last constraint is non-linear (it is quadratic). This can not be handled by PuLP. The constraint can be interpreted as:
x[d] = 0 or sum(f,y[f,d]) = 0 ∀d
or
x[d] = 1 ==> sum(f,y[f,d]) = 0 ∀d
This can be linearized as:
sum(f,y[f,d]) <= (1-x[d])*M
where M = |F| (number of elements in F, i.e. |F|=10). You can check that:
x[d]=0 => sum(f,y[f,d]) <= M (i.e. non-binding)
x[d]=1 => sum(f,y[f,d]) <= 0 (i.e. zero)
So you need to replace your quadratic constraint with this linear one.
Note that this is not the only formulation. You could also linearize the individual terms z[f,d]=x[d]*y[f,d]. I'll leave that as an exercise.

Two number Sum program in python O(N^2)

I am used to write code in c++ but now I am trying to learn python. I came to know about the Python language and it is very popular among everyone. So I thought, let's give it a shot.
Currently I am preparing for companies interview questions and able to solve most of them in c++. Alongside which, I am trying to write the code for the same in Python. For the things which I am not familiar with, I do a google search or watch tutorials etc.
While I was writing code for my previously solved easy interview questions in python, I encountered a problem.
Code : Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Given an array of integers, print the indices of the two numbers such that they add up to a specific target.
def twoNum(*arr, t):
cur = 0
x = 0
y = 0
for i in range (len(arr) - 1):
for j in range (len(arr) - 1):
if(i == j):
break
cur = arr[i] + arr[j]
if(t == cur):
x = arr[i]
y = arr[j]
break
if(t == cur):
break
print(f"{x} + {y} = {x+y} ")
arr = [3, 5, -4, 8, 11, 1, -1, 6]
target = 10
twoNum(arr, t=target)
So here is the problem: I have defined x, y in function and then used x = arr[i] and y = arr[j] and I m printing those values.
output coming is : is 0 + 0 = 10 (where target is 10)
This is I guess probably because I am using x = 0 and y = 0 initially in the function and it seems x and y values are not updating then I saw outline section in VSCode there I saw x and y are declared twice, once at the starting of the function and second in for loop.
Can anyone explain to me what is going on here?
For reference, here is an image of the code I wrote in C++
Change this:
def twoNum(*arr, t):
to this:
def twoNum(arr, t):
* is used to indicate that there will be a variable number of arguments, see this. It is not for pointers as in C++.
Basically what you are trying to do is to write C code in python.
I would instead try to focus first on how to write python code in a 'pythonic' way first. But for your question - sloving it your way using brute force in python:
In [173]: def two_num(arr, t):
...: for i in arr:
...: for j in arr[i + 1: ]:
...: if i + j == t:
...: print(f"{i} + {j} = {t}")
...: return
Here's a way to implement a brute force approach using a list comprehension:
arr = [1,3,5,7,9]
target = 6
i,j = next((i,j) for i,n in enumerate(arr[:-1]) for j,m in enumerate(arr[i+1:],i+1) if n+m==target)
output:
print(f"arr[{i}] + arr[{j}] = {arr[i]} + {arr[j]} = {target}")
# arr[0] + arr[2] = 1 + 5 = 6
Perhaps even more pythonic would be to use iterators:
from itertools import tee
iArr = enumerate(arr)
i,j = next((i,j) for i,n in iArr for j,m in tee(iArr,1)[0] if n+m==target)
When you get to implementing an O(n) solution, you should look into dictionaries:
d = { target-n:j for j,n in enumerate(arr) }
i,j = next( (i,d[m]) for i,m in enumerate(arr) if m in d and d[m] != i )

Recurrent sequence task

Given the sequence f0, f1, f2, ... given by the recurrence relations f0 = 0, f1 = 1, f2 = 2 and fk = f (k-1) + f (k-3)
Write a program that calculates the n elements of this sequence with the numbers k1, k2, ..., kn.
Input format
The first line of the input contains an integer n (1 <= n <= 1000)
The second line contains n non-negative integers ki (0 <= ki <= 16000), separated by spaces.
Output format
Output space-separated values ​​for fk1, fk2, ... fkn.
Memory Limit: 10MB
Time limit: 1 second
The problem is that the recursive function at large values ​​goes beyond the limit.
def f (a):
    if a <= 2:
        return a
    return f (a - 1) + f (a - 3)
n = int (input ())
nums = list (map (int, input (). split ()))
for i in range (len (nums)):
    if i <len (nums) - 1:
        print (f (nums [i]), end = '')
    else:
        print (f (nums [i]))
I also tried to solve through a cycle, but the task does not go through time (1 second):
fk1 = 0
fk2 = 0
fk3 = 0
n = int (input ())
nums = list (map (int, input (). split ()))
a = []
for i in range (len (nums)):
    itog = 0
    for j in range (1, nums [i] + 1):
        if j <= 2:
            itog = j
        else:
            if j == 3:
                itog = 0 + 2
                fk1 = itog
                fk2 = 2
                fk3 = 1
            else:
                itog = fk1 + fk3
                fk1, fk2, fk3 = itog, fk1, fk2
    if i <len (nums) - 1:
        print (itog, end = '')
    else:
        print (itog)
How else can you solve this problem so that it is optimal in time and memory?
Concerning the memory, the best solution probably is the iterative one. I think you are not far from the answer. The idea would be to first check for the simple cases f(k) = k (ie, k <= 2), for all other cases k > 2 you can simply compute fi using (fi-3, fi-2, fi-1) until i = k. What you need to do during this process is indeed to keep track of the last three values (similar to what you did in the line fk1, fk2, fk3 = itog, fk1, fk2).
On the other hand, there is one thing that you need to do here. If you just perform computations of fk1, fk2, ... fkn independently, then you are screwed (unless you use a super fast machine or a Cython implementation). On the other hand, there is no reason to perform n independent computations, you can just compute fx for x = max(k1, k2, ..., kn) and on the way you'll store every answer for fk1, fk2, ..., fkn (this will slow down the computation of fx by a little bit, but instead of doing this n times you'll do it only once). This way it can be solved under 1s even for n = 1000.
On my machine, independent calculations for f15000, f15001, ..., f16000 takes roughly 30s, the "all at once" solution takes roughly 0.035s.
Honestly, that's not such an easy exercise, it would be interesting to show your solution on a site like code review to get some feedback on your solution once you found one :).
First, you have to sort the numbers. Then calculate values of the sequence one by one:
while True:
a3 = a2 + a0
a0 = a3 + a1
a1 = a0 + a2
a2 = a1 + a3
Lastly, return values in beginning order. To do that you have to remember position of every number. From [45, 22, 14, 33] make [[45,0], [22,1], [14,2], [33,3]] and then sort, calculate values and change them with argument [[f45,0], [f22,1], [f14,2], [f33,3]], then sort by second value.

Dynamic programming solution to maximizing an expression by placing parentheses

I'm trying to implement an algorithm from Algorithmic Toolbox course on Coursera that takes an arithmetic expression such as 5+8*4-2 and computes its largest possible value. However, I don't really understand the choice of indices in the last part of the shown algorithm; my implementation fails to compute values using the ones initialized in 2 tables (which are used to store maximized and minimized values of subexpressions).
The evalt function just takes the char, turns it into the operand and computes a product of two digits:
def evalt(a, b, op):
if op == '+':
return a + b
#and so on
MinMax computes the minimum and the maximum values of subexpressions
def MinMax(i, j, op, m, M):
mmin = 10000
mmax = -10000
for k in range(i, j-1):
a = evalt(M[i][k], M[k+1][j], op[k])
b = evalt(M[i][k], m[k+1][j], op[k])
c = evalt(m[i][k], M[k+1][j], op[k])
d = evalt(m[i][k], m[k+1][j], op[k])
mmin = min(mmin, a, b, c, d)
mmax = max(mmax, a, b, c, d)
return(mmin, mmax)
And this is the body of the main function
def get_maximum_value(dataset):
op = dataset[1:len(dataset):2]
d = dataset[0:len(dataset)+1:2]
n = len(d)
#iniitializing matrices/tables
m = [[0 for i in range(n)] for j in range(n)] #minimized values
M = [[0 for i in range(n)] for j in range(n)] #maximized values
for i in range(n):
m[i][i] = int(d[i]) #so that the tables will look like
M[i][i] = int(d[i]) #[[i, 0, 0...], [0, i, 0...], [0, 0, i,...]]
for s in range(n): #here's where I get confused
for i in range(n-s):
j = i + s
m[i][j], M[i][j] = MinMax(i,j,op,m,M)
return M[0][n-1]
Sorry to bother, here's what had to be improved:
for s in range(1,n)
in the main function, and
for k in range(i, j):
in MinMax function. Now it works.
The following change should work.
for s in range(1,n):
for i in range(0,n-s):

Formulating constraints of a LP in Pulp Python

I have this LP problem, and I'm trying to solve it using PuLP in Python-3. One option that I can think of is to write all variable explicitly, but I want to avoid it. Is there a way that I can use lists/dicts in this problem? (I did refer to https://pythonhosted.org/PuLP/CaseStudies/a_sudoku_problem.html where dicts were being used, but didn't quite understand the entire solution)
Assume wt{i,j,type} denotes the number of traded goods between person[i] and person[j] of type.
LP Problem:
(Here, cost{i,j} is a known cost of pairing for all (i,j) pairs.
subject to:
I would be really grateful for any help, as I'm a beginner to both optimization and python/pulp.
The 'lists/dicts' is a way to define variables over domains (indexed variables).
The indexs argument of LpVariable.dicts() defines the domain - cartesian product of the supplied sets. See also documentation of PuLP - LpVariable.
The code sample below does not contain all your constraints, but I believe you can easily fill-in the remaining ones. Constraint 1 (with const1 and const2) is treated via the lower and upper bound of the wt variable instead.
from pulp import LpProblem, LpVariable, LpMaximize, LpInteger, lpSum, value
prob = LpProblem("problem", LpMaximize)
# define 'index sets'
I = range(10) # [0, 1, ..., 9]
J = range(10)
T = range(3)
# define parameter cost[i,j]
cost = {}
for i in I:
for j in J:
cost[i,j] = i + j # whatever
# define wt[i,j,t]
const1 = 0 # lower bound for w[i,j,t]
const2 = 100 # upper bound for w[i,j,t]
wt = LpVariable.dicts(name="wt", indexs=(I, J, T), lowBound=const1, upBound=const2, cat=LpInteger)
# define assign[i,j]
assign = LpVariable.dicts(name="assign", indexs=(I, J))
# contraint
for i in I:
for j in J:
prob += assign[i][j] == lpSum(wt[i][j][t] for t in T), ""
# objective
prob += lpSum(cost[i,j] * assign[i][j] for i in I for j in J)
prob.solve()
for i in I:
for j in J:
for t in T:
print "wt(%s, %s, %s) = %s" % (i, j, t, value(wt[i][j][t]))
for i in I:
for j in J:
print "assign(%s, %s) = %s" % (i, j, value(assign[i][j]))

Categories

Resources