aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbozokopic <bozo.kopic@gmail.com>2017-04-25 16:47:44 +0200
committerbozokopic <bozo.kopic@gmail.com>2017-04-25 16:47:44 +0200
commit1a7bbad8a6295db02d3e66a8d601b5e9da1e9057 (patch)
treed04346fb4e54cf9207f4dece771cf75e707eb1b7
parentdcec4e34741e0906e66d0fa1d22b7a876daab09f (diff)
csp calculation - fitness function
-rw-r--r--README.rst6
-rw-r--r--src_py/opcut/csp.py67
2 files changed, 70 insertions, 3 deletions
diff --git a/README.rst b/README.rst
index c0d4b7b..ceb34d4 100644
--- a/README.rst
+++ b/README.rst
@@ -1,9 +1,9 @@
-optcut
-======
+opcut
+=====
`https://opcut.herokuapp.com/`
-`optcut` is cutting stock problem optimizer
+`opcut` is cutting stock problem optimizer
(`https://en.wikipedia.org/wiki/Cutting_stock_problem`) utilizing multiple
panels and guillotine cuts (end-to-end cuts). This project includes multiple
back-end optimizer implementations and single-page web application front-end.
diff --git a/src_py/opcut/csp.py b/src_py/opcut/csp.py
new file mode 100644
index 0000000..da8906a
--- /dev/null
+++ b/src_py/opcut/csp.py
@@ -0,0 +1,67 @@
+import collections
+import enum
+
+
+InputPanel = collections.namedtuple('InputPanel', ['width', 'height', 'label'])
+InputItem = collections.namedtuple('InputItem', ['width', 'height', 'label',
+ 'rotate'])
+OutputPanel = collections.namedtuple('OutputPanel', ['width', 'height',
+ 'label', 'items'])
+OutputItem = collections.namedtuple('OutputItem', ['width', 'height', 'label',
+ 'x', 'y'])
+
+Method = enum.Enum('Method', ['FORWARD_GREEDY'])
+
+
+def calculate(panels, items, cut_width, method):
+ """Calculate cutting stock problem
+
+ Args:
+ panels (List[InputPanel]): input panels
+ items (List[InputItem]): input items
+ cut_width (float): cut width
+ method (Method): calculation method
+
+ Returns:
+ List[OutputPanel]
+
+ """
+ return {
+ Method.FORWARD_GREEDY: _calculate_forward_greedy
+ }[method](panels, items)
+
+
+def _calculate_forward_greedy(panels, items):
+ pass
+
+
+_Part = collections.namedtuple('_Part', ['panel', 'width', 'height', 'x', 'y'])
+_State = collections.namedtuple('_State', ['inputs', 'outputs'])
+_fitness_K = 0.03
+
+
+def _fitness(state):
+ panel_states = {}
+ for i in state.inputs:
+ if i.panel not in panel_states:
+ panel_states[i.panel] = _State([i], [])
+ else:
+ panel_states[i.panel].inputs.append(i)
+ for i in state.outputs:
+ if i.panel not in panel_states:
+ panel_states[i.panel] = _State([], [i])
+ else:
+ panel_states[i.panel].outputs.append(i)
+
+ total_area = sum(i.width * i.height for i in panel_states.keys())
+ result = 0
+ for panel, panel_state in panel_states.items():
+ result += (panel.width * panel.height -
+ sum(i.width * i.height
+ for i in panel_state.outputs)) / total_area
+ result -= (_fitness_K *
+ min(i.width * i.height for i in panel_state.outputs,
+ default=0) *
+ max(i.width * i.height for i in panel_state.inputs,
+ default=0)) / (total_area * total_area)
+ return result