open-ship 0.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1 +1,3 @@
1
+ v0.1.2. added classes for sorting shipments
2
+ v0.1.1. changed base filenames for less painful requires
1
3
  v0.1. first version
data/Manifest CHANGED
@@ -3,9 +3,20 @@ LICENSE
3
3
  Manifest
4
4
  README
5
5
  Rakefile
6
- lib/openship.rb
7
- lib/openship/label.rb
8
- lib/openship/openship.rb
9
- lib/openship/sscc.rb
10
- spec/openship/sscc_spec.rb
6
+ lib/open-ship.rb
7
+ lib/open-ship/gga4r.rb
8
+ lib/open-ship/gga4r/array_helper.rb
9
+ lib/open-ship/gga4r/gga4r_main.rb
10
+ lib/open-ship/gga4r/version.rb
11
+ lib/open-ship/label.rb
12
+ lib/open-ship/label/carton_label.rb
13
+ lib/open-ship/label/text_label.rb
14
+ lib/open-ship/sortr.rb
15
+ lib/open-ship/sscc.rb
16
+ spec/open-ship/carton_spec.rb
17
+ spec/open-ship/label/carton_label_spec.rb
18
+ spec/open-ship/label/text_label_spec.rb
19
+ spec/open-ship/sscc_spec.rb
11
20
  spec/spec_helper.rb
