by Anonymous » 16 Apr 2025, 07:08
Ich versuche, eine Einschränkungsprogrammierlösung für die Elementallokation im Regal zu formulieren. Das Ziel ist, dass einfache Gegenstände derselben Marke so nah wie möglich gehalten werden und einen anständigen quadratischen oder rechteckigen Block beibehalten sollten. Wenn mein Planogramm jeweils 3 Regal an 10 cm gibt, dann wird meine Partitionszahl 30 betrachtet, wenn man die Granularität von 1. /> < /p>
wobei jeder (x, y) Punkt x -> Partitionsnummer im Regal bezeichnet, y -> Regalnummer. Nur wenige Einschränkungen. /> Alle miteinander verbundenen Element -Partition derselben Marke haben einen Adjazenzwert. Ich versuche, diese Punktzahl zu maximieren. Code: < /p>
Code: Select all
import cpmpy as cp
import numpy as np
import pandas as pd
import seaborn as sns
import networkx as nx
import matplotlib.pyplot as plt
from collections import defaultdict
from GridGraph_mod import process_group
from concurrent.futures import ProcessPoolExecutor, as_completed
pd.set_option("display.max_rows", 500)
pd.set_option("display.max_columns", 500)
def create_mapping(brand_shelf_allowded_mapping, pog_df, shelf_count):
remaining_brand = set(pog_df.brand_nm.unique()) - set(brand_shelf_allowded_mapping["brand_nm"])
brand_shelf_allowded_mapping['brand_nm'].extend(remaining_brand)
for _ in range(len(remaining_brand)):
brand_shelf_allowded_mapping['shelf_allowed'].append([x for x in range(shelf_count)])
return brand_shelf_allowded_mapping
def parallel_creator(key, idx_df):
node_dict = {}
with ProcessPoolExecutor() as executor:
futures = {executor.submit(process_group, level, data): level for level, data in idx_df.groupby(key)}
for future in as_completed(futures):
level, var_dict = future.result()
node_dict[level] = var_dict
return node_dict
if __name__ == "__main__":
bay_count = 3
granularity = 1
shelf_count = 7
section_width = 133
grid_width = int(section_width * bay_count / granularity)
grid_height = shelf_count
pog_df = pd.read_csv("data_temp/N3ADAA.csv")
pog_df['linear'] = pog_df.linear.apply(np.ceil)
pog_df['gridlinear'] = pog_df.linear//granularity
G = nx.grid_2d_graph(int(section_width * bay_count/granularity),int(shelf_count))
pos = {(x, y): (x, y) for x, y in G.nodes()}
products = pog_df[['tpnb', 'gridlinear']].astype(str)
locations = pd.Series([str(s) for s in G.nodes()], name='location')
locations = pd.concat([locations,locations.to_frame().location.str.strip("() ").str.split(',', expand=True).rename(columns={0: 'x', 1: 'y'})], axis=1)
pog_df = pd.merge(pog_df,
pog_df.groupby("brand_nm", as_index=False).agg(gridlinear_brand = ("gridlinear", "sum")),
on = "brand_nm")
l_c_idx = pd.merge(pog_df.reset_index(drop=True),
locations,
how='cross')[['tpnb', 'brand_nm', 'gridlinear', 'gridlinear_brand', 'location', 'x', 'y']]
l_c_idx["x"] = l_c_idx["x"].astype("int32")
l_c_idx["y"] = l_c_idx["y"].astype("int32")
brand_shelf_allowded_mapping = {
"brand_nm": ['TESCO ESSENTIALS', 'TESCO PROFORMULA', 'PRONAMEL', 'FIXODENT', 'MACLEANS', 'ARM & HAMMER', 'TEPE', 'POLIGRIP', 'STERADENT', 'PRO FORMULA', 'ORAL-B', 'COLGATE', 'LISTERINE', 'SENSODYNE','CORSODYL', 'AQUAFRESH'],
"shelf_allowed": [[0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0,1], [2,3,4,5], [2,3,4,5], [2,3,4,5], [0,1], [6], [6]]
}
brand_shelf_allowded_mapping = create_mapping(brand_shelf_allowded_mapping, pog_df, shelf_count)
brand_shelf_allowded_mapping_df = pd.DataFrame(brand_shelf_allowded_mapping)
brand_shelf_allowded_mapping_df = brand_shelf_allowded_mapping_df.explode("shelf_allowed")
brand_shelf_allowded_mapping_df.shelf_allowed = brand_shelf_allowded_mapping_df.shelf_allowed.astype("int32")
l_c_idx = pd.merge(l_c_idx, brand_shelf_allowded_mapping_df, left_on=["brand_nm", "y"], right_on=["brand_nm", "shelf_allowed"], how="inner")[l_c_idx.columns]
l_c_idx['Var'] = l_c_idx.apply(lambda x: cp.boolvar(name=x['location']+'-'+str(x['tpnb'])+'-'+x["brand_nm"]), axis=1)
# model_initiation
m = cp.Model()
# 1. Every Item should take whatever space is needed by them
l_c_idx.groupby('tpnb', as_index=False).agg({'Var':cp.sum, 'gridlinear': 'unique'}).apply(lambda x: m.constraints.append(x['Var']==int(float(x["gridlinear"]))), axis=1)
# 2. All location should take distinct items only
l_c_idx.groupby('location', as_index=False).agg({'Var':cp.sum}).apply(lambda x: m.constraints.append(x['Var']
Daten: Beispiel < /p>
tpnb,linear,item_height,item_width,item_depth,brand_nm
61452116,16.1,3.6,15.0,3.0,AQUAFRESH
62977195,14.0,4.5,13.0,3.7,SENSODYNE
81116754,17.2,4.6,17.0,3.8,AQUAFRESH
85988423,16.0,3.6,15.0,3.0,COLGATE
85992262,9.0,14.9,3.5,3.5,TESCO PROFORMULA
85992832,9.8,18.9,4.5,2.5,TESCO PROFORMULA
86016064,11.4,23.0,10.5,2.4,TESCO ESSENTIALS
88903192,17.2,4.6,17.0,3.8,AQUAFRESH
91256336,17.8,23.2,4.2,3.0,AQUAFRESH
51769631,19.5,4.2,19.0,3.5,MACLEANS
52098829,19.5,4.2,19.0,3.5,MACLEANS
76956089,19.7,4.3,18.9,3.8,AQUAFRESH
79360074,35.0,4.5,17.3,4.0,COLGATE
84928779,18.4,3.3,18.0,3.3,TESCO ESSENTIALS
93038799,19.4,4.5,18.7,3.7,AQUAFRESH
51164799,19.5,21.2,9.0,4.6,COLGATE
51257776,19.5,21.2,9.0,4.6,COLGATE
73385394,19.5,21.3,9.0,4.5,COLGATE
85290842,34.0,22.5,8.4,5.0,TESCO ESSENTIALS
85290856,17.4,22.1,8.5,4.8,PRO FORMULA
86006295,13.5,16.2,6.4,6.4,TESCO PROFORMULA
61489561,21.0,16.0,7.0,4.8,AQUAFRESH
74168299,8.9,23.0,4.2,2.5,AQUAFRESH
80184938,26.0,23.0,5.5,2.8,COLGATE
81116731,35.0,4.6,17.0,3.8,AQUAFRESH
84538526,17.5,3.8,16.9,1.3,AQUAFRESH
91713372,12.3,23.9,11.0,5.0,ORAL-B
92000950,6.8,21.6,6.0,1.0,ORAL-B
Bitte helfen Sie, wie kann ich dies auch für große Eingaben erstellen.
Ich versuche, eine Einschränkungsprogrammierlösung für die Elementallokation im Regal zu formulieren. Das Ziel ist, dass einfache Gegenstände derselben Marke so nah wie möglich gehalten werden und einen anständigen quadratischen oder rechteckigen Block beibehalten sollten. Wenn mein Planogramm jeweils 3 Regal an 10 cm gibt, dann wird meine Partitionszahl 30 betrachtet, wenn man die Granularität von 1. /> < /p>
wobei jeder (x, y) Punkt x -> Partitionsnummer im Regal bezeichnet, y -> Regalnummer. Nur wenige Einschränkungen. /> Alle miteinander verbundenen Element -Partition derselben Marke haben einen Adjazenzwert. Ich versuche, diese Punktzahl zu maximieren. Code: < /p>
[code]import cpmpy as cp
import numpy as np
import pandas as pd
import seaborn as sns
import networkx as nx
import matplotlib.pyplot as plt
from collections import defaultdict
from GridGraph_mod import process_group
from concurrent.futures import ProcessPoolExecutor, as_completed
pd.set_option("display.max_rows", 500)
pd.set_option("display.max_columns", 500)
def create_mapping(brand_shelf_allowded_mapping, pog_df, shelf_count):
remaining_brand = set(pog_df.brand_nm.unique()) - set(brand_shelf_allowded_mapping["brand_nm"])
brand_shelf_allowded_mapping['brand_nm'].extend(remaining_brand)
for _ in range(len(remaining_brand)):
brand_shelf_allowded_mapping['shelf_allowed'].append([x for x in range(shelf_count)])
return brand_shelf_allowded_mapping
def parallel_creator(key, idx_df):
node_dict = {}
with ProcessPoolExecutor() as executor:
futures = {executor.submit(process_group, level, data): level for level, data in idx_df.groupby(key)}
for future in as_completed(futures):
level, var_dict = future.result()
node_dict[level] = var_dict
return node_dict
if __name__ == "__main__":
bay_count = 3
granularity = 1
shelf_count = 7
section_width = 133
grid_width = int(section_width * bay_count / granularity)
grid_height = shelf_count
pog_df = pd.read_csv("data_temp/N3ADAA.csv")
pog_df['linear'] = pog_df.linear.apply(np.ceil)
pog_df['gridlinear'] = pog_df.linear//granularity
G = nx.grid_2d_graph(int(section_width * bay_count/granularity),int(shelf_count))
pos = {(x, y): (x, y) for x, y in G.nodes()}
products = pog_df[['tpnb', 'gridlinear']].astype(str)
locations = pd.Series([str(s) for s in G.nodes()], name='location')
locations = pd.concat([locations,locations.to_frame().location.str.strip("() ").str.split(',', expand=True).rename(columns={0: 'x', 1: 'y'})], axis=1)
pog_df = pd.merge(pog_df,
pog_df.groupby("brand_nm", as_index=False).agg(gridlinear_brand = ("gridlinear", "sum")),
on = "brand_nm")
l_c_idx = pd.merge(pog_df.reset_index(drop=True),
locations,
how='cross')[['tpnb', 'brand_nm', 'gridlinear', 'gridlinear_brand', 'location', 'x', 'y']]
l_c_idx["x"] = l_c_idx["x"].astype("int32")
l_c_idx["y"] = l_c_idx["y"].astype("int32")
brand_shelf_allowded_mapping = {
"brand_nm": ['TESCO ESSENTIALS', 'TESCO PROFORMULA', 'PRONAMEL', 'FIXODENT', 'MACLEANS', 'ARM & HAMMER', 'TEPE', 'POLIGRIP', 'STERADENT', 'PRO FORMULA', 'ORAL-B', 'COLGATE', 'LISTERINE', 'SENSODYNE','CORSODYL', 'AQUAFRESH'],
"shelf_allowed": [[0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0,1], [2,3,4,5], [2,3,4,5], [2,3,4,5], [0,1], [6], [6]]
}
brand_shelf_allowded_mapping = create_mapping(brand_shelf_allowded_mapping, pog_df, shelf_count)
brand_shelf_allowded_mapping_df = pd.DataFrame(brand_shelf_allowded_mapping)
brand_shelf_allowded_mapping_df = brand_shelf_allowded_mapping_df.explode("shelf_allowed")
brand_shelf_allowded_mapping_df.shelf_allowed = brand_shelf_allowded_mapping_df.shelf_allowed.astype("int32")
l_c_idx = pd.merge(l_c_idx, brand_shelf_allowded_mapping_df, left_on=["brand_nm", "y"], right_on=["brand_nm", "shelf_allowed"], how="inner")[l_c_idx.columns]
l_c_idx['Var'] = l_c_idx.apply(lambda x: cp.boolvar(name=x['location']+'-'+str(x['tpnb'])+'-'+x["brand_nm"]), axis=1)
# model_initiation
m = cp.Model()
# 1. Every Item should take whatever space is needed by them
l_c_idx.groupby('tpnb', as_index=False).agg({'Var':cp.sum, 'gridlinear': 'unique'}).apply(lambda x: m.constraints.append(x['Var']==int(float(x["gridlinear"]))), axis=1)
# 2. All location should take distinct items only
l_c_idx.groupby('location', as_index=False).agg({'Var':cp.sum}).apply(lambda x: m.constraints.append(x['Var']
Daten: Beispiel < /p>
tpnb,linear,item_height,item_width,item_depth,brand_nm
61452116,16.1,3.6,15.0,3.0,AQUAFRESH
62977195,14.0,4.5,13.0,3.7,SENSODYNE
81116754,17.2,4.6,17.0,3.8,AQUAFRESH
85988423,16.0,3.6,15.0,3.0,COLGATE
85992262,9.0,14.9,3.5,3.5,TESCO PROFORMULA
85992832,9.8,18.9,4.5,2.5,TESCO PROFORMULA
86016064,11.4,23.0,10.5,2.4,TESCO ESSENTIALS
88903192,17.2,4.6,17.0,3.8,AQUAFRESH
91256336,17.8,23.2,4.2,3.0,AQUAFRESH
51769631,19.5,4.2,19.0,3.5,MACLEANS
52098829,19.5,4.2,19.0,3.5,MACLEANS
76956089,19.7,4.3,18.9,3.8,AQUAFRESH
79360074,35.0,4.5,17.3,4.0,COLGATE
84928779,18.4,3.3,18.0,3.3,TESCO ESSENTIALS
93038799,19.4,4.5,18.7,3.7,AQUAFRESH
51164799,19.5,21.2,9.0,4.6,COLGATE
51257776,19.5,21.2,9.0,4.6,COLGATE
73385394,19.5,21.3,9.0,4.5,COLGATE
85290842,34.0,22.5,8.4,5.0,TESCO ESSENTIALS
85290856,17.4,22.1,8.5,4.8,PRO FORMULA
86006295,13.5,16.2,6.4,6.4,TESCO PROFORMULA
61489561,21.0,16.0,7.0,4.8,AQUAFRESH
74168299,8.9,23.0,4.2,2.5,AQUAFRESH
80184938,26.0,23.0,5.5,2.8,COLGATE
81116731,35.0,4.6,17.0,3.8,AQUAFRESH
84538526,17.5,3.8,16.9,1.3,AQUAFRESH
91713372,12.3,23.9,11.0,5.0,ORAL-B
92000950,6.8,21.6,6.0,1.0,ORAL-B
[/code]
Bitte helfen Sie, wie kann ich dies auch für große Eingaben erstellen.