open-ship 0.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+