-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathBalance-Objects.py
executable file
·175 lines (123 loc) · 3.35 KB
/
Balance-Objects.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/env python
# encoding: UTF-8
# This is a solver for a simple binning problem
# It just do random swap and minimize an objective function
# Author: Sébastien Boisvert
# License: GPLv3
import sys
import random
arguments=sys.argv
if len(arguments)!=3:
print("Usage: "+arguments[0]+" Entries Bins")
print("Entries is a 2-column file, the columns are: object description, oject weight")
print("This program outputs an optimal layout of objects in bins so that all the bins have equal weight or so")
sys.exit()
inputFile=arguments[1]
bins=int(arguments[2])
objects=[]
binWeights=[]
indexName=0
indexWeight=1
indexBin=2
i=0
while i<bins:
binWeights.append(0)
i+=1
print("Configuring for "+str(bins)+" bins")
print("Reading "+inputFile)
stream=open(inputFile)
selectedBin=0
for line in stream:
tokens=line.split()
weight=int(tokens[1])
objects.append([tokens[0],weight,selectedBin])
binWeights[selectedBin]+=weight
stream.close()
print("Fetched "+str(len(objects))+" objects")
sum=0
for i in objects:
weight=i[indexWeight]
sum+=weight
print("Sum of weights is "+str(sum))
average=sum/bins
print("Expected weight per bin: "+str(average))
i=0
def getScore(binWeights,average):
score=0
for i in binWeights:
difference=average-i
difference*=difference
score+=difference
return score
score=getScore(binWeights,average)
print("Initial score: "+str(score))
def getRandomObject(objects):
value=random.randint(0,len(objects)-1)
if value%2==1:
value-=1
return value
def getRandomBin(binWeights):
value=random.randint(0,len(binWeights)-1)
return value
iteration=0
lastPrint=0
printPeriod=10000
maximumIterationsWithoutImprovement=10000000
beforeStop=maximumIterationsWithoutImprovement
changes=0
lastChange=0
arrivalPeriod=0
sumOfArrivals=0
averageArrival=0
while beforeStop>=0:
beforeStop-=1
objectA=getRandomObject(objects)
objectB=getRandomObject(objects)
weightA=objects[objectA][indexWeight]
weightB=objects[objectB][indexWeight]
binA=objects[objectA][indexBin]
binB=objects[objectB][indexBin]
binWeights[binA]-=2*weightA
binWeights[binB]-=2*weightB
newBinA=getRandomBin(binWeights)
newBinB=getRandomBin(binWeights)
binWeights[newBinA]+=2*weightA
binWeights[newBinB]+=2*weightB
newScore=getScore(binWeights,average)
if iteration>= lastPrint+printPeriod:
print("Iteration: "+str(iteration)+" score: "+str(score)+" left: "+str(beforeStop)+" changes: "+str(changes)+" arrival: "+str(averageArrival))
lastPrint=iteration
# revert the swap
if newScore>=score:
binWeights[newBinA]-=2*weightA
binWeights[newBinB]-=2*weightB
binWeights[binA]+=2*weightA
binWeights[binB]+=2*weightB
iteration+=1
continue
score=newScore
beforeStop=maximumIterationsWithoutImprovement
arrivalPeriod=iteration-lastChange
changes+=2
sumOfArrivals+=arrivalPeriod
averageArrival=sumOfArrivals/(changes/2)
lastChange=iteration
objects[objectA][indexBin]=newBinA
objects[objectA+1][indexBin]=newBinA
objects[objectB][indexBin]=newBinB
objects[objectB+1][indexBin]=newBinB
lastImprovement=iteration
iteration+=1
print("Solution:")
print("Bin ExpectedWeight ActualWeight")
while i<bins:
print(str(i)+" "+str(average)+" "+str(binWeights[i]))
i+=1
files={}
for i in objects:
bin=i[indexBin]
if bin not in files:
files[bin]=open(inputFile+".Bin_"+str(bin)+".txt","w")
files[bin].write(i[indexName]+"\n")
for i in files:
files[i].close()