Redundant lines in 0/1 Matrix output - python

I am trying to create a script that can allows me to output all the different combinations possible for different project optimization choices. In short, there are 6 projets (A B C D E F) that each have 2, 3 or 6 possible choices of optimization, that are mutually exclusive (you can't choose F4 and F5 at the same time for example).
import numpy as np
A = range(1, 3)
B = range(1, 3)
C = range(1, 7)
D= range(1,3)
E=range(1,3)
F=range(1,4)
length = len(A) + len(B) + len(C) + len(D) + len(E) + len(F)
nb_projet = len(A) * len(B) * len(C) * len(D) * len(E) * len(F)
result = np.zeros((length, nb_projet))
for k in range(len(A)):
for i in range(len(A)):
for j in range(nb_projet):
result[i, j] = (i+j % len(A)) == k
for k in range(len(B)):
for i in range(len(B)):
for j in range(nb_projet):
result[i + len(A), j] = (i+j % len(B)) == k
for k in range(len(C)):
for i in range(len(C)):
for j in range(nb_projet):
result[i + len(A)+len(B), j] = (i+j % len(C)) == k
for k in range(len(D)):
for i in range(len(D)):
for j in range(nb_projet):
result[i + len(A)+len(B)+len (C), j] = (i+j % len(D)) == k
for k in range(len(E)):
for i in range(len(E)):
for j in range(nb_projet):
result[i + len(A)+len(B)+len (C)+len(D), j] = (i+j % len(E)) == k
for k in range(len(F)):
for i in range(len(F)):
for j in range(nb_projet):
result[i + len(A)+len(B)+len (C)+len(D)+len(E), j] = (i+j % len(F)) == 0
print (result.T)
np.savetxt("ResultsS2.txt", result, delimiter=" ")
Basically the code is supposed to add a 1 if the optimization is chosen. At the moment it only generates 6 differents scenarios and not the 250+ that are possible.
Does anyone have an idea on how to fix this ?
Thank yu a lot !

This is just a bunch of concatenated one-hot arrays, so utilizing the second answer here and meshgrid to create the full factorial, you can just do something like this:
projects = [2,2,6,2,2,3] #[A.size, B.size, C.size . . .]
m = np.meshgrid(*[np.arange(i) for i in projects])
oneHots = [np.eye(projects[i])[m[i].flat] for i in range(len(projects))]
out = np.hstack(oneHots).T
out.shape
>(17, 288)

You can use something like this. Not the smartest, but if the arrays are not too long, it would work perfectly.
import numpy as np
A = range(0, 2)
B = range(0, 2)
C = range(0, 6)
length = len(A) + len(B) + len(C)
nb_projet = len(A) * len(B) * len(C)
result = np.zeros((length, nb_projet))
selectedList = []
count = 0
for i in A:
for j in B:
for k in C:
result[(i,count)]= 1
result[(len(A)+j,count)]=1
result[(len(A)+len(B)+k, count)] = 1
count+=1
Note, that I had changed the ranges to fit better.

Related

how to fix 'gurobipy.LinExpr' object is not iterable

I am having some issues with my Linear Program Model in gurobi. I am quite new to programming, and don't really understand what the error is. It comes up as 'gurobipy.LinExpr' object is not iterable with my Objective Function. This is my code currently
from gurobipy import *
IDtoLVC = [
[40.4,61.2,69.3,60.9,86.8,13.1,70.5,69.7],
[59.5,5.6,45.8,85.6,62.6,46.9,77.8,29.7],
[27.2,62.7,26.9,30.1,30.3,62.6,11.7,45.0]
]
CCDPop = [2180,4887,2174,4244,2444,2156,2433,2096,4148,3636,4935,3160,4153,2058,4614,3862,4588,4264,2559,2770,3964,2333,3681,4786,3256]
CCDtoLVC = [
[48.8,0,0,0,0,19.2,0,0],
[46.3,0,0,0,0,8.3,0,0],
[0,37.2,0,0,0,17.7,0,0],
[0,14.0,0,0,0,0,0,36.1],
[0,18.4,0,0,0,0,0,42.2],
[35.5,0,0,0,0,20.1,0,0],
[33.3,0,0,0,0,6.8,0,0],
[24.9,0,0,0,0,18.7,0,0],
[0,17.4,0,0,0,30.8,0,0],
[0,12.4,0,0,0,0,0,20.1],
[23.5,0,0,31.6,0,0,0,0],
[6.9,0,0,28.3,0,0,0,0],
[17.9,0,27.7,0,0,0,0,0],
[0,24.4,20.3,0,0,0,0,16.4],
[0,28.9,26.1,0,0,0,0,11.5],
[28.3,0,0,12.0,0,0,0,0],
[13.0,0,0,14.4,0,0,24.9,0],
[13.1,0,26.7,31.0,0,0,24.0,0],
[0,0,6.5,0,17.1,0,0,25.4],
[0,0,20.3,0,16.4,0,0,23.3],
[0,0,0,15.1,0,0,35.3,0],
[27.2,0,0,14.1,0,0,7.8,0],
[0,0,25.6,0,25.0,0,14.7,0],
[0,0,26.7,0,12.0,0,0,0],
[0,0,30.2,0,15.5,0,0,0]
]
LVCCost = [194, 105, 184]
# Sets
I = range(3) # no. of IDs
J = range(8) # no. of LVCs
K = range(25) # no. of CCDs
T = range(6) # length of time
# Model
m = Model('Vaccine Distribution')
X = { (i,j,t): m.addVar() for i in I for j in J for t in T }
Y = { (j,k,t): m.addVar() for j in J for k in K for t in T }
m.setObjective((0.20 * quicksum(quicksum(quicksum(X[i,j,t] * IDtoLVC[i][j] for i in I for j in J for t in T)))) +
(quicksum(quicksum(quicksum(Y[j,k,t] * CCDtoLVC[k][j] for j in J for k in K for t in T)))) +
(quicksum(quicksum(quicksum(X[i,j,t] * LVCCost[i] for i in I for j in J for t in T)))),
GRB.MINIMIZE)
m.optimize()
You don't need three nested calls to quicksum in order to express a triple sum. Instead, you just call quicksum once:
sum1 = quicksum(X[i,j,t] * IDtoLVC[i][j] for i in I for j in J for t in T)
sum2 = quicksum(Y[j,k,t] * CCDtoLVC[k][j] for j in J for k in K for t in T)
sum3 = quicksum(X[i,j,t] * LVCCost[i] for i in I for j in J for t in T)
m.setObjective(0.20 * sum1 + sum2 + sum3, GRB.MINIMIZE)

How to code subtour constraint in cplex python

I am quite new in python cplex. I tried to model VRP and needed to eliminate subtours for feasible solution, but I cannot do that with the following code:
from docplex.mp.model import Model
import numpy as np
n = 10
Q = 20
N = [i for i in range(1, n+1)]
V = [0] + N
rnd = np.random
rnd.seed(0)
q = {i: rnd.randint(1, 10) for i in N}
loc_x = rnd.rand(len(V))*200
loc_y = rnd.rand(len(V))*100
A = [(i, j) for i in V for j in V if i != j]
c = {(i, j): np.hypot(loc_x[i]-loc_x[j], loc_y[i]-loc_y[j]) for i, j in A}
mdl = Model('CVRP')
x = mdl.binary_var_dict(A, name='x')
u = mdl.continuous_var_dict(N, lb=0, name='u')
mdl.minimize(mdl.sum(c[i, j]*x[i, j] for i, j in A))
mdl.add_constraints(mdl.sum(x[i, j] for j in V if j != i) == 1 for i in N)
mdl.add_constraints(mdl.sum(x[i, j] for i in V if i != j) == 1 for j in N)
mdl.add_constraints(mdl.add(u[i] - u[j] + n*(x[i,j]) <= n - 1 for i,j in N if i!=j))
mdl.parameters.timelimit = 15
solution = mdl.solve()
print(solution)
When I run it, I get the following error:
File "C:\Users\user.spyder-py3\TSP\cplexExp.py", line 25, in
mdl.add_constraints(mdl.add(u[i] - u[j] + n*(x[i,j]) <= n - 1 for i,j in N if i!=j))
TypeError: cannot unpack non-iterable int object
I really appreciate for any help. thanks!!
Thanks guys, the problem is that N is one dimensional array, but I considered it as two dimensional by using i,j in N. I figured that out. By the way, do you know any good resource to learn CPLEX Python? I am new and do not know where to start. Thanks!!
Have a look at the Docplex examples here:
https://github.com/IBMDecisionOptimization/docplex-examples

matrix multiplication without numpy

#Here I should get [[1,3,4],[2,5,7],[5,9,6]] as my final output but Instead im getting [[5,9,6],[5,9,6],[5,9,6]]
def matrix_mul(A, B):
m1 = len(A)
n1 = len(A[0])
m2 = len(B)
n2 = len(B[0])
if(n1!=m2):
print("Not Possible")
else:
c = [[0]*n2]*m1
for i in range(m1):
for j in range(n2):
total = 0
for k in range(n1):
total += A[i][k] * B[k][j]
c[i][j]=total
return c
A = [[1,3,4],[2,5,7],[5,9,6]]
B = [[1,0,0],[0,1,0],[0,0,1]]
print("AxB\n",matrix_mul(A, B))
Change c = [[0]*n2]*m1 to
c = [[0]*n2 for _ in range(m1)]

How i **2 different from i * i in python while calculating?

I was trying to solve Leetcode#279.Perfect-Squares
When I tried i ** 2 in loops, I got Time Limit Exceed. But once I change it to i * i, the code was accepted, that means i * i is faster than i ** 2 in python
What principles in python3 caused this difference?
Code and result for reference:
Use j * j, AC, beats 23%
class Solution:
def numSquares(self, n: int):
if n < 2:
return n
dp = [n] * (n + 1)
dp[0] = 0
dp[1] = 1
for i in range(2, n + 1):
j = 1
while j * j <= i:
dp[i] = min(dp[i], dp[i - j * j] + 1)
j += 1
return dp[-1]
If change all j * j to j ** 2, TLE.

Pythagorean triple with python

I want to get a number 'n' and produce Pythagorean triple that total of them is equal with 'n'.
for example for n=12 my output is 3, 4, 5 (12 = 3 + 4 + 5).
I write below code but it take a lot of time for big numbers. please help me to improve it.
a = int(input())
done = False
for i in range(int(a/4)+1,2,-1):
if done:
break
for j in range(i+1,int(a/2)+1):
k = a-(i+j)
if k <= j:
break
if i**2 + j**2 == k**2:
print(i,j,k)
done = True
break
if done == False:
print('Impossible')
This code may help you
limits = int(input())
c, m = 0, 2
# Limiting c would limit
# all a, b and c
while c < limits :
# Now loop on n from 1 to m-1
for n in range(1, m) :
a = m * m - n * n
b = 2 * m * n
c = m * m + n * n
# if c is greater than
# limit then break it
if c > limits :
break
if a+b+c == limits:
print(a, b, c)
m = m + 1
>> 12
>> 3 4 5
I've used the joblib module to parallelize your code, though I haven't tested if there is a speedup for very large n; let me know:
from joblib import Parallel, delayed
done = False
def triple(a):
global done
for i in range(int(a/4)+1,2,-1):
if done:
break
for j in range(i+1,int(a/2)+1):
k = a-(i+j)
if k <= j:
break
if i**2 + j**2 == k**2:
print(i,j,k)
done = True
break
if done == False:
print('Impossible')
if __name__ == '__main__':
a = int(input("n:"))
Parallel(n_jobs=-1, backend="threading")(map(delayed(triple), [a]))
To generate a Pythagorean triplet of a given sum, you can run two loops, where the first loop runs from i = 1 to n/3, the second loop runs from j = i+1 to n/2. In second loop, we check if (n – i – j) is equal to i * i + j * j.
n = int(input()
for i in range(1, int(n / 3) + 1):
for j in range(i + 1, int(n / 2) + 1):
k = n - i - j
if (i * i + j * j == k * k):
print(i, j, k)

Categories