21
+ tmp/test_carton_label.pdf
22
+ tmp/test_text_label.pdf
@@ -0,0 +1,30 @@
1
+ class Array
2
+
3
+
4
+ # Yields given bloc using arrays items pair by pair.
5
+ # e.g.
6
+ # <code>
7
+ # ["a","b","c","d"].each_pair do |first, second|
8
+ # puts second + " - " + second
9
+ # end
10
+ # </code>
11
+ # will print:
12
+ # b - a
13
+ # c - d
14
+ #
15
+ def each_pair
16
+ num = self.size/2
17
+ (0..num-1).collect do |index|
18
+ yield self[index*2], self[(index*2)+1]
19
+ end
20
+ end
21
+
22
+ # Splits the array into two parts first from position
23
+ # 0 to "position" and second from position "position+1" to
24
+ # last position.
25
+ # Returns two new arrays.
26
+ def separate(position)
27
+ return self[0..position], self[position+1..-1]
28
+ end
29
+
30
+ end
@@ -0,0 +1,180 @@
1
+ require "yaml"
2
+ require "logger"
3
+ require "rubygems"
4
+ require "active_support"
5
+
6
+ class GeneticAlgorithm
7
+ attr_reader :generations, :p_combination, :p_mutation
8
+
9
+ # Must be initialized with a Array of chromosomes
10
+ # To be a chomosome the object must implement the next methods:
11
+ # - fitness
12
+ # - recombine
13
+ # - mutate
14
+ # Accepts the next properties:
15
+ # - extra_generations: adds given array of generations to the GeneticAlgorithm's own array of generations.
16
+ # - p_combination: probability of combiantion ( by default 0.2 )
17
+ # - p_mutation: probability of mutation ( by default 0.01 )
18
+ # - max_population: maximum number of individuals that are allowed to form a generation.
19
+ # - logger: logger to write messages if given.
20
+ def initialize(in_pop, prop = {})
21
+ @generations = [in_pop]
22
+ @generations += prop[:extra_generations] if prop[:extra_generations]
23
+ @p_combination = prop[:p_combination] || 0.2
24
+ @p_mutation = prop[:p_mutation] || 0.01
25
+ @max_population = prop[:max_population]
26
+ @logger = prop[:logger] if prop[:logger]
27
+ @use_threads = prop[:use_threads] if prop[:use_threads]
28
+ # mean_fitness
29
+ end
30
+
31
+
32
+ # HELPER METHODS
33
+
34
+ # Returns the number of generations that are in the GeneticAlgorithm object.
35
+ def num_generations
36
+ @generations.size - 1
37
+ end
38
+
39
+ # Returns an array with the best fitted individuals for given
40
+ # generation number ( by default from last generation ).
41
+ def best_fit(num_generation = -1)
42
+ raise "Generation not generated still num generations = #{num_generations}" if num_generation > num_generations
43
+ generation = @generations[num_generation]
44
+ max_fitness = generation.collect { |chromosome| chromosome.fitness }.max
45
+ generation.select { |chromosome| chromosome.fitness == max_fitness }
46
+ end
47
+
48
+ # Returns the mean of the fitness for given
49
+ # generation number ( by default from last generation ).
50
+ def mean_fitness(num = -1)
51
+ raise "Generation not generated still num generations = #{num_generations}" if num > self.num_generations
52
+ num = self.num_generations if num == -1
53
+ sum_fitness = 0
54
+ @generations[num].each { |chromosome| sum_fitness += chromosome.fitness }
55
+ sum_fitness.to_f / @generations[num].size.to_f
56
+ end
57
+
58
+ # Returns a GeneticAlgorithm object with the generations
59
+ # loaded from given files and with properties prop.
60
+ # Files must contain the chromosomes in YAML format.
61
+ def self.populate_from_files(a_filenames, prop = {})
62
+ a_filenames = [a_filenames] if a_filenames.class == String
63
+
64
+ loaded_generations = a_filenames.collect { |filename| YAML.load(File.open(filename, "r")) }
65
+ prop[:extra_generations] = loaded_generations[1..-1] if loaded_generations.size > 1
66
+ return GeneticAlgorithm.new(loaded_generations[0], prop)
67
+ end
68
+
69
+ # Saves into filename and in yaml format the generation that matchs with given
70
+ # generation number ( by default from last generation ).
71
+ def save_generation(filename, num_generation = -1)
72
+ f = File.new(filename, "w")
73
+ f.write(self.generations[num_generation].to_yaml)
74
+ f.close
75
+ end
76
+
77
+ # EVOLUTION METHODS
78
+
79
+ # Evolves the actual generation num_steps steps (1 by default).
80
+ def evolve(num_steps = 1)
81
+ num_steps.times do
82
+ @generations << evaluation_with_threads(@generations[-1])
83
+ selection!
84
+ recombination!
85
+ mutation!
86
+ end
87
+ end
88
+
89
+ # Prepares given generation for evaluation ( evaluates its fitness ).
90
+ def evaluation(g)
91
+ @logger.debug "Evaluation " + g.size.to_s + " chromosomes." if @logger
92
+ i = 0
93
+ g.collect do |chromosome|
94
+ i += 1
95
+ @logger.debug "Evaluating chromosome #{i}:" if @logger
96
+ @logger.debug "#{chromosome.stats.join("\n")}" if @logger
97
+ chromosome.fitness
98
+ chromosome
99
+ end
100
+ end
101
+
102
+ # Prepares given generation for evaluation ( evaluates its fitness ),
103
+ # using Threads
104
+ def evaluation_with_threads(g)
105
+ @logger.debug "Evaluation " + g.size.to_s + " chromosomes." if @logger
106
+ threads = []
107
+ i = 0
108
+ g.each do |chromosome|
109
+ i += 1
110
+ @logger.debug "Evaluating chromosome #{i}:" if @logger
111
+ @logger.debug "#{chromosome.stats.join("\n")}" if @logger
112
+ threads << Thread.new(chromosome) do |t_chromosome|
113
+ t_chromosome.fitness
114
+ @logger.debug "Thread finished #{Thread.current.object_id} - #{Thread.current.status}" if @logger
115
+ end
116
+ end
117
+ # Wait for threads for finish
118
+ threads.each do |thread|
119
+ @logger.debug "#{thread.status}" if @logger
120
+ thread.join
121
+ @logger.debug "#{thread.status}" if @logger
122
+ end
123
+ return g
124
+ end
125
+
126
+
127
+ # Selects population to survive and recombine
128
+ def selection(g)
129
+ g_tmp = remainder_stochastic_sampling(g)
130
+ g_tmp = g_tmp.sort_by {|i| -i.fitness }[0..(@max_population-1)] if @max_population && (g_tmp.size > @max_population)
131
+ g_tmp
132
+ end
133
+ def selection!; @generations[-1] = selection(@generations[-1]); end
134
+
135
+ # Recombines population
136
+ def recombination(g)
137
+ @logger.debug "Recombination " + g.size.to_s + " chromosomes." if @logger
138
+ new_generation = g.dup.shuffle!
139
+ @logger.debug "Shuffled!" if @logger
140
+ new_children = []
141
+ new_generation.in_groups_of(2) do |chromosome1, chromosome2|
142
+ next if chromosome2.nil?
143
+ if rand > (1 - @p_combination)
144
+ @logger.debug "Recombining" if @logger
145
+ new_children << chromosome1.recombine(chromosome2)
146
+ end
147
+ end
148
+ new_generation + new_children
149
+ end
150
+
151
+ def recombination!; @generations[-1] = recombination(@generations[-1]); end
152
+
153
+ # Mutates population
154
+ def mutation(g)
155
+ @logger.debug "Mutation " + g.size.to_s + " chromosomes." if @logger
156
+ new_generation = g.dup
157
+ new_generation.each do |chromosome|
158
+ if rand > (1 - @p_mutation)
159
+ @logger.debug "Mutate" if @logger
160
+ chromosome.mutate
161
+ end
162
+ end
163
+ end
164
+ def mutation!; @generations[-1] = mutation(@generations[-1]); end
165
+
166
+ # Remainder Stochastic Sampling algorithm for selection.
167
+ def remainder_stochastic_sampling(g)
168
+ new_generation = []
169
+ g.each do |chromosome|
170
+ num_rep = 0
171
+ if chromosome.fitness > 0
172
+ num_rep += (chromosome.fitness.to_f/mean_fitness).to_i
173
+ num_rep += 1 if rand > (1 - (chromosome.fitness/mean_fitness)%1)
174
+ end
175
+ new_generation = new_generation + ([chromosome] * num_rep)
176
+ end
177
+ new_generation
178
+ end
179
+
180
+ end
@@ -0,0 +1,9 @@
1
+ module Gga4r #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 9
5
+ TINY = 2
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'gga4r/**/*.rb')].sort.each { |lib| require lib }
@@ -0,0 +1,61 @@
1
+ require 'prawn'
2
+ require 'prawn/measurement_extensions'
3
+ require 'barby'
4
+ require 'barby/outputter/prawn_outputter'
5
+
6
+ module OpenShip
7
+ module Label
8
+
9
+ class CartonLabel
10
+
11
+ attr_accessor :product, :style, :sku, :upc, :quantity, :origin
12
+
13
+ def gtin
14
+ self.upc.to_s.rjust(14, "0")
15
+ end
16
+
17
+ def to_pdf
18
+ document = Prawn::Document.new(:page_size => [11.cm, 6.7.cm],
19
+ :right_margin => 0.0.cm,
20
+ :left_margin => 0.0.cm,
21
+ :top_margin => 0.0.cm,
22
+ :bottom_margin => 0.0.cm,
23
+ :page_layout => :portrait)
24
+
25
+ barcode = Barby::Code25Interleaved.new(self.gtin)
26
+
27
+ barcode.annotate_pdf(document, {:x => 0.5.cm, :y => 1.7.cm, :xdim => 0.073.cm, :height => 2.5.cm})
28
+
29
+ document.stroke do
30
+ document.rectangle [0.5.cm,6.4.cm], 1.5.cm, 1.5.cm
31
+ end
32
+
33
+
34
+ document.text_box("QTY", :size => 16, :align => :center, :at => [0.5.cm, 6.3.cm], :width => 1.5.cm, :height => 1.cm)
35
+ document.text_box(self.quantity.to_s, :size => 20, :align => :center, :at => [0.5.cm, 5.7.cm], :width => 1.5.cm, :height => 1.5.cm)
36
+
37
+
38
+ document.text_box(self.gtin[0..7], :size => 16, :align => :left, :at => [2.2.cm, 6.3.cm], :width => 2.cm, :height => 1.cm)
39
+ document.text_box(self.gtin[8..12], :size => 20, :align => :left, :at => [2.2.cm, 5.7.cm], :width => 2.5.cm, :height => 1.5.cm)
40
+
41
+ document.text_box(self.product, :size => 12, :align => :right, :at => [5.5.cm, 6.4.cm], :width => 5.cm, :height => 0.5.cm)
42
+ document.text_box(self.style, :size => 12, :align => :right, :at => [5.5.cm, 5.9.cm], :width => 5.cm, :height => 0.5.cm)
43
+ document.text_box(self.sku, :size => 12, :align => :right, :at => [5.5.cm, 5.4.cm], :width => 5.cm, :height => 0.5.cm)
44
+
45
+ document.text_box(self.origin, :size => 10, :align => :center, :at => [0.cm, 0.75.cm], :width => 11.cm, :height => 0.5.cm)
46
+
47
+ document.font("Courier")
48
+
49
+ document.text_box(self.gtin[0..0], :size => 16, :align => :left, :at => [1.25.cm, 1.5.cm], :width => 0.8.cm, :height => 1.cm)
50
+ document.text_box(self.gtin[1..2], :size => 16, :align => :left, :at => [2.3.cm, 1.5.cm], :width => 1.cm, :height => 1.cm)
51
+ document.text_box(self.gtin[3..7], :size => 16, :align => :left, :at => [3.7.cm, 1.5.cm], :width => 2.cm, :height => 1.cm)
52
+ document.text_box(self.gtin[8..12], :size => 16, :align => :left, :at => [6.45.cm, 1.5.cm], :width => 2.cm, :height => 1.cm)
53
+ document.text_box(self.gtin[13..13], :size => 16, :align => :left, :at => [9.15.cm, 1.5.cm], :width => 1.cm, :height => 1.cm)
54
+
55
+ document
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ require 'prawn'
2
+ require 'prawn/measurement_extensions'
3
+ require 'barby'
4
+ require 'barby/outputter/prawn_outputter'
5
+
6
+ module OpenShip
7
+ module Label
8
+
9
+ class TextLabel
10
+
11
+ attr_accessor :address1, :address2, :address3, :address4,
12
+ :sku, :po, :line, :quantity, :total_cartons
13
+
14
+ def to_pdf
15
+ document = Prawn::Document.new(:page_size => [20.cm, 15.cm],
16
+ :page_layout => :portrait)
17
+
18
+
19
+ document.text_box(self.address1, :size => 16, :align => :left, :at => [0.2.cm, 11.cm], :width => 12.cm, :height => 0.75.cm)
20
+ document.text_box(self.address2, :size => 16, :align => :left, :at => [0.2.cm, 10.25.cm], :width => 12.cm, :height => 0.75.cm)
21
+ document.text_box(self.address3, :size => 16, :align => :left, :at => [0.2.cm, 9.5.cm], :width => 12.cm, :height => 0.75.cm)
22
+ document.text_box(self.address4, :size => 16, :align => :left, :at => [0.2.cm, 8.75.cm], :width => 12.cm, :height => 0.75.cm)
23
+
24
+
25
+ po_line = "PO#: #{self.po}"
26
+ document.text_box(po_line, :size => 16, :align => :left, :at => [0.2.cm, 7.25.cm], :width => 12.cm, :height => 0.75.cm)
27
+
28
+ line_no = "Line #: #{self.line}"
29
+ document.text_box(line_no, :size => 16, :align => :left, :at => [0.2.cm, 6.5.cm], :width => 12.cm, :height => 0.75.cm)
30
+
31
+ style_line = "Mfg Style #: #{self.sku}"
32
+ document.text_box(style_line, :size => 16, :align => :left, :at => [0.2.cm, 5.75.cm], :width => 12.cm, :height => 0.75.cm)
33
+
34
+ quantity_line = "Inner Pk Qty: #{self.quantity}"
35
+ document.text_box(quantity_line, :size => 16, :align => :left, :at => [0.2.cm, 5.cm], :width => 12.cm, :height => 0.75.cm)
36
+
37
+ total_cartons_line = "Total Master Pk. Cartons per Line Item: #{self.total_cartons}"
38
+ document.text_box(total_cartons_line, :size => 16, :align => :left, :at => [0.2.cm, 4.25.cm], :width => 15.cm, :height => 0.75.cm)
39
+
40
+
41
+ document.text_box("Pre-Priced: NO", :size => 20, :align => :left, :at => [0.2.cm, 3.cm], :width => 12.cm, :height => 1.cm)
42
+ document.text_box("FRAGILE: NO", :size => 20, :align => :left, :at => [0.2.cm, 2.cm], :width => 12.cm, :height => 1.cm)
43
+
44
+
45
+ document
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -1,6 +1,6 @@
1
1
  module OpenShip
