Spaces:
Build error
Build error
import numpy as np | |
from copy import deepcopy | |
from math import * | |
from collections import * | |
import sys | |
import streamlit as st | |
import time | |
def main(): | |
st.set_page_config(page_title="Wood Cutting Algorithm") | |
start_time = time.time() | |
lst = [] | |
n = st.number_input( | |
"Enter number of different types of wood sizes: ", min_value=1, step=1 | |
) | |
for i in range(0, n): | |
ele = [ | |
st.number_input( | |
"Enter number " + str(i) + " wood size: ", min_value=1, step=1 | |
), | |
st.number_input( | |
"Enter number " + str(i) + " quantity: ", min_value=1, step=1 | |
), | |
] | |
lst.append(ele) | |
cuts_dict = dict(lst) | |
cuts = list(cuts_dict.keys()) | |
def getDesired(des_dict, Bo="No"): | |
if Bo == "No": | |
return des_dict | |
exis = st.selectbox("Is there existing inventory?", ["Yes", "No"]) | |
if exis == "Yes": | |
for i in des_dict.keys(): | |
val = st.number_input( | |
"How many boards of %d size are in existing inventory: " % i, | |
min_value=0, | |
step=1, | |
) | |
des_dict[i] = (des_dict[i] - val) if des_dict[i] >= val else 0 | |
st.write(des_dict) | |
return des_dict | |
def getMin(des, prov): | |
minQua = sum([(k * v) for k, v in des.items()]) / prov | |
return dict(minQua) | |
def expansion(des): | |
cutlist = [] | |
for k, v in des.items(): | |
cutlist += [k] * v | |
return cutlist | |
def simplify(des, prov): | |
for i in des.keys(): | |
val = prov // i | |
des[i] = val if val <= des[i] else des[i] | |
return des | |
def optimization(sols, des, prov): | |
des_keys = list(des.keys()) | |
min_c = [] | |
for i in range(len(prov)): | |
min_c += [prov[i]] * len(sols[i]) | |
c = np.array(min_c) | |
A = [[] for i in range(len(des))] | |
for i in range(len(sols)): | |
for j in range(len(sols[0])): | |
for k in range(len(des)): | |
A[k].append(sols[i][j][des_keys[k]]) | |
B = [((-1) * des[k]) for k in des.keys()] | |
print(B) | |
pass | |
def modulize(des, prov1, prov2, res, res_complete): | |
if len(des.keys()) == 0: | |
return res_complete | |
if min(des.keys()) > prov2: | |
return res_complete | |
des2 = deepcopy(des) | |
for i in des.keys(): | |
des2.pop(i) | |
if prov2 % i == 0: | |
cnt = prov2 // i | |
if cnt > des[i]: | |
continue | |
res += [i] * cnt | |
if sum(res) == prov1: | |
res_complete.append(res) | |
res = [] | |
if prov2 >= i: | |
cnt = prov2 // i | |
if cnt > des[i]: | |
cnt = des[i] | |
for coun in range(1, cnt + 1): | |
remain = prov2 - (coun * i) | |
res_min = [i] * coun | |
res_complete = modulize( | |
des2, prov1, remain, res + res_min, res_complete | |
) | |
return res_complete | |
def generate_cut_list(cut_dict): | |
cut_list = [] | |
for key, value in cut_dict.items(): | |
for i in range(value): | |
cut_list.append(int(key)) | |
return cut_list | |
def wood_cutting(cut_list, sheet_size, max_sheets): | |
sheets = 0 | |
rem_sheets = [0] * max_sheets | |
cuts_per_sheet = [] | |
# loops through all cuts | |
for i in range(len(cut_list)): | |
j = 0 | |
# Algorithm to find the best sheet to assign the cut | |
min_waste = sheet_size + 1 | |
best_index = 0 | |
for j in range(sheets): | |
if ( | |
rem_sheets[j] >= cut_list[i] | |
and rem_sheets[j] - cut_list[i] < min_waste | |
): | |
best_index = j | |
min_waste = rem_sheets[j] - cut_list[i] | |
# If no sheet can accommodate the cut, then we create new sheet | |
if min_waste == sheet_size + 1: | |
rem_sheets[sheets] = sheet_size - cut_list[i] | |
cuts_per_sheet.append([cut_list[i]]) | |
sheets += 1 | |
# Assign the cut to best sheet | |
else: | |
rem_sheets[best_index] -= cut_list[i] | |
cuts_per_sheet[best_index].append(cut_list[i]) | |
return (sheets, cuts_per_sheet, rem_sheets[:sheets]) | |
def print_patterns(final, fid): | |
fin = [] | |
for i in final: | |
fin.append(dict(Counter(i))) | |
print(dict(Counter(i)), file=fid) | |
return fin | |
def usable(waste): | |
if 0 in list(waste.keys()): | |
waste.pop(0) | |
usable_w = dict() | |
unusable_w = dict() | |
for k in waste.keys(): | |
if k >= min(cuts): | |
usable_w[k] = waste[k] | |
else: | |
unusable_w[k] = waste[k] | |
return [usable_w, unusable_w] | |
def outPrint(final): | |
for i in final: | |
print(Counter(i)) | |
return | |
def outComp(final1, final2): | |
for i in final1: | |
if i not in final2: | |
print(i) | |
for x in final2: | |
if x not in final1: | |
print(x) | |
return | |
def dictComp(dict1, dict2): | |
for key in list(dict1.keys()): | |
try: | |
if dict1[key] < dict2.get(key, 0): | |
return -1 | |
except: | |
return -1 | |
return 1 | |
def dictSub(dict1, dict2): | |
dict3 = {key: dict1[key] - dict2.get(key, 0) for key in dict1.keys()} | |
return dict3 | |
def mod_key(key, res): | |
key_c = [] | |
for dict_res in res: | |
if key in dict_res.keys(): | |
key_c.append(dict_res) | |
return key_c | |
def list_to_dict(final, target): | |
fin = [] | |
for i in final: | |
if sum(i) == target: | |
if dict(Counter(i)) not in fin: | |
fin.append(dict(Counter(i))) | |
return fin | |
des = getDesired(cuts_dict, "Yes") | |
prov = st.number_input("Enter sheet size (in cm): ", min_value=1, step=1) | |
sols = [] | |
des = simplify(des, prov) | |
sols.append(modulize(des, prov, prov, [], [])) | |
sols = [x for x in sols if x] | |
sols = [expansion(des) + x for x in sols] | |
waste = [] | |
for i in sols: | |
waste.append(prov - sum(i)) | |
min_waste = min(waste) | |
sols_waste = [sols[x] for x in range(len(waste)) if waste[x] == min_waste] | |
final = [] | |
for sol in sols_waste: | |
sheets, cuts_per_sheet, waste_per_sheet = wood_cutting( | |
generate_cut_list(cuts_dict), prov, len(sol) | |
) | |
if not waste_per_sheet: | |
final.append(sol) | |
else: | |
for i in range(len(sol)): | |
if waste_per_sheet[i] == 0: | |
continue | |
else: | |
temp_sol = deepcopy(sol) | |
temp_sol.remove(sol[i]) | |
temp_sol += [waste_per_sheet[i]] | |
temp_sol = sorted(temp_sol) | |
if temp_sol not in final: | |
final.append(temp_sol) | |
st.write("Output:") | |
out = print_patterns(final, sys.stdout) | |
st.write(out) | |
if __name__ == "__main__": | |
main() | |