sagnik022002 commited on
Commit
0864e84
·
verified ·
1 Parent(s): 8a627c8

Upload 9 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ container_app_shorter_cropped.gif filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ venv/
2
+ tests
3
+ CHANGELOG.md
4
+ .gitpod.yml
5
+ __pycache__/
.gitpod.yml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ tasks:
2
+ - name: VIKTOR
3
+ init: |
4
+ curl -Lo viktor-cli 'https://sys.viktor.ai/api/v1/get-cli/?platform=linux&format=binary'
5
+ chmod +x viktor-cli
6
+ mv viktor-cli /workspace/viktor-cli
7
+ command: |
8
+ echo "export PATH=\$PATH:/workspace" >> ~/.bashrc
9
+ source ~/.bashrc
10
+
11
+
README.md CHANGED
@@ -1,11 +0,0 @@
1
- ---
2
- title: Containers
3
- emoji: 🔥
4
- colorFrom: gray
5
- colorTo: green
6
- sdk: docker
7
- pinned: false
8
- license: apache-2.0
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
app.py ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from viktor.core import ViktorController
2
+ from viktor.geometry import SquareBeam, Group, Material
3
+ from viktor.parametrization import ViktorParametrization, Text, IntegerField, OptionField, DynamicArray
4
+ from viktor.views import SVGView, SVGResult, GeometryResult, GeometryView
5
+ from viktor import Color
6
+ from io import StringIO
7
+ from matplotlib.patches import Rectangle
8
+
9
+ from solver import solver
10
+ import pandas as pd
11
+ import numpy as np
12
+ from rectpack import newPacker
13
+ import rectpack.packer as packer
14
+ import matplotlib.pyplot as plt
15
+ import random
16
+
17
+
18
+ class Parametrization(ViktorParametrization):
19
+ title = Text('# Container Loading Optimization')
20
+
21
+ bin_type = OptionField('What type of container to fill?', options=["20'", "40'"], default="20'", flex=90)
22
+
23
+ # dynamic array with pallet inputs
24
+ array = DynamicArray('Select pallet types and quantities',
25
+ default=[{'pallet_dim': '120 x 80 cm: Standard Euro Pallet', 'pallet_quantity': 1}])
26
+ array.pallet_dim = OptionField('Pallet Type',
27
+ options=['120 x 80 cm: Standard Euro Pallet', '60 x 80 cm: Half Euro Pallet',
28
+ '60 x 40 cm: Display Pallet', '120 x 100 cm: Standard Block Pallet',
29
+ '60 x 100 cm: Half Block Pallet', '60 x 50 cm: HST mini-pallet'], flex=70,
30
+ default='120 x 80 cm: Standard Euro Pallet')
31
+ array.pallet_quantity = IntegerField('Quantity', default=1, flex=25)
32
+
33
+
34
+ class Controller(ViktorController):
35
+ label = 'My Container'
36
+ parametrization = Parametrization(width=35)
37
+
38
+ @SVGView("container", duration_guess=1)
39
+ def create_svg_result(self, params, **kwargs):
40
+ '''This function creates the output view plotting the pallets and container.'''
41
+
42
+ # initialize figure
43
+ fig = plt.figure(figsize=(4, 12))
44
+
45
+ # Set Containers size
46
+ bins20 = [(235, 590)] # 20' container
47
+ bins40 = [(235, 1203)] # 40' container
48
+ # https://www.dsv.com/fr-fr/nos-solutions/modes-de-transport/fret-maritime/dimensions-de-conteneurs-maritimes/dry-container
49
+ # https://www.icontainers.com/help/how-many-pallets-fit-in-a-container/
50
+
51
+ # Set Pallet Dimensions
52
+ bx = 5 # buffer x
53
+ by = 5 # buffer y
54
+
55
+ pal_128 = [120 + bx, 80 + by]
56
+ pal_68 = [60 + bx, 80 + by]
57
+ pal_64 = [60 + bx, 40 + by]
58
+ pal_1210 = [120 + bx, 100 + by]
59
+ pal_610 = [60 + bx, 100 + by]
60
+ pal_65 = [60 + bx, 50 + by]
61
+
62
+ # How many of each pallet type is selected
63
+ n_128, n_68, n_64, n_1210, n_610, n_65 = 0, 0, 0, 0, 0, 0
64
+
65
+ for pallet in params.array:
66
+ if pallet.pallet_dim == '120 x 80 cm: Standard Euro Pallet':
67
+ n_128 += pallet.pallet_quantity
68
+ if pallet.pallet_dim == '60 x 80 cm: Half Euro Pallet':
69
+ n_68 += pallet.pallet_quantity
70
+ if pallet.pallet_dim == '60 x 40 cm: Display Pallet':
71
+ n_64 += pallet.pallet_quantity
72
+ if pallet.pallet_dim == '120 x 100 cm: Standard Block Pallet':
73
+ n_1210 += pallet.pallet_quantity
74
+ if pallet.pallet_dim == '60 x 100 cm: Half Block Pallet':
75
+ n_610 += pallet.pallet_quantity
76
+ if pallet.pallet_dim == '60 x 50 cm: HST mini-pallet':
77
+ n_65 += pallet.pallet_quantity
78
+
79
+ # Plot Container
80
+ if params.bin_type == "20'":
81
+ bin_type = bins20
82
+ plt.plot([0, 235, 235, 0, 0], [0, 0, 590, 590, 0], linewidth=2.5, color="k")
83
+ else:
84
+ bin_type = bins40
85
+ plt.plot([0, 235, 235, 0, 0], [0, 0, 1203, 1203, 0], linewidth=2.5, color="k")
86
+
87
+ # all_rects, all_pals = solver(params.n_812, params.n_1012, bin_type)
88
+ all_rects, all_pals = solver(n_128, n_68, n_64, n_1210, n_610, n_65, bin_type)
89
+
90
+ # Loop all rect
91
+ for rect in all_rects:
92
+ b, x, y, w, h, rid = rect
93
+ # Pallet type colours. If included also add color in plot below.
94
+ if [w, h] == pal_128 or [h, w] == pal_128:
95
+ color = 'pink'
96
+ if [w, h] == pal_68 or [h, w] == pal_68:
97
+ color = 'brown'
98
+ if [w, h] == pal_64 or [h, w] == pal_64:
99
+ color = 'olive'
100
+ if [w, h] == pal_1210 or [h, w] == pal_1210:
101
+ color = 'orange'
102
+ if [w, h] == pal_610 or [h, w] == pal_610:
103
+ color = 'blue'
104
+ if [w, h] == pal_65 or [h, w] == pal_65:
105
+ color = 'purple'
106
+ plt.gca().add_patch(Rectangle((x, y), w, h, facecolor=color, edgecolor='k', fill=True, lw=2))
107
+
108
+ plt.axis('equal')
109
+ plt.axis('off')
110
+ fig.tight_layout()
111
+
112
+ # save figure
113
+ svg_data = StringIO()
114
+ fig.savefig(svg_data, format='svg')
115
+ plt.close()
116
+
117
+ return SVGResult(svg_data)
118
+
119
+ @GeometryView("3D container", duration_guess=1)
120
+ def visualize_container(self, params, **kwargs):
121
+
122
+ # generate container
123
+ length_x = 2.35
124
+ length_z = 2.6
125
+ if params.bin_type == "20'":
126
+ length_y = 5.90
127
+ bin_type = [(235, 590)]
128
+ else:
129
+ length_y = 12.03
130
+ bin_type = [(235, 1203)]
131
+ container = SquareBeam(length_x, length_y, length_z)
132
+ container.material = Material('iron', threejs_opacity=0.5)
133
+ container.translate([(length_x / 2), (length_y / 2), (length_z / 2)])
134
+
135
+ # Set Pallet Dimensions
136
+ bx = 5 # buffer x
137
+ by = 5 # buffer y
138
+
139
+ pal_128 = [120 + bx, 80 + by]
140
+ pal_68 = [60 + bx, 80 + by]
141
+ pal_64 = [60 + bx, 40 + by]
142
+ pal_1210 = [120 + bx, 100 + by]
143
+ pal_610 = [60 + bx, 100 + by]
144
+ pal_65 = [60 + bx, 50 + by]
145
+
146
+ # How many of each pallet type is selected
147
+ n_128, n_68, n_64, n_1210, n_610, n_65 = 0, 0, 0, 0, 0, 0
148
+
149
+ for pallet in params.array:
150
+ if pallet.pallet_dim == '120 x 80 cm: Standard Euro Pallet':
151
+ n_128 += pallet.pallet_quantity
152
+ if pallet.pallet_dim == '60 x 80 cm: Half Euro Pallet':
153
+ n_68 += pallet.pallet_quantity
154
+ if pallet.pallet_dim == '60 x 40 cm: Display Pallet':
155
+ n_64 += pallet.pallet_quantity
156
+ if pallet.pallet_dim == '120 x 100 cm: Standard Block Pallet':
157
+ n_1210 += pallet.pallet_quantity
158
+ if pallet.pallet_dim == '60 x 100 cm: Half Block Pallet':
159
+ n_610 += pallet.pallet_quantity
160
+ if pallet.pallet_dim == '60 x 50 cm: HST mini-pallet':
161
+ n_65 += pallet.pallet_quantity
162
+
163
+ # all_rects, all_pals = solver(params.n_812, params.n_1012, bin_type)
164
+ all_rects, all_pals = solver(n_128, n_68, n_64, n_1210, n_610, n_65, bin_type)
165
+
166
+ pallets = []
167
+ for i, pallet in enumerate(all_rects):
168
+ b, x, y, w, h, rid = pallet
169
+ length_x = w / 100
170
+ length_y = h / 100
171
+ length_z = random.uniform(1, 2) # random pallet heights
172
+
173
+ # create pallet
174
+ pallet_box = SquareBeam(length_x=length_x - 0.1, length_y=length_y - 0.1,
175
+ length_z=length_z) # add 0.1 loose space between pallets
176
+
177
+ # move pallet to right location (defining the center of the pallet)
178
+ pallet_box.translate([(x / 100 + 0.5 * length_x), (y / 100 + 0.5 * length_y), (0.5 * length_z)])
179
+
180
+ # set Material
181
+ if [w, h] == pal_128 or [h, w] == pal_128:
182
+ color = Color(227, 119, 194) # pink
183
+ elif [w, h] == pal_68 or [h, w] == pal_68:
184
+ color = Color(140, 86, 75) # brown
185
+ elif [w, h] == pal_64 or [h, w] == pal_64:
186
+ color = Color(188, 189, 34) # olive
187
+ elif [w, h] == pal_1210 or [h, w] == pal_1210:
188
+ color = Color(255, 127, 14) # orange
189
+ elif [w, h] == pal_610 or [h, w] == pal_610:
190
+ color = Color(31, 119, 180) # blue
191
+ elif [w, h] == pal_65 or [h, w] == pal_65:
192
+ color = Color(148, 103, 189) # purple
193
+ pallet_box.material = Material('plastic', color=color)
194
+
195
+ # add to pallet list
196
+ pallets.append(pallet_box)
197
+ pallets = Group(pallets)
198
+
199
+ container_system = Group([container, pallets])
200
+
201
+ return GeometryResult(container_system)
container-optimization.ipynb ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import pandas as pd\n",
10
+ "import numpy as np\n",
11
+ "from rectpack import newPacker\n",
12
+ "import rectpack.packer as packer\n",
13
+ "import matplotlib.pyplot as plt"
14
+ ]
15
+ },
16
+ {
17
+ "cell_type": "code",
18
+ "execution_count": null,
19
+ "metadata": {},
20
+ "outputs": [],
21
+ "source": [
22
+ "def plot_solution(all_rects, pal_812, pal_1012):\n",
23
+ " # Plot\n",
24
+ " plt.figure(figsize=(10,10))\n",
25
+ " # Loop all rect\n",
26
+ " for rect in all_rects:\n",
27
+ " b, x, y, w, h, rid = rect\n",
28
+ " x1, x2, x3, x4, x5 = x, x+w, x+w, x, x\n",
29
+ " y1, y2, y3, y4, y5 = y, y, y+h, y+h,y\n",
30
+ "\n",
31
+ " # Pallet type\n",
32
+ " if [w, h] == pal_812:\n",
33
+ " color = '--k'\n",
34
+ " else:\n",
35
+ " color = '--r'\n",
36
+ "\n",
37
+ " plt.plot([x1,x2,x3,x4,x5],[y1,y2,y3,y4,y5], color)\n",
38
+ " \n",
39
+ " plt.show()"
40
+ ]
41
+ },
42
+ {
43
+ "cell_type": "code",
44
+ "execution_count": null,
45
+ "metadata": {},
46
+ "outputs": [],
47
+ "source": [
48
+ "# Function Solver\n",
49
+ "def solver(n_812, n_1012, bins):\n",
50
+ " # Pallets to load\n",
51
+ " rectangles = [pal_812 for i in range(n_812)] + [pal_1012 for i in range(n_1012)]\n",
52
+ " \n",
53
+ " # Build the Packer\n",
54
+ " pack = newPacker(mode = packer.PackingMode.Offline, bin_algo = packer.PackingBin.Global,\n",
55
+ " rotation=True)\n",
56
+ "\n",
57
+ " # Add the rectangles to packing queue\n",
58
+ " for r in rectangles:\n",
59
+ " pack.add_rect(*r)\n",
60
+ "\n",
61
+ " # Add the bins where the rectangles will be placed\n",
62
+ " for b in bins:\n",
63
+ " pack.add_bin(*b)\n",
64
+ "\n",
65
+ " # Start packing\n",
66
+ " pack.pack()\n",
67
+ " \n",
68
+ " # Full rectangle list\n",
69
+ " all_rects = pack.rect_list()\n",
70
+ "\n",
71
+ " # Pallets with dimensions\n",
72
+ " all_pals = [sorted([p[3], p[4]]) for p in all_rects]\n",
73
+ "\n",
74
+ " # Count number of 80 x 120 \n",
75
+ " p_812, p_1012 = all_pals.count(pal_812), all_pals.count(pal_1012)\n",
76
+ " print(\"{:,}/{:,} Pallets 80 x 120 (cm) | {:,}/{:,} Pallets 100 x 120 (cm)\".format(p_812, n_812, p_1012, n_1012))\n",
77
+ " \n",
78
+ " return all_rects, all_pals"
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": null,
84
+ "metadata": {},
85
+ "outputs": [],
86
+ "source": [
87
+ "# Pallets Count\n",
88
+ "#-- 80 x 120 cm\n",
89
+ "\n",
90
+ "bx = 0\n",
91
+ "by = 0 \n",
92
+ "pal_812 = [80 + bx, 120 + by]\n",
93
+ "#-- 100 x 120 cm\n",
94
+ "bx = 0\n",
95
+ "by = 0\n",
96
+ "pal_1012 = [100 + bx, 120 + by]\n",
97
+ "\n",
98
+ "# Number of pallets\n",
99
+ "n_812 = 14\n",
100
+ "n_1012 = 0 # 100 x 120 cm\n",
101
+ "rectangles = [pal_812 for i in range(n_812)] + [pal_1012 for i in range(n_1012)]\n",
102
+ "\n",
103
+ "# Container size\n",
104
+ "bins20 = [(236, 595)] \n",
105
+ "bins40 = [(236, 1203.396)] \n",
106
+ "# https://www.dsv.com/fr-fr/nos-solutions/modes-de-transport/fret-maritime/dimensions-de-conteneurs-maritimes/dry-container\n",
107
+ "# https://www.icontainers.com/help/how-many-pallets-fit-in-a-container/"
108
+ ]
109
+ },
110
+ {
111
+ "cell_type": "code",
112
+ "execution_count": null,
113
+ "metadata": {},
114
+ "outputs": [],
115
+ "source": [
116
+ "# Test 1\n",
117
+ "n_812 = 8\n",
118
+ "n_1012 = 2\n",
119
+ "all_rects, all_pals = solver(n_812, n_1012, bins20)\n",
120
+ "plot_solution(all_rects, pal_812, pal_1012)"
121
+ ]
122
+ }
123
+ ],
124
+ "metadata": {
125
+ "language_info": {
126
+ "name": "python"
127
+ },
128
+ "orig_nbformat": 4
129
+ },
130
+ "nbformat": 4,
131
+ "nbformat_minor": 2
132
+ }
container_app_shorter_cropped.gif ADDED

