Skip to content

Commit f371ee7

Browse files
author
SALAKHIEV Ildar
committed
Initial commit after BMSTU validation
0 parents  commit f371ee7

12 files changed

+561
-0
lines changed

.project

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<projectDescription>
3+
<name>Bin_Packaging_Problem</name>
4+
<comment></comment>
5+
<projects>
6+
</projects>
7+
<buildSpec>
8+
<buildCommand>
9+
<name>org.python.pydev.PyDevBuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
13+
</buildSpec>
14+
<natures>
15+
<nature>org.python.pydev.pythonNature</nature>
16+
</natures>
17+
</projectDescription>

.pydevproject

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<?eclipse-pydev version="1.0"?><pydev_project>
3+
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
4+
<path>/${PROJECT_DIR_NAME}</path>
5+
</pydev_pathproperty>
6+
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
7+
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
8+
</pydev_project>

Box.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from random import uniform
2+
from drawing import FLOOR_WIDTH_PXL
3+
MAX_BOX_SIZE_PXL = int (FLOOR_WIDTH_PXL * 0.35)
4+
5+
counter = 0
6+
7+
class Box(object):
8+
def __init__(self):
9+
self.height = int(uniform(0.4,1)*MAX_BOX_SIZE_PXL)
10+
self.width = int(uniform(0.4,1)*MAX_BOX_SIZE_PXL)
11+
coefficient = float((self.width*self.height))/(MAX_BOX_SIZE_PXL**2)
12+
self.color = (int(uniform(0.1,1)*(70+150*coefficient)), int(110 + 145*coefficient), int(uniform(0.1,1)*(70+150*coefficient)))
13+
global counter
14+
self.box_Num = counter
15+
counter += 1
16+
print" Box Number: "+ str(counter) + " Height: " + str(self.height) + " Width: " + str(self.width)
17+

Box.pyc

1.12 KB
Binary file not shown.

