I am trying to optimise the problem below using Mystic. I am currently receiving an error that I don't understand and was hoping someone more familiar with the library could help.
def objective(x):
x0,x1,x2,x3,x4,x5,x6,x7,x8 = x
return x0**2 + x4**2 + x8**2
equations = '''
x0 + x1 + x2 - x3 - x6 - 20 == 0.0
x4 + x3 + x5 - x1 - x7 - 150 == 0.0
x8 + x6 + x7 - x2 - x5 + 100 == 0.0
x6 == 0
x7 == 0
x0 >= 10
x4 >= 60
'''
from mystic.symbolic import generate_conditions, generate_penalty
pf = generate_penalty(generate_conditions(equations), k=1e4)
from mystic.symbolic import generate_constraint, generate_solvers, solve
cf = generate_constraint(generate_solvers(solve(equations))
When calculating cf i receive an 'NotImplementedError:cannot simplify inequalities' and wanted to know why this could be?
If anyone knows how i would extend this such that i can create the constraints through a function or in a different manner I would also be keen to know.
Cheers
I'm the mystic author. You should always first try just using solve(equations) and see what happens. It can fail to symbolically solve the equations due to the inequalities. If so, then try to do simplify(equalities) instead. That symbolically simplifies equations so there's only one variable on the LHS for each line. The inequality solver usually can then work in that case. If that fails, you can rewrite the equations so there's only one variable on the LHS.
>>> def objective(x):
... x0,x1,x2,x3,x4,x5,x6,x7,x8 = x
... return x0**2 + x4**2 + x8**2
...
>>> import mystic
>>> equations = '''
... x0 + x1 + x2 - x3 - x6 - 20 == 0.0
... x4 + x3 + x5 - x1 - x7 - 150 == 0.0
... x8 + x6 + x7 - x2 - x5 + 100 == 0.0
... x6 == 0
... x7 == 0
... x0 >= 10
... x4 >= 60
... '''
>>> eqns = mystic.symbolic.simplify(equations)
>>> print(eqns)
x0 == -x1 - x2 + x3 + x6 + 20
x8 == x2 + x5 - x6 - x7 - 100
x4 >= 60
x7 == 0
x6 == 0
x0 >= 10
x4 == x1 - x3 - x5 + x7 + 150
>>> from mystic.symbolic import generate_constraint, generate_solvers
>>> cf = generate_constraint(generate_solvers(eqns))
>>> cf([0,1,2,3,4,5,6,7,8])
[26, 1, 2, 3, 143, 5, 0, 0, -106]
>>>
I think I'm facing a Milp problem but I'm not sure.
The problem in a simplified form is: There are 3 suppliers of materials (trucks) for 3 cities. The real problem is 30 Suppliers and 100 cities...
Supliers capacity: a:1; b:2; c:3.
Cities Demand: a:2; b:3; c:1
Distances Supplier(Cities):
a(a:2;b:4;c:6)
b(a:4;b:2;c:4)
c(a:6;b:4;c:2)
like this with each Capacity and Demand
Sa1 - Ca2
Sb2 - Cb3
Sc3 - Cc1
The goal its optimize the suply but there is one (devil) condition:
Just one supplier per city.
Whitout the contidion the problem is a simple problem to solve with basic Linear Programming.
With the condition I think that could be solved with Mixed Integer Linear Programming - MILP.
But not figure it out how to solve this with MILP Method and Pulp (python module).
If someone can help me
Thanks!
My first try
from scipy.optimize import linprog
c = [2,4,6,4,2,4,6,4,2]
Ae = [[1,1,1,0,0,0,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,1,1,1],
[1,0,0,1,0,0,1,0,0],
[0,1,0,0,1,0,0,1,0],
[0,0,1,0,0,1,0,0,1],
]
be = [1,2,3,2,3,1]
x0_bounds = (0,None)
x1_bounds = (0,None)
x2_bounds = (0,None)
x3_bounds = (0,None)
x4_bounds = (0,None)
x5_bounds = (0,None)
x6_bounds = (0,None)
x7_bounds = (0,None)
x8_bounds = (0,None)
sol = linprog(c, A_eq= Ae, b_eq = be, bounds = ((x0_bounds,x1_bounds,x2_bounds,x3_bounds,x4_bounds,x5_bounds,x6_bounds,x7_bounds,x8_bounds)) )
print(sol)
fun: 18.0
message: 'Optimization terminated successfully.'
nit: 10
slack: array([], dtype=float64)
status: 0
success: True
x: array([1., 0., 0., 0., 2., 0., 1., 1., 1.])
Process finished with exit code 0
I've done!
Videos of Caylie Cincera from youtube help me a lot. Illustration of the problem. Each location could receive at most of one supplier.
https://imgur.com/O2CNa9M
from pulp import *
#Pulp way to start a LP problem
prob = LpProblem("testpulp",LpMinimize)
#The 9 Arcs Origin and destiny
x1 = LpVariable("x1_11",0,None,LpInteger)
x2 = LpVariable("x2_12",0,None,LpInteger)
x3 = LpVariable("x3_13",0,None,LpInteger)
x4 = LpVariable("x4_21",0,None,LpInteger)
x5 = LpVariable("x5_22",0,None,LpInteger)
x6 = LpVariable("x6_23",0,None,LpInteger)
x7 = LpVariable("x7_31",0,None,LpInteger)
x8 = LpVariable("x8_32",0,None,LpInteger)
x9 = LpVariable("x9_33",0,None,LpInteger)
#Auxiliar Variables z y and k
z1 = LpVariable("z1",0,1,LpBinary)
z2 = LpVariable("z2",0,1,LpBinary)
z3 = LpVariable("z3",0,1,LpBinary)
y1 = LpVariable("y1",0,1,LpBinary)
y2 = LpVariable("y2",0,1,LpBinary)
y3 = LpVariable("y3",0,1,LpBinary)
k1 = LpVariable("k1",0,1,LpBinary)
k2 = LpVariable("k2",0,1,LpBinary)
k3 = LpVariable("k3",0,1,LpBinary)
#Objective Function
prob += 2*x1 + 4*x2+ 6*x3 + 4*x4 + 2*x5 + 4*x6 + 6*x7 + 4*x8 + 2*x9, "fobj"
#Constraints
#Supply constraints
prob += x1 + x2 + x3 == 1, "m1"
prob += x4 + x5 + x6 == 2, "m2"
prob += x7 + x8 + x9 == 3, "m3"
#Demand constraints
prob += x1 + x4 + x7 == 2, "d1"
prob += x2 + x5 + x8 == 3, "r2"
prob += x3 + x6 + x9 == 1, "r4"
#Trick to force unique supplier for each location
prob += x1 <= 2*y1, "yx1"
prob += x4 <= 2*y2, "yx2"
prob += x7 <= 2*y3, "yx3"
prob += x2 <= 3*z1, "zx1"
prob += x5 <= 3*z2, "zx2"
prob += x8 <= 3*z3, "zx3"
prob += x3 <= 1*k1, "kx1"
prob += x6 <= 1*k2, "kx2"
prob += x9 <= 1*k3, "kx3"
prob += y1 + y2 + y3 == 1, "yk"
prob += z1 + z2 + z3 == 1, "zk"
prob += k1 + k2 + k3 == 1, "kk"
prob.solve()
for v in prob.variables():
print(v.name, " = ", v.varValue)
print("Total Profit: ",value(prob.objective))
#The "optimal" solution of this problem is the unique solution
#The hard part is to force unique supplier for each location
The output:
k1 = 1.0
k2 = 0.0
k3 = 0.0
x1_11 = 0.0
x2_12 = 0.0
x3_13 = 1.0
x4_21 = 2.0
x5_22 = 0.0
x6_23 = 0.0
x7_31 = 0.0
x8_32 = 3.0
x9_33 = 0.0
y1 = 0.0
y2 = 1.0
y3 = 0.0
z1 = 0.0
z2 = 0.0
z3 = 1.0
Total Profit: 26.0
Process finished with exit code 0
Suppose I have a dataframe with n rows:
Index data1 data2 data3
0 x0 x0 x0
1 x1 x1 x1
2 x2 x2 x2
...
n xn xn xn
How do I create a new dataframe (using pandas) with k copies of each row appended to itself:
Index data1 data2 data3
0 x0 x0 x0
1 x0 x0 x0
...
k-1 x0 x0 x0
k x1 x1 x1
k+1 x1 x1 x1
...
2k-1 x1 x1 x1
2k x2 x2 x2
...
First concat, then sort
The method I'd use is to create a list of duplicate dataframes, concat them together, and then sort_index:
count = 5
new_df = pd.concat([df]*count).sort_index()
Using numpy.repeat and .iloc In here, k=2
df.iloc[np.repeat(np.arange(len(df)), 3)]
Out[256]:
Index data1 data2 data3
0 0 x0 x0 x0
0 0 x0 x0 x0
0 0 x0 x0 x0
1 1 x1 x1 x1
1 1 x1 x1 x1
1 1 x1 x1 x1
2 2 x2 x2 x2
2 2 x2 x2 x2
2 2 x2 x2 x2
Option 1
Use repeat + reindex + reset_index:
df
data1 data2 data3
0 x0 x0 x0
1 x1 x1 x1
2 x2 x2 x2
df.reindex(df.index.repeat(5)).reset_index(drop=1)
data1 data2 data3
0 x0 x0 x0
1 x0 x0 x0
2 x0 x0 x0
3 x0 x0 x0
4 x0 x0 x0
5 x1 x1 x1
6 x1 x1 x1
7 x1 x1 x1
8 x1 x1 x1
9 x1 x1 x1
10 x2 x2 x2
11 x2 x2 x2
12 x2 x2 x2
13 x2 x2 x2
14 x2 x2 x2
Option 2
Similar solution with repeat + pd.DataFrame:
pd.DataFrame(np.repeat(df.values, 5, axis=0), columns=df.columns)
data1 data2 data3
0 x0 x0 x0
1 x0 x0 x0
2 x0 x0 x0
3 x0 x0 x0
4 x0 x0 x0
5 x1 x1 x1
6 x1 x1 x1
7 x1 x1 x1
8 x1 x1 x1
9 x1 x1 x1
10 x2 x2 x2
11 x2 x2 x2
12 x2 x2 x2
13 x2 x2 x2
14 x2 x2 x2
Comparisons
%timeit pd.concat([df] * 100000).sort_index().reset_index(drop=1)
1 loop, best of 3: 14.6 s per loop
%timeit df.iloc[np.repeat(np.arange(len(df)), 100000)].reset_index(drop=1)
10 loops, best of 3: 22.6 ms per loop
%timeit df.reindex(df.index.repeat(100000)).reset_index(drop=1)
10 loops, best of 3: 19.9 ms per loop
%timeit pd.DataFrame(np.repeat(df.values, 100000, axis=0), columns=df.columns)
100 loops, best of 3: 17.1 ms per loop
I have a .csv file with the following format:
A B C D E F
X1 X2 X3 X4 X5 X6
Y1 Y2 Y3 Y4 Y5 Y6
Z1 Z2 Z3 Z4 Z5 Z6
What I want:
A X1
B X2
C X3
D X4
E X5
F X6
A Y1
B Y2
C Y3
D Y4
E Y5
F Y6
A Z1
B Z2
C Z3
D Z4
E Z5
F Z6
I am unable to wrap my mind around the built-in transpose functions in order to achieve the final result. Any help would be appreciated.
You can simply melt your dataframe using pandas:
import pandas as pd
df = pd.read_csv(csv_filename)
>>> pd.melt(df)
variable value
0 A X1
1 A Y1
2 A Z1
3 B X2
4 B Y2
5 B Z2
6 C X3
7 C Y3
8 C Z3
9 D X4
10 D Y4
11 D Z4
12 E X5
13 E Y5
14 E Z5
15 F X6
16 F Y6
17 F Z6
A pure python solution would be as follows:
file_out_delimiter = ',' # Use '\t' for tab delimited.
with open(filename, 'r') as f, open(filename_out, 'w') as f_out:
headers = f.readline().split()
for row in f:
for pair in zip(headers, row.split()):
f_out.write(file_out_delimiter.join(pair) + '\n')
resulting in the following file contents:
A,X1
B,X2
C,X3
D,X4
E,X5
F,X6
A,Y1
B,Y2
C,Y3
D,Y4
E,Y5
F,Y6
A,Z1
B,Z2
C,Z3
D,Z4
E,Z5
F,Z6