Git LFS Details

  • SHA256: 01481518824b5064f0a913a624100ffe01608a9a15a50b8b1d5324c487e90627
  • Pointer size: 132 Bytes
  • Size of remote file: 2.39 MB
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ viktor==13.5.1
2
+ rectpack
solver.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import pandas as pd
3
+ import numpy as np
4
+ from rectpack import newPacker
5
+ import rectpack.packer as packer
6
+ import matplotlib.pyplot as plt
7
+
8
+
9
+ # Function Solver
10
+ def solver(n_128, n_68, n_64, n_1210, n_610, n_65, bins):
11
+ ''' For optimizing how pallets should be placed in the container. The inputs are the quantities of each pallet type and the container size.'''
12
+
13
+ # Set Pallet Buffer
14
+ bx = 5 # buffer x
15
+ by = 5 # buffer y
16
+ pal_128 = [120 + bx, 80 + by]
17
+ pal_68 = [60 + bx, 80 + by]
18
+ pal_64 = [60 + bx, 40 + by]
19
+ pal_1210 = [120 + bx, 100 + by]
20
+ pal_610 = [60 + bx, 100 + by]
21
+ pal_65 = [60 + bx, 50 + by]
22
+
23
+ # Create Rectangles / Pallets to load
24
+ rectangles =[pal_128 for i in range(n_128)] + [pal_68 for i in range(n_68)] + [pal_64 for i in range(n_64)] +\
25
+ [pal_1210 for i in range(n_1210)] + [pal_610 for i in range(n_610)] + [pal_65 for i in range(n_65)]
26
+
27
+ # Build the Packer
28
+ pack = newPacker(mode = packer.PackingMode.Offline, bin_algo = packer.PackingBin.Global,
29
+ rotation=True)
30
+
31
+ # Add the rectangles to packing queue
32
+ for r in rectangles:
33
+ pack.add_rect(*r)
34
+
35
+ # Add the bins where the rectangles will be placed
36
+ for b in bins:
37
+ pack.add_bin(*b)
38
+
39
+ # Start packing
40
+ pack.pack()
41
+
42
+ # Full rectangle list
43
+ all_rects = pack.rect_list()
44
+
45
+ # Pallets with dimensions
46
+ all_pals = [sorted([p[3], p[4]]) for p in all_rects]
47
+
48
+ return all_rects, all_pals
49
+
50
+
viktor.config.toml ADDED
@@ -0,0 +1 @@
 
 
1
+ app_type = 'editor'