Evristic_solution.py

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
from drawing import FLOOR_HEIGHT_PXL
2+
from drawing import FLOOR_WIDTH_PXL
3+
from Box import MAX_BOX_SIZE_PXL
4+
import random
5+
import copy
6+
7+
8+
class Solution_Position(object): #gives the box the angle and the down & left or down & right position
9+
def __init__(self, Boxes_list, solution, X=0, Y=0):
10+
Copy_Of_Boxes_List = copy.copy(Boxes_list)
11+
if len(solution) >= len(Copy_Of_Boxes_List):
12+
print "all boxes fitted in"
13+
for i in solution:
14+
for j in Copy_Of_Boxes_List:
15+
if j.box_Num == i.box_Num:
16+
Copy_Of_Boxes_List.remove(j)
17+
box = random.choice(Copy_Of_Boxes_List)
18+
self.box_Num = box.box_Num
19+
self.angle = random.choice((0,1))
20+
self.position = random.choice((0,1)) #0 - down & left, 1- down & right
21+
self.width = box.width
22+
self.height = box.height
23+
self.X = X
24+
self.Y = Y
25+
self.color = box.color
26+
27+
28+
29+
class Evristic_solution(object):
30+
def __init__(self, Boxes_List):
31+
self.Boxes_List = Boxes_List
32+
self.positions = []
33+
self.solve_properly()
34+
self.Put_Cost_Value()
35+
36+
def solve_properly(self):
37+
self.clear_copies()
38+
#flag_of_overfill = False
39+
#while not(flag_of_overfill):
40+
self.positions.append(Solution_Position(self.Boxes_List,self.positions))
41+
self.Put_X_Y_to_positions()
42+
self.Put_Cost_Value()
43+
44+
def copy(self,positions):
45+
self.positions = []
46+
for i in positions:
47+
self.positions.append(copy.copy(i))
48+
self.Put_Cost_Value()
49+
50+
def sort_By_X(self,positions):
51+
return positions.X
52+
53+
def clear_copies(self):
54+
boxes = []
55+
for position in self.positions:
56+
boxes.append(position.box_Num)
57+
if boxes.count(position.box_Num) > 1:
58+
self.positions.remove(position)
59+
60+
61+
def Put_X_Y_to_positions(self):
62+
for j in self.positions:
63+
if j.angle:
64+
j.height, j.width = j.width, j.height #turn
65+
66+
list_of_Y = []
67+
positions_with_X_Y = []
68+
flag_of_overfill = False
69+
for current_box in self.positions: #here begins looking for empty space
70+
flag_put_in_place = False
71+
#if not(flag_of_overfill):
72+
list_of_Y = [1]
73+
for position in positions_with_X_Y:
74+
list_of_Y.append(position.Y+position.height + 2) #+2 is to avoid pixels crosses
75+
list_of_Y.sort()
76+
77+
for Y in list_of_Y:
78+
if not(flag_put_in_place): #to see if we have found space
79+
possible_positions_list_in_Y_line = [0]
80+
for position in positions_with_X_Y:
81+
if (position.Y <= Y + current_box.height and position.Y+position.height > Y): #pay attention to this place with <= or <
82+
possible_positions_list_in_Y_line.append(position.X)
83+
possible_positions_list_in_Y_line.append(position.X+position.width)
84+
possible_positions_list_in_Y_line.append(FLOOR_WIDTH_PXL)
85+
if len(possible_positions_list_in_Y_line)>0:
86+
possible_positions_list_in_Y_line.sort(reverse=current_box.position)
87+
88+
89+
for current_X in possible_positions_list_in_Y_line:
90+
if current_box.position:
91+
possible_X = current_X - current_box.width
92+
else:
93+
possible_X = current_X
94+
if not(flag_put_in_place):
95+
if self.Check_for_crosses_of_list(positions_with_X_Y, possible_X, Y, current_box.width, current_box.height):
96+
flag_of_overfill, positions_with_X_Y = self.Put_in_X_Y_Position_Down_Right_or_Down_Left(current_box.position, flag_put_in_place, Y, current_box, possible_X, positions_with_X_Y, flag_of_overfill)
97+
flag_put_in_place = True
98+
#else:
99+
#self.positions.remove(current_box)
100+
#print "removed"
101+
self.positions = []
102+
for i in positions_with_X_Y:
103+
self.positions.append(i)
104+
return flag_of_overfill
105+
106+
107+
def Put_in_X_Y_Position_Down_Right_or_Down_Left(self, Right_Or_Left, flag_put_in_place,Y, current_box, possible_X, positions_with_X_Y, flag_of_overfill):
108+
if Y + current_box.height < FLOOR_HEIGHT_PXL:
109+
if Right_Or_Left: #true means to right
110+
current_box.X = possible_X
111+
else:
112+
current_box.X = possible_X
113+
current_box.Y = Y
114+
positions_with_X_Y.append(current_box)
115+
else:
116+
flag_of_overfill = True
117+
'''self.positions.remove(current_box)'''
118+
return flag_of_overfill, positions_with_X_Y
119+
120+
121+
122+
def Check_for_crosses_of_list(self,positions_with_X_Y, X, Y, width, height):
123+
if (X < 0 or X + width > FLOOR_WIDTH_PXL):
124+
return False
125+
for position in positions_with_X_Y:
126+
if self.Check_for_crosses (position.X, position.Y,
127+
position.X+position.width, position.Y+ position.height,
128+
X, Y,
129+
X + width, Y + height):
130+
return False
131+
return True
132+
133+
def Check_for_crosses (self, AX1, AY1, AX2, AY2, BX1, BY1 , BX2, BY2):
134+
if (abs(AX1 - BX1) > MAX_BOX_SIZE_PXL or abs(AY1 - BY1) > MAX_BOX_SIZE_PXL):
135+
return False
136+
if self.Dot_inside_recktangle(AX1 + 1, AY1 + 1, BX1, BY1, BX2, BY2):
137+
return True
138+
if self.Dot_inside_recktangle(AX1 + 1, AY2 - 1, BX1, BY1, BX2, BY2):
139+
return True
140+
if self.Dot_inside_recktangle(AX2 - 1, AY1 + 1, BX1, BY1, BX2, BY2):
141+
return True
142+
if self.Dot_inside_recktangle(AX2 - 1, AY2 - 1, BX1, BY1, BX2, BY2):
143+
return True
144+
145+
if self.Dot_inside_recktangle(BX1 + 1, BY1 + 1, AX1, AY1, AX2, AY2):
146+
return True
147+
if self.Dot_inside_recktangle(BX1 + 1, BY2 - 1, AX1, AY1, AX2, AY2):
148+
return True
149+
if self.Dot_inside_recktangle(BX2 - 1, BY1 + 1, AX1, AY1, AX2, AY2):
150+
return True
151+
if self.Dot_inside_recktangle(BX2 - 1, BY2 - 1, AX1, AY1, AX2, AY2):
152+
return True
153+
154+
if (AX1 < BX1 and AX2 > BX2 and AY1 > BY1 and AY2 < BY2):
155+
return True
156+
if (BX1 < AX1 and BX2 > AX2 and BY1 > AY1 and BY2 < AY2):
157+
return True
158+
159+
return False
160+
161+
def Dot_inside_recktangle(self,X,Y,AX,AY,BX,BY):
162+
return (X >= AX and X <= BX and Y >= AY and Y <= BY)
163+
164+
def Put_Cost_Value(self):
165+
Cost = 0.0
166+
for i in self.positions:
167+
Cost = Cost + i.width * i.height
168+
self.cost = Cost/(FLOOR_HEIGHT_PXL * FLOOR_WIDTH_PXL)
169+
170+
171+
172+
173+
class Solutions_List(object):
174+
def __init__(self, count, Boxes_List):
175+
self.count = count
176+
self.Boxes_List = Boxes_List
177+
self.solutions = []
178+
for i in range(count):
179+
self.solutions.append(Evristic_solution(Boxes_List))
180+
181+
def Cycle(self):
182+
self.solutions.sort(key=self.sort_By_Cost, reverse = True)
183+
spliting_percent = 0.4
184+
185+
to_Mutation = int(self.count * spliting_percent)
186+
i = 0
187+
while i < self.count-1:
188+
if i < to_Mutation:
189+
self.solutions.append(self.Mutation_of_solution(self.solutions[i]))
190+
else:
191+
solution1, solution2 = self.Crossbreeding(self.solutions[i], self.solutions[i + 1])
192+
self.solutions.append(solution1)
193+
self.solutions.append(solution2)
194+
i = i + 1
195+
i = i + 1
196+
197+
#taking best solutions
198+
solutions_new = []
199+
while len(solutions_new) < self.count and len(self.solutions) > 1:
200+
num = random.randint(0,len(self.solutions)-1)
201+
solution1 = self.solutions[num]
202+
self.solutions.remove(solution1)
203+
solution2 = self.solutions[random.randint(0,len(self.solutions)-1)]
204+
self.solutions.remove(solution2)
205+
solutions_new.append(self.Selection(solution1,solution2))
206+
self.solutions = solutions_new
207+
self.solutions.sort(key=self.sort_By_Cost, reverse = True)
208+
209+
210+
def Mutation_of_solution (self, solution):
211+
mutation_rate = 0.1
212+
mutated_solution = Evristic_solution(self.Boxes_List)
213+
mutated_solution.copy(solution.positions)
214+
215+
for i in mutated_solution.positions:
216+
if random.random() <= mutation_rate:
217+
mutated_solution.positions.insert(mutated_solution.positions.index(i),Solution_Position(self.Boxes_List, mutated_solution.positions))
218+
mutated_solution.positions.remove(i)
219+
if random.random() <= mutation_rate:
220+
i.angle = not(i.angle)
221+
if random.random() <= mutation_rate:
222+
i.position = not(i.position)
223+
224+
mutated_solution.solve_properly()
225+
return mutated_solution
226+
227+
def Crossbreeding (self, s1, s2):
228+
crossbreeding_points = 1
229+
point = 0
230+
solution1 = copy.copy(s1)
231+
solution2 = copy.copy(s2)
232+
solution1.copy(s1.positions)
233+
solution2.copy(s2.positions)
234+
min_length = min(len(solution1.positions),len(solution2.positions))
235+
for crosbreeding_point in range(crossbreeding_points):
236+
point = random.randint(0, min_length)
237+
for position in range(point):
238+
solution1.positions[position], solution2.positions[position] = solution2.positions[position], solution1.positions[position]
239+
240+
solution1.solve_properly()
241+
solution2.solve_properly()
242+
return solution1, solution2
243+
244+
def Selection (self, solution1, solution2):
245+
if solution1.cost > solution2.cost:
246+
return solution1
247+
else:
248+
return solution2
249+
250+
def sort_By_Cost(self,solution):
251+
return solution.cost
252+
253+

Evristic_solution.pyc

8.79 KB
Binary file not shown.

0 commit comments

Comments
 (0)