Related
python code:
import tkinter as tk
import pandas as pd
from tkinter import filedialog
from tkinter import constants as tk
root = tk.Tk()
def load_file():
filepath = filedialog.askopenfilename()
# Use the filepath to read the Excel file
df = pd.read_excel(filepath)
# Do something with the dataframe
result_text.delete(1.0, tk.END)
for index, row in df.iterrows():
selected_containers = select_container(row['length'], row['width'], row['height'], row['weight'], row['volume'],
row['stackable'])
if selected_containers:
result_text.insert(tk.END,
f'Cargo with dimension {row["length"]} x {row["width"]} x {row["height"]} with weight {row["weight"]} and volume {row["volume"]} can be loaded into the following container(s):\n')
for container in selected_containers:
result_text.insert(tk.END, f'{container.type}\n')
container.cargoes.append(
{'length': row['length'], 'width': row['width'], 'height': row['height'], 'weight': row['weight'],
'stackable': row['stackable']})
container.remaining_weight -= row['weight']
load_button = tk.Button(root, text="PAKET LİSTESİNİ YÜKLE BABAYIĞIT", command=load_file)
load_button.pack()
root.mainloop()
def select_container(cargo_length, cargo_width, cargo_height, cargo_weight, cargo_volume, cargo_stackable):
container_types = [
Container('20ft', 20, 8, 8.5, 24000, 33, 9.6),
Container('40ft', 40, 8, 8.5, 40000, 67, 9.6),
Container('40ft HC', 40, 8, 9.6, 40000, 76, 9.6),
Container('45ft', 45, 8.6, 9.6, 40000, 86.5, 9.6),
Container('53ft', 53, 8.6, 9.6, 40000, 98.5, 9.6),
Container('45ft', 45, 8, 9.6,40000, 76,9.6),
Container('Open Top', 40, 8, 9.6,40000, 76,9.6),
Container('Flat Rack', 40, 8, 9.6,40000, 76,9.6)
]
for container in container_types:
if cargo_length <= container.length and cargo_width <= container.width and cargo_height <= (container.height if not cargo_stackable else container.stackable_height) and cargo_weight <= container.remaining_weight and cargo_volume <= container.remaining_volume:
container.cargoes.append({'length': cargo_length, 'width': cargo_width, 'height': cargo_height, 'weight': cargo_weight, 'volume': cargo_volume, 'stackable': cargo_stackable})
container.remaining_weight -= cargo_weight
container.remaining_volume -= cargo_volume
return container
return None
class Container:
def _init_(self,type,length,width,height,weight,volume,stackable_height):
self.type = type
self.length = length
self.width = width
self.height = height
self.weight = weight
self.volume = volume
self.stackable_height = stackable_height
self.cargoes = []
self.remaining_weight = weight
self.remaining_volume = volume
def _str_(self):
return f'Type: {self.type} Dimensions: {self.length} x {self.width} x {self.height} Weight capacity: {self.weight} Volume capacity: {self.volume}'
def load_file():
filepath = filedialog.askopenfilename()
df = pd.read_excel()
result_text.delete(1.0, END)
Purpose of the code: It will tell us the number and type of container we should use, according to the package features we will load, the width, height and weight of the cargoes.
It uses tkinter for interface and pandas for reading excel. You can see it in the code.
sample packing list
I have a large customer data set (10 million+) , that I am running my loop calculation. I am trying to add multiprocessing, but it seems to take longer when I use multiprocessing, by splitting data1 into chunks running it in sagemaker studio. I am not sure what I am doing wrong but the calculation takes longer when using multiprocessing, please help.
input data example:
state_list = ['A','B','C','D','E'] #possible states
data1 = pd.DataFrame({"cust_id": ['x111','x112'], #customer data
"state": ['B','E'],
"amount": [1000,500],
"year":[3,2],
"group":[10,10],
"loan_rate":[0.12,0.13]})
data1['state'] = pd.Categorical(data1['state'],
categories=state_list,
ordered=True).codes
lookup1 = pd.DataFrame({'year': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'lim %': [0.1, 0.1, 0.1, 0.1, 0.1,0.1, 0.1, 0.1, 0.1, 0.1]}).set_index(['year'])
matrix_data = np.arange(250).reshape(10,5,5) #3d matrix by state(A-E) and year(1-10)
end = pd.Timestamp(year=2021, month=9, day=1) # creating a list of dates
df = pd.DataFrame({"End": pd.date_range(end, periods=10, freq="M")})
df['End']=df['End'].dt.day
End=df.values
end_dates = End.reshape(-1) # array([30, 31, 30, 31, 31, 28, 31, 30, 31, 30]); just to simplify access to the end date values
calculation:
num_processes = 4
# Split the customer data into chunks
chunks = np.array_split(data1, num_processes)
queue = mp.Queue()
def calc(chunk):
results1={}
for cust_id, state, amount, start, group, loan_rate in chunks.itertuples(name=None, index=False):
res1 = [amount * matrix_data[start-1, state, :]]
for year in range(start+1, len(matrix_data)+1,):
res1.append(lookup1.loc[year].iat[0] * np.array(res1[-1]))
res1.append(res1[-1] * loan_rate * end_dates[year-1]/365) # year - 1 here
res1.append(res1[-1]+ 100)
res1.append(np.linalg.multi_dot([res1[-1],matrix_data[year-1]]))
results1[cust_id] = res1
queue.put(results1)
processes = [mp.Process(target=calc, args=(chunk,)) for chunk in chunks]
for p in processes:
p.start()
for p in processes:
p.join()
results1 = {}
while not queue.empty():
results1.update(queue.get())
I think it would be easier to use a multiprocessing pool with the map method, which will submit tasks in chunks anyway but your worker function calc just needs to deal with individuals tuples since the chunking is done in a transparent function. The pool will compute what it thinks is an optimal number of rows to be chunked together based on the total number of rows and the number of processes in the pool, but you can override this. So a solution would look something like the following. Since you have not tagged your question with the OS you are running under, the code below should run under Windows, Linux or MacOS in the most efficient way for that platform. But as I mentioned in a comment, multiprocessing may actually slow down getting your results if calc is not sufficiently CPU-intensive.
from multiprocessing import Pool
import pandas as pd
import numpy as np
def init_pool_processes(*args):
global lookup1, matrix_data, end_dates
lookup1, matrix_data, end_dates = args # unpack
def calc(t):
cust_id, state, amount, start, group, loan_rate = t # unpack
results1 = {}
res1 = [amount * matrix_data[start-1, state, :]]
for year in range(start+1, len(matrix_data)+1,):
res1.append(lookup1.loc[year].iat[0] * np.array(res1[-1]))
res1.append(res1[-1] * loan_rate * end_dates[year-1]/365) # year - 1 here
res1.append(res1[-1] + 100)
return (cust_id, res1) # return tuple
def main():
state_list = ['A','B','C','D','E'] #possible states
data1 = pd.DataFrame({"cust_id": ['x111','x112'], #customer data
"state": ['B','E'],
"amount": [1000,500],
"year":[3,2],
"group":[10,10],
"loan_rate":[0.12,0.13]})
data1['state'] = pd.Categorical(data1['state'],
categories=state_list,
ordered=True).codes
lookup1 = pd.DataFrame({'year': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'lim %': [0.1, 0.1, 0.1, 0.1, 0.1,0.1, 0.1, 0.1, 0.1, 0.1]}).set_index(['year'])
matrix_data = np.arange(250).reshape(10,5,5) #3d matrix by state(A-E) and year(1-10)
end = pd.Timestamp(year=2021, month=9, day=1) # creating a list of dates
df = pd.DataFrame({"End": pd.date_range(end, periods=10, freq="M")})
df['End']=df['End'].dt.day
End=df.values
end_dates = End.reshape(-1) # array([30, 31, 30, 31, 31, 28, 31, 30, 31, 30]); just to simplify access to the end date values
with Pool(initializer=init_pool_processes, initargs=(lookup1, matrix_data, end_dates)) as pool:
results = {cust_id: arr for cust_id, arr in pool.map(calc, data1.itertuples(name=None, index=False))}
for cust_id, arr in results.items():
print(cust_id, arr)
if __name__ == '__main__':
main()
Prints:
x111 [array([55000, 56000, 57000, 58000, 59000]), array([5500., 5600., 5700., 5800., 5900.]), array([56.05479452, 57.0739726 , 58.09315068, 59.11232877, 60.13150685]), array([156.05479452, 157.0739726 , 158.09315068, 159.11232877,
160.13150685]), array([15.60547945, 15.70739726, 15.80931507, 15.91123288, 16.01315068]), array([0.15904763, 0.16008635, 0.16112507, 0.1621638 , 0.16320252]), array([100.15904763, 100.16008635, 100.16112507, 100.1621638 ,
100.16320252]), array([10.01590476, 10.01600864, 10.01611251, 10.01621638, 10.01632025]), array([0.09220121, 0.09220216, 0.09220312, 0.09220407, 0.09220503]), array([100.09220121, 100.09220216, 100.09220312, 100.09220407,
100.09220503]), array([10.00922012, 10.00922022, 10.00922031, 10.00922041, 10.0092205 ]), array([0.10201178, 0.10201178, 0.10201178, 0.10201178, 0.10201178]), array([100.10201178, 100.10201178, 100.10201178, 100.10201178,
100.10201178]), array([10.01020118, 10.01020118, 10.01020118, 10.01020118, 10.01020118]), array([0.09873075, 0.09873075, 0.09873075, 0.09873075, 0.09873075]), array([100.09873075, 100.09873075, 100.09873075, 100.09873075,
100.09873075]), array([10.00987308, 10.00987308, 10.00987308, 10.00987308, 10.00987308]), array([0.10201843, 0.10201843, 0.10201843, 0.10201843, 0.10201843]), array([100.10201843, 100.10201843, 100.10201843, 100.10201843,
100.10201843]), array([10.01020184, 10.01020184, 10.01020184, 10.01020184, 10.01020184]), array([0.09873076, 0.09873076, 0.09873076, 0.09873076, 0.09873076]), array([100.09873076, 100.09873076, 100.09873076, 100.09873076,
100.09873076])]
x112 [array([22500, 23000, 23500, 24000, 24500]), array([2250., 2300., 2350., 2400., 2450.]), array([24.04109589, 24.57534247, 25.10958904, 25.64383562, 26.17808219]), array([124.04109589, 124.57534247, 125.10958904, 125.64383562,
126.17808219]), array([12.40410959, 12.45753425, 12.5109589 , 12.56438356, 12.61780822]), array([0.13695496, 0.13754483, 0.1381347 , 0.13872456, 0.13931443]), array([100.13695496, 100.13754483, 100.1381347 , 100.13872456,
100.13931443]), array([10.0136955 , 10.01375448, 10.01381347, 10.01387246, 10.01393144]), array([0.11056217, 0.11056282, 0.11056347, 0.11056413, 0.11056478]), array([100.11056217, 100.11056282, 100.11056347, 100.11056413,
100.11056478]), array([10.01105622, 10.01105628, 10.01105635, 10.01105641, 10.01105648]), array([0.09983629, 0.09983629, 0.09983629, 0.09983629, 0.09983629]), array([100.09983629, 100.09983629, 100.09983629, 100.09983629,
100.09983629]), array([10.00998363, 10.00998363, 10.00998363, 10.00998363, 10.00998363]), array([0.11052119, 0.11052119, 0.11052119, 0.11052119, 0.11052119]), array([100.11052119, 100.11052119, 100.11052119, 100.11052119,
100.11052119]), array([10.01105212, 10.01105212, 10.01105212, 10.01105212, 10.01105212]), array([0.10696741, 0.10696741, 0.10696741, 0.10696741, 0.10696741]), array([100.10696741, 100.10696741, 100.10696741, 100.10696741,
100.10696741]), array([10.01069674, 10.01069674, 10.01069674, 10.01069674, 10.01069674]), array([0.11052906, 0.11052906, 0.11052906, 0.11052906, 0.11052906]), array([100.11052906, 100.11052906, 100.11052906, 100.11052906,
100.11052906]), array([10.01105291, 10.01105291, 10.01105291, 10.01105291, 10.01105291]), array([0.10696741, 0.10696741, 0.10696741, 0.10696741, 0.10696741]), array([100.10696741, 100.10696741, 100.10696741, 100.10696741,
100.10696741])]
If you wish to save memory, you could use method imap_unordered:
def main():
... # code omitted
def compute_chunksize(iterable_size, pool_size):
chunksize, remainder = divmod(iterable_size, 4 * pool_size)
if remainder:
chunksize += 1
return chunksize
from multiprocessing import cpu_count
pool_size = cpu_count()
iterable_size = 100_000 # Your best estimate
chunksize = compute_chunksize(iterable_size, pool_size)
with Pool(pool_size, initializer=init_pool_processes, initargs=(lookup1, matrix_data, end_dates)) as pool:
it = pool.imap_unordered(calc, data1.itertuples(name=None, index=False), chunksize=chunksize)
"""
# Create dictionary in memory:
results = {cust_id: arr for cust_id, arr in it}
"""
# Or to save memory, iterate the results:
for cust_id, arr in it:
print(cust_id, arr)
if __name__ == '__main__':
main()
So i am traying to make a cycle that gives different sankey diagram the thing is due to the plotly optimization the node are in different positions. I will like to set the standard order to be [Formal, Informal, Unemployed, Inactive]
import matplotlib.pyplot as plt
import pandas as pd
import plotly.graph_objects as go
df = pd.read_csv(path, delimiter=",")
Lista_Paises = df["code"].unique().tolist()
Lista_DF = []
for x in Lista_Paises:
DF_x = df[df["code"] == x]
Lista_DF.append(DF_x)
def grafico(df):
df = df.astype({"Source": "category", "Value": "float", "Target": "category"})
def category(i):
if i == "Formal":
return 0
if i == "Informal":
return 1
if i == "Unemployed":
return 2
if i == "Inactive":
return 3
def color(i):
if i == "Formal":
return "#9FB5D5"
if i == "Informal":
return "#E3EEF9"
if i == "Unemployed":
return "#E298AE"
if i == "Inactive":
return "#FCEFBC"
df['Source_cat'] = df["Source"].apply(category).astype("int")
df['Target_cat'] = df["Target"].apply(category).astype("int")
# df['Source_cat'] = LabelEncoder().fit_transform(df.Source)
# df['Target_cat'] = LabelEncoder().fit_transform(df.Target)
df["Color"] = df["Source"].apply(color).astype("str")
df = df.sort_values(by=["Source_cat", "Target_cat"])
Lista_Para_Sumar = df["Source_cat"].nunique()
Lista_Para_Tags = df["Source"].unique().tolist()
Suma = Lista_Para_Sumar
df["out"] = df["Target_cat"] + Suma
TAGS = Lista_Para_Tags + Lista_Para_Tags
Origen = df['Source_cat'].tolist()
Destino = df["out"].tolist()
Valor = df["Value"].tolist()
Color = df["Color"].tolist()
return (TAGS, Origen, Destino, Valor, Color)
def Sankey(TAGS: object, Origen: object, Destino: object, Valor: object, Color: object, titulo: str) -> object:
label = TAGS
source = Origen
target = Destino
value = Valor
link = dict(source=source, target=target, value=value,
color=Color)
node = dict(x=[0, 0, 0, 0, 1, 1, 1, 1], y=[1, 0.75, 0.5, 0.25, 0, 1, 0.75, 0.5, 0.25, 0], label=label, pad=35,
thickness=10,
color=["#305CA3", "#C1DAF1", "#C9304E", "#F7DC70", "#305CA3", "#C1DAF1", "#C9304E", "#F7DC70"])
data = go.Sankey(link=link, node=node, arrangement='snap')
fig = go.Figure(data)
fig.update_layout(title_text=titulo + "-" + "Mujeres", font_size=10, )
plt.plot(alpha=0.01)
titulo_guardar = (str(titulo) + ".png")
fig.write_image("/Users/agudelo/Desktop/GRAFICOS PNUD/Graficas/MUJERES/" + titulo_guardar, engine="kaleido")
for y in Lista_DF:
TAGS, Origen, Destino, Valor, Color = grafico(y)
titulo = str(y["code"].unique())
titulo = titulo.replace("[", "")
titulo = titulo.replace("]", "")
titulo = titulo.replace("'", "")
Sankey(TAGS, Origen, Destino, Valor, Color, titulo)
The expected result should be.
The expected result due to the correct order:
The real result i am getting is:
I had a similar problem earlier. I hope this will work for you. As I did not have your data, I created some dummy data. Sorry about the looooong explanation. Here are the steps that should help you reach your goal...
This is what I did:
Order the data and sort it - used pd.Categorical to set the order and then df.sort to sort the data so that the input is sorted by source and then destination.
For the sankey node, you need to set the x and y positions. x=0, y=0 starts at top left. This is important as you are telling plotly the order you want the nodes. One weird thing is that it sometimes errors if x or y is at 0 or 1. Keep it very close, but not the same number... wish I knew why
For the other x and y entries, I used ratios as my total adds up to 285. For eg. Source-Informal starts at x = 0.001 and y = 75/285 as Source-Formal = 75 and this will start right after that
Based on step 1, the link -> source and destination should also be sorted. But, pls do check.
Note: I didn't color the links, but think you already have achieved that...
Hope this helps resolve your issue...
My data - sankey.csv
source,destination,value
Formal,Formal,20
Formal,Informal, 10
Formal,Unemployed,30
Formal,Inactive,15
Informal,Formal,20
Informal,Informal,15
Informal,Unemployed,25
Informal,Inactive,25
Unemployed,Formal,5
Unemployed,Informal,10
Unemployed,Unemployed,10
Unemployed,Inactive,5
Inactive,Formal,30
Inactive,Informal,20
Inactive,Unemployed,20
Inactive,Inactive,25
The code
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv('sankey.csv') #Read above CSV
#Sort by Source and then Destination
df['source'] = pd.Categorical(df['source'], ['Formal','Informal', 'Unemployed', 'Inactive'])
df['destination'] = pd.Categorical(df['destination'], ['Formal','Informal', 'Unemployed', 'Inactive'])
df.sort_values(['source', 'destination'], inplace = True)
df.reset_index(drop=True)
mynode = dict(
pad = 15,
thickness = 20,
line = dict(color = "black", width = 0.5),
label = ['Formal', 'Informal', 'Unemployed', 'Inactive', 'Formal', 'Informal', 'Unemployed', 'Inactive'],
x = [0.001, 0.001, 0.001, 0.001, 0.999, 0.999, 0.999, 0.999],
y = [0.001, 75/285, 160/285, 190/285, 0.001, 75/285, 130/285, 215/285],
color = ["#305CA3", "#C1DAF1", "#C9304E", "#F7DC70", "#305CA3", "#C1DAF1", "#C9304E", "#F7DC70"])
mylink = dict(
source = [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 ],
target = [ 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7 ],
value = df.value.to_list())
fig = go.Figure(data=[go.Sankey(
arrangement='snap',
node = mynode,
link = mylink
)])
fig.update_layout(title_text="Basic Sankey Diagram", font_size=20)
fig.show()
The output
I am trying to solve a linear programming problem using IBM's CPLEX Python API. It involves two sets of equality constraints. The code below works fine when we use either one of the two sets of constraints, but fails to find a solution when both sets of constraints are used.
The constraints are:
First constraint: Wx' = c', where W = [[20,0,0],[0,20,30]], x = [a,b,c], c=[20,30]
Second constraint: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
Objective function: minimize a + c
One solution which meets both sets of constrains is a=1, b=0, c=1.
There is an error in the way I am introducing the two sets of constrains in Cplex Python. My code is below. To check that the code works with either set of constraints by itself comment out on of the sets of constraints.
import cplex
from cplex.exceptions import CplexError
import sys
def populatebynonzero(prob):
my_obj = [1.0, 0.0, 1.0]
my_ub = [1.0] * len(my_obj)
my_lb = [0.0] * len(my_obj)
my_colnames = ["a", "b", "c"]
prob.objective.set_sense(prob.objective.sense.minimize)
prob.variables.add(obj = my_obj, ub = my_ub, lb = my_lb ,names = my_colnames)
# first set of equality constraints: Wx' = c', where W = [[20,0,0],[0,20,30]], x = [a,b,c], c=[20,30]
my_rhs = [20.0, 30.0]
my_rownames = ["c1", "c2"]
my_sense = "E" * len(my_rownames)
rows = [0,1,1]
cols = [0,1,2]
vals = [20.0,20.0,30.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,0,1]
cols = [0,1,2]
vals = [1.0,1.0,1.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
def lpex1():
try:
my_prob = cplex.Cplex()
handle = populatebynonzero(my_prob)
my_prob.solve()
except CplexError, exc:
print exc
return
numrows = my_prob.linear_constraints.get_num()
numcols = my_prob.variables.get_num()
print
# solution.get_status() returns an integer code
print "Solution status = " , my_prob.solution.get_status(), ":",
# the following line prints the corresponding string
print my_prob.solution.status[my_prob.solution.get_status()]
print "Solution value = ", my_prob.solution.get_objective_value()
slack = my_prob.solution.get_linear_slacks()
pi = my_prob.solution.get_dual_values()
x = my_prob.solution.get_values()
dj = my_prob.solution.get_reduced_costs()
for i in range(numrows):
print "Row %d: Slack = %10f Pi = %10f" % (i, slack[i], pi[i])
for j in range(numcols):
print "Column %d: Value = %10f Reduced cost = %10f" % (j, x[j], dj[j])
my_prob.write("lpex1.lp")
print x, "SOLUTIONS"
lpex1()
It works if the two sets of constraints are combined into one matrix in the following way, though it would be good to find a solution which does not have to do combining
import cplex
from cplex.exceptions import CplexError
import sys
def populatebynonzero(prob):
my_obj = [1.0, 0.0, 1.0]
my_ub = [1.0] * len(my_obj)
my_lb = [0.0] * len(my_obj)
my_colnames = ["a", "b", "c"]
prob.objective.set_sense(prob.objective.sense.minimize)
prob.variables.add(obj = my_obj, ub = my_ub, lb = my_lb ,names = my_colnames)
#combined constraints
my_rhs = [20.0, 30.0, 1.0, 1.0]
my_rownames = ["c1", "c2", "e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,1,1,2,2,3]
cols = [0,1,2,0,1,2]
vals = [20.0,20.0,30.0,1,1,1]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
"""
# first set of equality constraints: Wx' = c', where W = [[20,0,0],[0,20,30]], x = [a,b,c], c=[20,30]
my_rhs = [20.0, 30.0]
my_rownames = ["c1", "c2"]
my_sense = "E" * len(my_rownames)
rows = [0,1,1]
cols = [0,1,2]
vals = [20.0,20.0,30.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,0,1]
cols = [0,1,2]
vals = [1.0,1.0,1.0]
prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames)
prob.linear_constraints.set_coefficients(zip(rows, cols, vals))
"""
def lpex1():
try:
my_prob = cplex.Cplex()
handle = populatebynonzero(my_prob)
my_prob.solve()
except CplexError, exc:
print exc
return
numrows = my_prob.linear_constraints.get_num()
numcols = my_prob.variables.get_num()
print
# solution.get_status() returns an integer code
print "Solution status = " , my_prob.solution.get_status(), ":",
# the following line prints the corresponding string
print my_prob.solution.status[my_prob.solution.get_status()]
print "Solution value = ", my_prob.solution.get_objective_value()
slack = my_prob.solution.get_linear_slacks()
pi = my_prob.solution.get_dual_values()
x = my_prob.solution.get_values()
dj = my_prob.solution.get_reduced_costs()
for i in range(numrows):
print "Row %d: Slack = %10f Pi = %10f" % (i, slack[i], pi[i])
for j in range(numcols):
print "Column %d: Value = %10f Reduced cost = %10f" % (j, x[j], dj[j])
my_prob.write("lpex1.lp")
print x, "SOLUTIONS"
lpex1()
When you are attempting to create the second set of constraints, you are using the wrong indices for the rows:
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
rows = [0,0,1] # <- HERE
cols = [0,1,2]
vals = [1.0,1.0,1.0]
That is, you're using the row indices 0 and 1, which were created for the first set of constraints. Instead, you should do something like the following:
# second set of equality constraints: Vx' = e', where V = [[1,1,0],[0,0,1]], x = [a,b,c], c=[1,1]
my_rhs = [1.0, 1.0]
my_rownames = ["e1", "e2"]
my_sense = "E" * len(my_rownames)
cols = [0,1,2]
vals = [1.0,1.0,1.0]
rowindices = list(prob.linear_constraints.add(rhs = my_rhs, senses = my_sense,names = my_rownames))
assert len(rowindices) == 2
rows = [rowindices[0], rowindices[0], rowindices[1]]
prob.linear_constraints.set_coefficients(zip(rowindices, cols, vals))
Above, we get the new row indices from the call to prob.linear_constriants.add. With this change, the script works fine.
In addition, it's a good idea to write out the problem in LP format to make sure that it looks correct, like so:
prob.write("model.lp")
So as my first project in python outside of Code Academy, I decided to make a basic molecular dynamics simulator on pygame. It works fine for a while, but as soon as electrons start to move too fast, and strip all the other electrons off their atoms, I get the TypeError in the title. I have no idea where this comes from, and only appears after the program has been running long enough for me to mess up all the physics.
Now I know that the error is telling me that I'm trying to pass a list somewhere I shouldn't, but I've looked over the program and can't figure out where. The error pops up in the bit that tells electrons how to orbit their atom angle = findA(particles[el], particles[nuc]) + 0.001, which is controlled by the block of code near the end that tells the program in which order to do physics, and the list of what each electron is meant to orbit is controlled by another point, and so on.
So I decided just to give you all the code.
import sys, pygame, math
from pygame.locals import *
pygame.init()
sizeScreen = width, height = 1000, 700
sizeMenu = width, height = 652, 700
e = 1.6 * 10 ** -19
particles = {}
mx, my = 0, 0
selected = []
def findOrbital(el):
for a in particles:
if a != el and particles[a][4] != 'el':
if findD(particles[el], particles[a]) < 5 * 10 ** -11 and PTI[particles[a][4]][7] > len(particles[a][5]):
particles[a][5].append(el)
particles[el][5].append(a)
def searcher(List, item):
for a in List:
if a == item:
return True
return False
def moveAtEls(el, nuc):
angle = findA(particles[el], particles[nuc]) + 0.001
particles[el][0] = particles[nuc][0] + 50 * math.cos(angle)
particles[el][1] = particles[nuc][1] + 50 * math.sin(angle)
def check(each):
if particles[each][0] < 175:
particles[each][2] = -particles[each][2]
particles[each][0] = 175
elif particles[each][0] > 1000:
particles[each][2] = -particles[each][2]
particles[each][0] = 1000
if particles[each][1] < 0:
particles[each][3] = -particles[each][3]
particles[each][1] = 0
elif particles[each][1] > 700:
particles[each][3] = -particles[each][3]
particles[each][1] = 700
if particles[each][4] == 'el':
a = 'n'
findOrbital(each)
if a != 'n':
particles[each][5].append(a)
particles[a][5].append(each)
def findD(self, other):
return math.hypot((self[0] - other[0]), (self[1] - other[1])) * 0.62 * 10 ** -12
def findA(self, other):
return math.atan2((self[1] - other[1]), (self[0] - other[0]))
def move(self):
for other in particles:
if particles[other] != self and self[5] != particles[other] [5] and not searcher(self[5], other):
D = findD(self, particles[other])
if D == 0:
self[5].append(other)
particles[other][5].append(self)
break
angle = findA(self, particles[other])
F = 8987550000 * (PTI[self[4]][4] * PTI[particles[other][4]][4] * e ** 2)/D ** 2
a = int(F/PTI[self[4]][5])
ax = a * math.cos(angle)
ay = a * math.sin(angle)
self[2] += ax/(10 ** 16)
self[3] += ay/(10 ** 16)
self[0] += self[2]/(10 ** 8)
self[1] += self[3]/(10 ** 8)
pressed = ''
press = {'Katom':[2,148,2,32,0],'Knuc':[2,148,36,66,0],'Kel':[2,148,70,100,0]}
PTI = {'el':[0, 0, 0, 0, -1, 9.11 * 10 ** -31, pygame.image.load("electron.png"), 2],
'HNuc' : [185, 214, 8, 37, 1, 1.7 * 10 ** -27, pygame.image.load("nuc/HNuc.png"), 2, 1],
'HeNuc': [586, 613, 8, 37, 2, 6.6 * 10 ** -27, pygame.image.load("nuc/HeNuc.png"), 2, 2],
'LiNuc': [185, 214, 40, 69, 1, 1.16 * 10 ** -26, pygame.image.load("nuc/LiNuc.png"), 8, 1],
'BeNuc': [216, 246, 40, 69, 2, 1.53 * 10 ** -26, pygame.image.load("nuc/BeNuc.png"), 8, 2],
'BNuc' : [428, 457, 40, 69, 3, 1.84 * 10 ** -26, pygame.image.load("nuc/BNuc.png"), 8, 3],
'CNuc' : [460, 489, 40, 69, 4, 2.04 * 10 ** -26, pygame.image.load("nuc/CNuc.png"), 8, 4],
'NNuc' : [492, 520, 40, 69, 5, 2.38 * 10 ** -26, pygame.image.load("nuc/NNuc.png"), 8, 5],
'ONuc' : [523, 551, 40, 69, 6, 2.72 * 10 ** -26, pygame.image.load("nuc/ONuc.png"), 8, 6],
'FNuc' : [554, 583, 40, 69, 7, 3.23 * 10 ** -26, pygame.image.load("nuc/FNuc.png"), 8, 7],
'NeNuc': [586, 613, 40, 69, 8, 3.43 * 10 ** -26, pygame.image.load("nuc/NeNuc.png"), 8, 8]}
menu = pygame.display.set_mode(sizeMenu)
screenColor = pygame.Color(255, 255, 220)
screen = pygame.display.set_mode(sizeScreen)
edgeObj = pygame.image.load("edge.png")
addEl = [pygame.image.load('addElectron1.png'), pygame.image.load('addElectron2.png')]
addAtom = [pygame.image.load("addAtom1.png"), pygame.image.load("addAtom2.png"), pygame.image.load("atomTable.png")]
addNucleus = [pygame.image.load("addNuc1.png"), pygame.image.load("addNuc2.png"), pygame.image.load("NucTable.png")]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
elif event.type == MOUSEMOTION:
mx, my = event.pos
mouseState = pygame.mouse.get_pressed()
if mouseState[0]:
for key in press:
if press[key][0] < mx <press[key][1] and press[key][2] < my < press[key][3]:
pressed = key
press[key][4] = 1
if not mouseState[0] and pressed == 'Kel':
particles[len(particles)] = [mx, my, 0, 0, 'el', []]
pressed = ''
press['Kel'][4] = 0
if pressed != '':
if not mouseState[0]:
if press[pressed][0] < mx <press[pressed][1] and press[pressed][2] < my < press[pressed][3]:
press[pressed][4] = 2
pressed = ''
if press['Knuc'][4] == 2 or press['Katom'][4] == 2:
if mouseState[0]:
if 621 < mx < 651 and 2 < my < 14:
press['Knuc'][4] = 0
press['Katom'][4] = 0
if press['Knuc'][4] == 2:
for nuc in PTI:
if PTI[nuc][0] < mx < PTI[nuc][1] and PTI[nuc][2] < my < PTI[nuc][3]:
press['Knuc'][4] = 0
selected.append(nuc)
if press['Katom'][4] == 2:
for nuc in PTI:
if PTI[nuc][0] < mx < PTI[nuc][1] and PTI[nuc][2] < my < PTI[nuc][3]:
a = 0
selected.append(nuc)
while a < PTI[nuc][8]:
selected.append('el')
a += 1
press['Katom'][4] = 0
if selected != []:
if not mouseState[0]:
a = len(particles)
particles[a] = [mx, my, 0, 0, selected[0], [b for b in range(a+1, len(selected)-1)]]
for item in selected:
if item != selected[0]:
particles[len(particles)] = [mx, my, 0, 0, item, [a]]
selected = []
for each in particles:
check(each)
move(particles[each])
check(each)
if len(particles[each][5]) > 0 and particles[each][4] == 'el':
moveAtEls(each, particles[each][5][0])
particles[each][5] = []
screen.fill(screenColor)
for a in particles:
screen.blit(PTI[particles[a][4]][6], (particles[a][0] - 29, particles[a][1] - 31))
menu.blit(edgeObj, (0, 0))
menu.blit(addNucleus[press['Knuc'][4]], (2, 2))
menu.blit(addAtom[press['Katom'][4]], (2, 2))
menu.blit(addEl[press['Kel'][4]], (2, 2))
pygame.display.flip()
Sorry if I'm being a nuisance by posting all the code, but I'm a complete n00b and I'm surprised I got this far without help. I know the whole thing is untidy, but if you could help with the error I'd greatly appreciate it.
Next time I'll just stick to print("Hello, World!")
So, what I believe is happening is that when execute the line angle = findA(particles[el], particles[nuc]) + 0.001, either the el variable or the nuc variable is a list of some sort, rather then a single object.
This throws an error because particles is a dict, and you cannot have a list or any mutable type as a key in a dict.
So, given that this error does not execute immediately, I suspect that somewhere along the line, in a piece of code that is not immediately executed, you are accidentally passing in a list of some sort.
If you did mean to look things up in the particles dict by using a list as a key, then you should convert the list to a tuple first: tuples are like lists, but are immutable, and so can be hashed and used as a key of a dict.