2
2
 
3
- class Label
3
+ module Label
4
4
 
5
5
  end
6
6
 
@@ -0,0 +1,279 @@
1
+ require "activesupport"
2
+
3
+ module OpenShip
4
+
5
+
6
+
7
+ class BoxPosition
8
+ attr_accessor :position, :box
9
+
10
+ def get_relative_space
11
+ self.box.get_space(:relative_position => self.position)
12
+ end
13
+
14
+ end
15
+
16
+ class Position
17
+
18
+ attr_accessor :x, :y, :z
19
+
20
+ end
21
+
22
+ class Box
23
+ attr_accessor :length, :width, :height, :label, :weight, :product_quantity
24
+
25
+ def volume
26
+ (length * width * height)
27
+ end
28
+
29
+
30
+
31
+ end
32
+
33
+ class Carton < Box
34
+ attr_accessor :margin, :box_positions, :width_margin, :length_margin
35
+
36
+ def initialize()
37
+ self.box_positions = []
38
+ end
39
+
40
+ @last_box = nil
41
+
42
+ def space_packed(pos)
43
+ packed = false
44
+ self.box_positions.each { |bp|
45
+ unless packed
46
+ if ((pos.x >= bp.position.x) && (pos.x < (bp.box.width + bp.position.x)))
47
+ if ((pos.y >= bp.position.y) && (pos.y < (bp.box.length + bp.position.y)))
48
+ if ((pos.z >= bp.position.z) && (pos.z < (bp.box.height + bp.position.z)))
49
+ packed = true
50
+ end
51
+ end
52
+ end
53
+ end
54
+ }
55
+ packed
56
+ end
57
+
58
+ def get_space(opts={})
59
+ space = []
60
+ z_pos = 0
61
+ while (z_pos < self.height)
62
+ y_pos = 0
63
+ while(y_pos < self.length)
64
+ x_pos = 0
65
+ while(x_pos < self.width)
66
+ pos = Position.new
67
+ pos.x = x_pos
68
+ pos.y = y_pos
69
+ pos.z = z_pos
70
+ unless self.space_packed(pos)
71
+ space << pos
72
+ end
73
+ x_pos += 1
74
+ end
75
+ y_pos += 1
76
+ end
77
+ z_pos += 1
78
+ end
79
+ space
80
+ end
81
+
82
+ def free_space
83
+ self.volume - (self.box_positions.collect { |bp| bp.box }.sum { |bx| bx.volume })
84
+ end
85
+
86
+ def position_for_box(box)
87
+ spot = nil
88
+ free_space = self.get_space
89
+ free_space.each { |sp|
90
+ if ((self.width - sp.x) >= box.width)
91
+ if ((self.length - sp.y) >= box.length)
92
+ if ((self.height - sp.z) >= box.height)
93
+ # Test for potential overlaps
94
+ overlap = false
95
+ self.box_positions.each { |bp|
96
+
97
+ if ( ((bp.position.x + bp.box.width) > sp.x) && ((sp.x + box.width) > bp.position.x) )
98
+ if ( ((bp.position.z + bp.box.height) > sp.z) && ((sp.z + box.height) > bp.position.z) )
99
+ if ( ((bp.position.y + bp.box.length) > sp.y) && ((sp.y + box.length) > bp.position.y) )
100
+ overlap = true;
101
+ break
102
+ end
103
+ end
104
+ end
105
+ }
106
+ unless overlap
107
+ spot = sp
108
+ break
109
+ end
110
+ end
111
+ end
112
+ end
113
+ }
114
+ spot
115
+ end
116
+
117
+ def add_box(box)
118
+ if box.volume > self.free_space
119
+ return nil
120
+ end
121
+ pos = self.position_for_box(box)
122
+ if pos
123
+ bp = OpenShip::BoxPosition.new
124
+ bp.box = box
125
+ bp.position = pos
126
+ self.box_positions << bp
127
+ end
128
+ pos
129
+ end
130
+
131
+
132
+
133
+ end
134
+
135
+ class OpenShip::Shipment
136
+
137
+ @@fitness_values = []
138
+
139
+
140
+ attr_accessor :boxes_to_stores, :cartons_to_stores, :logger, :carton_dispenser
141
+
142
+ class CartonDispenser
143
+
144
+ def get_carton
145
+ cart = OpenShip::Carton.new
146
+ cart.width = 20
147
+ cart.height = 20
148
+ cart.length = 10
149
+ cart
150
+ end
151
+
152
+ end
153
+
154
+ def initialize(opts = {})
155
+ if opts[:logger]
156
+ @logger = opts[:logger]
157
+ else
158
+ @logger = Logger.new(STDOUT)
159
+ @logger.level = Logger::WARN
160
+ end
161
+ if opts[:carton_dispenser]
162
+ @carton_dispenser = opts[:carton_dispenser]
163
+ else
164
+ @carton_dispenser = CartonDispenser.new
165
+ end
166
+ @cartons_to_stores = nil
167
+ @boxes_to_stores = {}
168
+ end
169
+
170
+ def calculate_cartons
171
+ @cartons_to_stores = {}
172
+ self.boxes_to_stores.each { |k, v|
173
+ @cartons_to_stores[k] ||= []
174
+ cart = @carton_dispenser.get_carton
175
+ @cartons_to_stores[k] << cart
176
+ v.each { |box|
177
+ pos = cart.add_box(box)
178
+ if pos.nil?
179
+ cart = @carton_dispenser.get_carton
180
+ @cartons_to_stores[k] << cart
181
+ pos = cart.add_box(box)
182
+ if pos.nil?
183
+ raise "Box is too big for carton."
184
+ end
185
+ end
186
+ }
187
+ }
188
+ @cartons_to_stores
189
+ end
190
+
191
+ def fitness
192
+
193
+ if @cartons_to_stores.nil?
194
+ self.calculate_cartons
195
+ end
196
+
197
+ free_space = self.cartons_to_stores.sum { |k, v| v.sum { |c| c.free_space } }
198
+ box_count = self.boxes_to_stores.sum { |k, v| v.count }
199
+ carton_count = self.cartons_to_stores.sum { |k, v| v.count }
200
+ @logger.debug "Box Count: " + box_count.to_s
201
+ @logger.debug "Carton Free Space: " + free_space.to_s
202
+ @logger.debug "Carton Count: " + carton_count.to_s
203
+ fitness = (box_count.to_f / carton_count.to_f)
204
+ @@fitness_values << fitness
205
+ @logger.debug "Fitness Mean: " + fitness_mean.to_s
206
+ @logger.debug "Fitness: " + fitness.to_s
207
+ fitness
208
+ end
209
+
210
+ def stats
211
+ ["Total Volume :" + self.boxes_to_stores.sum { |k, v| v.sum { |b| b.volume } }.to_s]
212
+ end
213
+
214
+
215
+ def recombine(c2)
216
+ return1 = self.clone
217
+ return2 = c2.clone
218
+ self.boxes_to_stores.each { |k, v|
219
+ bxs = c2.boxes_to_stores[k]
220
+
221
+ cross_point = (rand * bxs.size).to_i
222
+ c1_a, c1_b = v.separate(cross_point)
223
+ c2_a, c2_b = bxs.separate(cross_point)
224
+ return1.boxes_to_stores[k] = c1_a + c2_b
225
+ return2.boxes_to_stores[k] = c2_a + c1_b
226
+ }
227
+ return1.cartons_to_stores = nil
228
+ return2.cartons_to_stores = nil
229
+ return1
230
+ end
231
+
232
+ def fitness_mean
233
+ (@@fitness_values.sum { |f| f } / @@fitness_values.length)
234
+ end
235
+
236
+ def mutate
237
+ #if (self.fitness < self.fitness_mean)
238
+ @logger.debug "################ Making a mutation!"
239
+ self.boxes_to_stores.each { |k, v|
240
+ self.boxes_to_stores[k] = v.shuffle
241
+ }
242
+ #end
243
+ self
244
+ end
245
+
246
+ def run_ga(generations = 10, population_size = 10)
247
+ @@fitness_values = []
248
+
249
+ population = []
250
+ population_size.times {
251
+ #ship = OpenShip::Shipment.new(:logger => @logger, :carton_dispenser => @carton_dispenser)
252
+ ship = self.clone
253
+ ship.boxes_to_stores = self.boxes_to_stores.clone
254
+
255
+ ship.boxes_to_stores.each { |k, v|
256
+ ship.boxes_to_stores[k] = v.shuffle
257
+ }
258
+ population << ship
259
+ }
260
+ ga = GeneticAlgorithm.new(population, {:logger => @logger})
261
+ generations.times { ga.evolve }
262
+ best_fit = ga.best_fit[0]
263
+ best_fit.cartons_to_stores.each { |k, v|
264
+ puts k
265
+ v.each { |cart|
266
+ @logger.debug "Carton"
267
+ cart.box_positions.each { |bp|
268
+ @logger.debug "length: " + bp.box.length.to_s + " width: " + bp.box.width.to_s + " height: " + bp.box.height.to_s
269
+ @logger.debug "x: " + bp.position.x.to_s + " y: " + bp.position.y.to_s + " z: " + bp.position.z.to_s
270
+ }
271
+ }
272
+ }
273
+ best_fit.fitness
274
+ best_fit
275
+ end
276
+
277
+ end
278
+
279
+ end
File without changes
data/lib/open-ship.rb ADDED
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
2
+
3
+ module OpenShip
4
+
5
+ end
6
+
7
+ require 'open-ship/sscc'
8
+ require 'open-ship/sortr'
9
+ require 'open-ship/label'
10
+ require 'open-ship/label/carton_label'
11
+ require 'open-ship/label/text_label'
12
+ require 'open-ship/gga4r'
13
+