opt_alg_framework 1.0.3 → 1.0.4

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NTBlMTIwMTFlNmJhY2Q4YmEzYTdiNDdmYjA4NTgxOGM4NzlhNTI3NA==
5
- data.tar.gz: !binary |-
6
- ZmUwM2I2ZjM1YjBhNzY0YjBlOTNmYWVhM2JlY2Q5YTkyOTcwMGY1NA==
2
+ SHA1:
3
+ metadata.gz: e5238e0506bf85414aee3fb138a49038c83ebb2d
4
+ data.tar.gz: e0f07c319a8d4f8e8bac291f1a9f73862153d370
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NWUwZjdjYjFkZDgwYTI4ZDM5NTUxNWVkZjZkNzRmMjE2OTc2ZTZhMjg3ZjY5
10
- Y2NlNmRiYzdlNWIxYTc1MDBiMWEzODNmNzljYmU2Nzc1NDAwNTkwNWE4YTk1
11
- MTE3ODY4YmQwYWJiM2NjMzc0OGJmYThmZTUyMDdmMzNlNmQ0NmI=
12
- data.tar.gz: !binary |-
13
- MDcwNmEzZDQ2NDFlN2NlMGFkMTAxYTllMDdlYjYzOWRiODU5MjY5MGEyM2Jh
14
- NDAzZWZjYTQxZThhN2Y3YWIyNmQwMmNmOThmZWU5ODUzNDEzYWE0ODRmNTM1
15
- NDQ0MzhlNGJkMDc4OTE1OTAyZjBlNWRmM2IwYTI1MmY0NjI1NmM=
6
+ metadata.gz: 1f4296bb2cc65002a2e1409c674f76e249790c316d61c91ef214e83b18b4658ea82cadb22548f22816c7c779d7ee1fae38e401ec0ea2fe86e598149ade080b9b
7
+ data.tar.gz: 9551a80e24e9967b52f44490d9d4c8a95236ed955f5acea96d53698d5d03bf94834bbe8dee8d8c5ac91e50185e97ce9e7e4e964ecf449ea58617e3dfec230b9f
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'rint'
3
4
  # Specify your gem's dependencies in opt_alg_framework.gemspec
4
5
  gemspec
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # OptAlgFramework
1
+ # opt-alg-framework (Optimization Algorithm Framework)
2
2
 
3
- Opt-Alg-Framework is a framework to work and build optimization algorithm. The basic idea is: you will have a codificated problem with a method to calculate its fitnes, an algorithm to improve the this fitness and operators used with the algorithm to build new solutions.
3
+ **opt-alg-framework** is a framework to work with and build optimization algorithm. The basic idea is: you will have a codificated problem with a method to calculate its fitness, an algorithm to improve this fitness and operators used with the algorithm to build new solutions.
4
4
 
5
5
  What is already implemented:
6
6
 
@@ -31,7 +31,7 @@ gem 'opt_alg_framework'
31
31
 
32
32
  And then execute:
33
33
 
34
- $ bundle
34
+ $ bundle install
35
35
 
36
36
  Or install it yourself as:
37
37
 
@@ -39,46 +39,28 @@ Or install it yourself as:
39
39
 
40
40
  ## Usage
41
41
 
42
- Example: read two instances of FSP problem (about the instances format, read README in *problem* directory!) and get its best results with Simulated Annealing algorithm, using RandomSwap operator.
42
+ Example: Read two instances of FSP problem (about the instances format, read README in *problem* directory!) and get its best results with SimulatedAnnealing algorithm, using RandomSwap operator.
43
43
 
44
44
  ```ruby
45
45
  operator = Operator::Tweak::RandomSwap.new
46
46
  problem = Problem::FSP.new
47
- problem.load_schedule(path)
47
+ problem.load_schedule("path to instance file")
48
48
  algorithm = Algorithm::LocalSearch::SimulatedAnnealing.new max_iterations: 10,
49
49
  cooling_rate: 0.009,
50
50
  problem: problem,
51
51
  tweak_operator: operator
52
52
 
53
- puts algorithm.start[:fitness]
53
+ puts algorithm.start # It will return a hash with the best solution found and its fitness
54
54
  ```
55
55
 
56
56
  ## Development
57
57
 
58
58
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` or, alternatively, `bundle console` for an interactive prompt that will allow you to experiment.
59
59
 
60
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
61
-
62
- ####Some conventions must be followed:
63
-
64
- * All problem classes need to have its fitness method acessible with the name *fitness*;
65
- * All swap operator classes need to have its swap method acessible with the name *tweak*;
66
- * All crossover operator classes need to have its crossover method named *cross*;
67
- * All selector operator classes need to have its selection method names *select*;
68
- * All algorithm classes need to have its main method names *start*;
69
- * In the algorithms, a solution is represent with a hash structure, and it's mandatory have at least the pair key-value *:solution* with the representation of the solution and *:fitness* with the fitness of the solution.
70
-
71
- ####TODO:
72
-
73
- * Treatments to verify if the conventions are being followed;
74
- * General implementations, like:
75
- * Local search algorithms;
76
- * Population based algorithms;
77
- * Operators (crossover, swap, selector) to any type of problem (permutational, binary, etc);
78
- * Different type of problems.
79
-
80
60
  ## Contributing
81
61
 
62
+ **This gem can deal with a lot of stuff, and everything must be simple to use (a.k.a *generic*). Before start to code, take a look in the README inside the folder of what you want to code (algorithms, problems, etc), some tips of what your class should have are there. Sugestions are welcome too! (;**
63
+
82
64
  1. Fork it ( https://github.com/[my-github-username]/opt_alg_framework/fork )
83
65
  2. Create your feature branch (`git checkout -b my-new-feature`)
84
66
  3. Commit your changes (`git commit -am 'Add some feature'`)
@@ -1,6 +1,16 @@
1
- valid_files = Dir["#{File.dirname(__FILE__)}/**/*.rb"].reject {|f| File.directory?(f) }
2
- valid_files.each { |f| require f }
1
+ require 'opt_alg_framework/algorithm/algorithm_interface'
2
+ require 'opt_alg_framework/problem/problem_interface'
3
+ require 'opt_alg_framework/operator/tweak/tweak_interface'
4
+ require 'opt_alg_framework/operator/selector/selector_interface'
5
+ require 'opt_alg_framework/operator/crossover/crossover_interface'
6
+
7
+ Dir[File.dirname(__FILE__) + "/opt_alg_framework/problem/**/*.rb"].each { |f| require f }
8
+ Dir[File.dirname(__FILE__) + "/opt_alg_framework/operator/**/*.rb"].each { |f| require f }
9
+ Dir[File.dirname(__FILE__) + "/opt_alg_framework/algorithm/**/*.rb"].each { |f| require f }
10
+
11
+ #valid_files = Dir["#{File.dirname(__FILE__)}/**/*.rb"].reject {|f| File.directory?(f) }
12
+ #valid_files.each { |f| require f }
3
13
 
4
14
  module OptAlgFramework
5
- # Write your code here
15
+
6
16
  end
@@ -0,0 +1,8 @@
1
+ # Implementation Details
2
+
3
+ * Inside your class, use `implements AlgorithmInterface`. That provides an interface behavior, enforcing
4
+ the implementation of mandatory methods;
5
+ * Organize algorithm class inside modules (e.g., `HillClimbing` class);
6
+ * `initialize` have only a hash like argument, where the configurations used in algorithm are specifyied;
7
+ * A solution is represented like a hash, with at least `:solution` and `:fitness` keys. The best solution should be
8
+ returned by the main method.
@@ -0,0 +1,10 @@
1
+ require 'interface'
2
+
3
+ module AlgorithmInterface
4
+ include Interface
5
+
6
+ def initialize(params = {})
7
+ must_implement start: 0
8
+ super(params)
9
+ end
10
+ end
@@ -1,34 +1,36 @@
1
1
  module Algorithm
2
2
  module LocalSearch
3
3
  class HillClimbing
4
+ implements AlgorithmInterface
5
+
4
6
  # Initialize passing a instantiated class of a problem and tweak operator
5
7
  def initialize(params)
6
8
  @tweak_operator = params[:tweak_operator]
7
9
  @problem = params[:problem]
8
10
  end
9
11
 
10
- # Main method
12
+ # solution_b = best solution
13
+ # solution_n = neighbor solution
11
14
  def start
12
- best = encapsulate_solution(@problem.default_solution)
15
+ solution_b = encapsulate_solution(@problem.default_solution.shuffle)
13
16
  while true do
14
- r = encapsulate_solution(@tweak_operator.tweak(best[:solution]))
15
- if r[:fitness] < best[:fitness]
16
- best = r.dup
17
+ solution_n = encapsulate_solution(@tweak_operator.tweak(solution_b[:solution]))
18
+ if solution_n[:fitness] < solution_b[:fitness]
19
+ solution_b = solution_n.dup
17
20
  else
18
21
  break
19
22
  end
20
23
  end
21
- best
24
+ solution_b
22
25
  end
23
26
 
24
27
  # Solution is a hash, with the keys :solution and :fitness
25
28
  def encapsulate_solution(solution)
26
29
  hash = Hash.new
27
30
  hash[:solution] = solution
28
- hash[:fitness] = @problem.fitness(tasks_sequence: solution)
31
+ hash[:fitness] = @problem.fitness(solution)
29
32
  hash
30
33
  end
31
-
32
34
  end
33
35
  end
34
36
  end
@@ -1,8 +1,8 @@
1
1
  module Algorithm
2
2
  module LocalSearch
3
3
  class SimulatedAnnealing
4
+ include AlgorithmInterface
4
5
  include Math
5
- attr_reader :temperature
6
6
 
7
7
  # Initialize specifying the cooling rate percentage (@cooling_rate), number of iterations in each
8
8
  # temperature (@max_iterations) and passing an instantiated problem and tweak operator class.
@@ -14,22 +14,24 @@ module Algorithm
14
14
  @temperature = initial_temperature
15
15
  end
16
16
 
17
- # Main method.
17
+ # solution_b = best solution
18
+ # solution_n = neighbor solution
19
+ # solution_c = current solution
18
20
  def start
19
- best = encapsulate_solution(@problem.default_solution.shuffle)
20
- current = best.dup
21
+ solution_b = encapsulate_solution(@problem.default_solution.shuffle)
22
+ solution_c = solution_b.dup
21
23
  temperature = @temperature
22
24
  while temperature > 1 do
23
25
  iteration = 1
24
26
  while iteration < @max_iterations do
25
- neighbor = encapsulate_solution(@tweak_operator.tweak(current[:solution]))
26
- current = neighbor.dup if accept?(current[:fitness], neighbor[:fitness], temperature)
27
- best = current.dup if current[:fitness] < best[:fitness]
27
+ solution_n = encapsulate_solution(@tweak_operator.tweak(solution_c[:solution]))
28
+ solution_c = solution_n.dup if accept?(solution_c[:fitness], solution_n[:fitness], temperature)
29
+ solution_b = solution_c.dup if solution_c[:fitness] < solution_b[:fitness]
28
30
  iteration += 1
29
31
  end
30
32
  temperature *= 1 - @cooling_rate
31
33
  end
32
- best
34
+ solution_b
33
35
  end
34
36
 
35
37
  private
@@ -50,7 +52,7 @@ module Algorithm
50
52
  def encapsulate_solution(solution)
51
53
  hash = Hash.new
52
54
  hash[:solution] = solution
53
- hash[:fitness] = @problem.fitness(tasks_sequence: solution)
55
+ hash[:fitness] = @problem.fitness(solution)
54
56
  hash
55
57
  end
56
58
 
@@ -1,8 +1,9 @@
1
1
  module Algorithm
2
2
  module LocalSearch
3
3
  class TabuSearch
4
+ implements AlgorithmInterface
4
5
 
5
- # Initialize specifying as parameters the tabu list size (@list_max_size), number of tweaks in each
6
+ # Initialize specifying as parameters the tabu list size (@list_max_size), number of tweaks in each
6
7
  # current solution (@tweak_number), number of iteratiions to perform in the algorithm (@iterations)
7
8
  # and an instantiated problem and tweak operator class.
8
9
  def initialize(params)
@@ -16,30 +17,32 @@ module Algorithm
16
17
 
17
18
  # Main method.
18
19
  def start
19
- s = encapsulate_solution(@problem.default_solution.dup)
20
- best = s.dup
21
- @tabu_list << s[:solution]
20
+ solution_c = encapsulate_solution(@problem.default_solution.dup)
21
+ solution_s = solution_c.dup
22
+ @tabu_list << solution_c[:solution]
22
23
  @iterations.times do
23
24
  @tabu_list.shift if @tabu_list.size == @list_max_size
24
- r = encapsulate_solution(@tweak_operator.tweak(s[:solution]))
25
+ solution_bn = solution_n1 = encapsulate_solution(@tweak_operator.tweak(solution_c[:solution]))
25
26
  (@tweak_number - 1).times do
26
- w = encapsulate_solution(@tweak_operator.tweak(s[:solution]))
27
- r = w.dup if !@tabu_list.include?(w) && w[:fitness] < r[:fitness] || @tabu_list.include?(r[:solution])
27
+ solution_n2 = encapsulate_solution(@tweak_operator.tweak(solution_c[:solution]))
28
+ solution_bn = solution_n2.dup if !@tabu_list.include?(solution_n2) &&
29
+ solution_n2[:fitness] < solution_n1[:fitness] ||
30
+ @tabu_list.include?(solution_n1[:solution])
28
31
  end
29
- if !@tabu_list.include?(r[:solution])
30
- s = r.dup
31
- @tabu_list << r
32
+ if !@tabu_list.include?(solution_bn[:solution])
33
+ solution_c = solution_bn.dup
34
+ @tabu_list << solution_n1
32
35
  end
33
- best = s.dup if s[:fitness] < best[:fitness]
36
+ solution_s = solution_c.dup if solution_c[:fitness] < solution_s[:fitness]
34
37
  end
35
- best
38
+ solution_s
36
39
  end
37
40
 
38
41
  # A solution is a hash, with the keys :solution and :fitness.
39
42
  def encapsulate_solution(solution)
40
43
  hash = Hash.new
41
44
  hash[:solution] = solution
42
- hash[:fitness] = @problem.fitness(tasks_sequence: solution)
45
+ hash[:fitness] = @problem.fitness(solution)
43
46
  hash
44
47
  end
45
48
  end
@@ -0,0 +1,8 @@
1
+ # Implementation Details
2
+
3
+ * Inside your class, use `implements [interface class name]`. That provides an interface behavior, enforcing
4
+ the implementation of mandatory methods. Different operators, different interfaces, take a look inside the folder of your
5
+ type of operator and see what is being used (you can identify it looking for a file who name ends with `interface`);
6
+ * Organize algorithm class inside modules (e.g., `RandomSwap` class);
7
+ * `initialize` have no arguments.
8
+
@@ -0,0 +1,10 @@
1
+ require 'interface'
2
+
3
+ module CrossoverInterface
4
+ include Interface
5
+
6
+ def initialize
7
+ must_implement cross:2
8
+ super
9
+ end
10
+ end
@@ -1,8 +1,9 @@
1
1
  module Operator
2
2
  module Crossover
3
3
  module Permutation
4
-
5
4
  class TwoPointCrossover
5
+ implements CrossoverInterface
6
+
6
7
  # Main method.
7
8
  def cross(chromossome1, chromossome2)
8
9
  point1 = Random.rand(0..chromossome1.size - 1)
@@ -27,7 +28,7 @@ module Operator
27
28
  start_piece + middle_piece + end_piece
28
29
  end
29
30
  end
30
-
31
+
31
32
  end
32
33
  end
33
34
  end
@@ -0,0 +1,10 @@
1
+ require 'interface'
2
+
3
+ module SelectorInterface
4
+ include Interface
5
+
6
+ def initialize(param)
7
+ must_implement select:1
8
+ super(param)
9
+ end
10
+ end
@@ -1,7 +1,8 @@
1
1
  module Operator
2
2
  module Selector
3
-
4
3
  class TournamentSelection
4
+ implements SelectorInterface
5
+
5
6
  # Initialize informing the tournament size.
6
7
  def initialize(size)
7
8
  @size = size
@@ -17,6 +18,5 @@ module Operator
17
18
  best_individual
18
19
  end
19
20
  end
20
-
21
21
  end
22
22
  end
@@ -1,8 +1,8 @@
1
1
  module Operator
2
2
  module Tweak
3
-
4
3
  class RandomSwap
5
- # Main method.
4
+ implements TweakInterface
5
+
6
6
  def tweak(solution)
7
7
  copy = solution.dup
8
8
  piece1 = Random.rand(0...copy.size)
@@ -13,6 +13,5 @@ module Operator
13
13
  copy
14
14
  end
15
15
  end
16
-
17
16
  end
18
17
  end
@@ -0,0 +1,10 @@
1
+ require 'interface'
2
+
3
+ module TweakInterface
4
+ include Interface
5
+
6
+ def initialize
7
+ must_implement tweak:1
8
+ super
9
+ end
10
+ end
@@ -1,7 +1,15 @@
1
- # About the instaces of the problems
1
+ # Implementation Details
2
+
3
+ * Inside your class, use `implements ProblemInterface`. That provides an interface behavior, enforcing
4
+ the implementation of mandatory methods;
5
+ * Organize algorithm class inside modules (e.g., `FSP` class);
6
+ * `initialize` have no arguments;
7
+ * Make sure that you have `attr_reader :default_solution` in your class and fill this instance variable with an initial solution. This variable will be called inside algorithm classes.
8
+
9
+ # About the problem instances
2
10
 
3
11
  ## FSP (Flow Shop Permutation)
4
- The instance of this kind of problem is a matrix, specifically a matrix where the rows are tasks and columns are machines. The fitness method need that to work properly.
12
+ The instance of this kind of problem is a matrix, specifically a matrix where the rows are tasks and columns are machines. This order need to be preserved to the fitness method work properly.
5
13
 
6
14
  A valid instance example is shown bellow, with 5 tasks (lines) and 3 machines (columns):
7
15
 
@@ -11,10 +19,8 @@ A valid instance example is shown bellow, with 5 tasks (lines) and 3 machines (c
11
19
  > 33 21 22 <br>
12
20
  > 10 9 11 <br>
13
21
 
14
- However, if your instance file is an inverted matrix (rows are machines and columns are tasks), just set the *transpose* parameter of *load_schedule* method to *true*:
22
+ However, if your instance file is an inverted matrix (rows are machines and columns are tasks), just pass *true* in a block to transpose the matrix.
15
23
 
16
24
  ```ruby
17
- fsp.load_schedule(path_to_instance, true)
25
+ fsp.load_schedule(path_to_instance) { true }
18
26
  ```
19
-
20
- That will invert the matrix to the right format.
@@ -1,10 +1,13 @@
1
1
  module Problem
2
-
2
+ #require 'opt_alg_framework/problem/problem_interface'
3
3
  # FSP class have a inner class Schedule
4
4
  class FSP
5
- # Inner class who represents the production schedule, that is, a matrix were the rows are the tasks
6
- # and the columns the machines.
7
- class Schedule
5
+ implements ProblemInterface
6
+ attr_reader :default_solution
7
+
8
+ # Inner class who represents the production schedule, that is, a matrix
9
+ # were the rows are the tasks and the columns the machines.
10
+ class Production
8
11
  require 'matrix'
9
12
 
10
13
  attr_reader :schedule
@@ -28,61 +31,62 @@ module Problem
28
31
  end
29
32
  end
30
33
 
31
- attr_reader :default_solution # Is the sequence of tasks ordered from 0...N
34
+ # Initialize the FSP problem with a empty schedule
35
+ def initialize
36
+ @production = Production.new
37
+ end
32
38
 
33
- # Used in makespan function to compare two execution times (also if one of them or the two are blank)
34
- @@bigger = Proc.new do |a, b|
35
- a ||= b ||= 0
36
- if a > b ||= 0 then a else b end
37
- end
39
+ # Load the production schedule from a file
40
+ def load_instance(path)
41
+ transpose = block_given? ? yield : false
42
+ @production.build_from_file(path, transpose)
43
+ @default_solution = (0...@production.schedule.row_size).to_a
44
+ end
38
45
 
39
- # Initialize the FSP problem with a empty schedule
40
- def initialize
41
- @schedule = Schedule.new()
42
- end
46
+ def fitness(solution)
47
+ schedule = @production.reorder_schedule(solution)
48
+ makespan(schedule: schedule, task: schedule.row_size - 1,
49
+ machine: schedule.column_size - 1, memory: {})
50
+ end
51
+
52
+ private
53
+
54
+ def bigger(num1 = 0, num2 = 0)
55
+ num1 ||= num2 ||= 0
56
+ if num1 > num2 ||= 0 then num1 else num2 end
57
+ end
58
+
59
+ # The hash options are:
60
+ # - schedule: matrix of the production schedule;
61
+ # - task: task index;
62
+ # - machine: machine index;
63
+ # - memory: store the total time spent at the point where the task index X is processed at the machine index Y
64
+ # (that avoid desnecessary recursive calls).
65
+ def makespan(options = {})
66
+ schedule = options[:schedule]
67
+ task = options[:task]
68
+ machine = options[:machine]
69
+ memory = options[:memory]
70
+ key = "#{task},#{machine}"
71
+ time = schedule[task, machine]
43
72
 
44
- # Load the production schedule from a file
45
- def load_schedule(path, transpose = false)
46
- @schedule.build_from_file(path, transpose)
47
- @default_solution = (0...@schedule.schedule.row_size).to_a
73
+ return time if task == 0 && machine == 0
74
+
75
+ if task > 0 # Before everithing, calculate the time spent in the tasks from N to 0
76
+ time_task_before = memory["#{task - 1},#{machine}"]
77
+ time_task_before = makespan(schedule: schedule, task: task - 1,
78
+ machine: machine, memory: memory) if memory["#{task - 1},#{machine}"].nil?
48
79
  end
49
80
 
50
- # Fitness function. The hash options are:
51
- # - schedule: matrix of the production schedule;
52
- # - task: task index;
53
- # - machine: machine index;
54
- # - memory: store the total time spent at the point where the task index X is processed at the machine index Y
55
- # (that avoid desnecessary recursive calls);
56
- # - tasks_sequence: sequence of tasks used to reorganize the schedule after calculate its makespan.
57
- # The default use of the method is: inform the tasks sequence as parameter and the method do all the work,
58
- # returning the makespan as result.
59
- def makespan(options = {}, block = @@bigger)
60
- if options[:tasks_sequence]
61
- schedule = @schedule.reorder_schedule(options[:tasks_sequence])
62
- makespan({schedule: schedule, task: schedule.row_size - 1, machine: schedule.column_size - 1, memory: {}}, block)
63
- else
64
- schedule = options[:schedule]
65
- task = options[:task]
66
- machine = options[:machine]
67
- memory = options[:memory]
68
- key = "#{task},#{machine}"
69
- time = schedule[task, machine]
70
- if task == 0 && machine == 0
71
- return time
72
- end
73
- if task > 0 # Before everithing, calculate the time spent in the tasks from N to 0
74
- time_task_before = memory["#{task - 1},#{machine}"]
75
- time_task_before = makespan({schedule: schedule, task: task - 1, machine: machine, memory: memory}, block) if memory["#{task - 1},#{machine}"].nil?
76
- end
77
- if machine > 0 # Calculate the time spent at the machines from N to 0
78
- time_machine_before = memory["#{task},#{machine - 1}"]
79
- time_machine_before = makespan({schedule: schedule, task: task, machine: machine - 1, memory: memory}, block) if memory["#{task},#{machine - 1}"].nil?
80
- end
81
- total_time = block.call(time_task_before, time_machine_before) + time # Calculate the total time
82
- memory[key] = total_time # Store the total time
83
- total_time
84
- end
81
+ if machine > 0 # Calculate the time spent of the same task at the machines from N to 0
82
+ time_machine_before = memory["#{task},#{machine - 1}"]
83
+ time_machine_before = makespan(schedule: schedule, task: task,
84
+ machine: machine - 1, memory: memory) if memory["#{task},#{machine - 1}"].nil?
85
85
  end
86
- alias :fitness :makespan # Needed because, in the algorithm classes, to be generic we call the 'fitness' function (all problem classes need to have a 'fitness' function)
86
+
87
+ total_time = bigger(time_task_before, time_machine_before) + time # Calculate the total time
88
+ memory[key] = total_time # Store the total time
89
+ total_time
90
+ end
87
91
  end
88
92
  end
@@ -0,0 +1,10 @@
1
+ require 'interface'
2
+
3
+ module ProblemInterface
4
+ include Interface
5
+
6
+ def initialize
7
+ must_implement load_instance: 1, fitness: 1
8
+ super
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module OptAlgFramework
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.4"
3
3
  end
@@ -6,10 +6,10 @@ require 'opt_alg_framework/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "opt_alg_framework"
8
8
  spec.version = OptAlgFramework::VERSION
9
- spec.authors = ["rodrigo-ehresmann"]
9
+ spec.authors = ["rwehresmann"]
10
10
  spec.email = ["igoehresmann@gmail.com"]
11
11
 
12
- spec.summary = %q{Gem with a optimization algorithm framework that implements problems, algorithms and operator classes.}
12
+ spec.summary = %q{Gem with an optimization algorithm framework who implements problems, algorithms and operators classes.}
13
13
  spec.homepage = "https://github.com/rodrigo-ehresmann/opt_alg_framework"
14
14
  spec.license = 'MIT'
15
15
 
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
23
23
  end
24
24
 
25
- spec.add_development_dependency "bundler", "~> 1.9"
25
+ spec.add_development_dependency "bundler", "~> 1.13"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
27
28
  end
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opt_alg_framework
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
- - rodrigo-ehresmann
7
+ - rwehresmann
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-16 00:00:00.000000000 Z
11
+ date: 2016-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.9'
19
+ version: '1.13'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.9'
26
+ version: '1.13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
41
55
  description:
42
56
  email:
43
57
  - igoehresmann@gmail.com
@@ -45,9 +59,9 @@ executables: []
45
59
  extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
- - .gitignore
49
- - .rspec
50
- - .travis.yml
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
51
65
  - Gemfile
52
66
  - LICENSE.txt
53
67
  - README.md
@@ -55,14 +69,21 @@ files:
55
69
  - bin/console
56
70
  - bin/setup
57
71
  - lib/opt_alg_framework.rb
72
+ - lib/opt_alg_framework/algorithm/README.md
73
+ - lib/opt_alg_framework/algorithm/algorithm_interface.rb
58
74
  - lib/opt_alg_framework/algorithm/local_search/hill_climbing.rb
59
75
  - lib/opt_alg_framework/algorithm/local_search/simulated_annealing.rb
60
76
  - lib/opt_alg_framework/algorithm/local_search/tabu_search.rb
77
+ - lib/opt_alg_framework/operator/README.md
78
+ - lib/opt_alg_framework/operator/crossover/crossover_interface.rb
61
79
  - lib/opt_alg_framework/operator/crossover/permutation/two_point_crossover.rb
80
+ - lib/opt_alg_framework/operator/selector/selector_interface.rb
62
81
  - lib/opt_alg_framework/operator/selector/tournament_selection.rb
63
82
  - lib/opt_alg_framework/operator/tweak/random_swap.rb
83
+ - lib/opt_alg_framework/operator/tweak/tweak_interface.rb
64
84
  - lib/opt_alg_framework/problem/README.md
65
85
  - lib/opt_alg_framework/problem/fsp.rb
86
+ - lib/opt_alg_framework/problem/problem_interface.rb
66
87
  - lib/opt_alg_framework/version.rb
67
88
  - opt_alg_framework.gemspec
68
89
  homepage: https://github.com/rodrigo-ehresmann/opt_alg_framework
@@ -76,19 +97,19 @@ require_paths:
76
97
  - lib
77
98
  required_ruby_version: !ruby/object:Gem::Requirement
78
99
  requirements:
79
- - - ! '>='
100
+ - - ">="
80
101
  - !ruby/object:Gem::Version
81
102
  version: '0'
82
103
  required_rubygems_version: !ruby/object:Gem::Requirement
83
104
  requirements:
84
- - - ! '>='
105
+ - - ">="
85
106
  - !ruby/object:Gem::Version
86
107
  version: '0'
87
108
  requirements: []
88
109
  rubyforge_project:
89
- rubygems_version: 2.6.3
110
+ rubygems_version: 2.5.1
90
111
  signing_key:
91
112
  specification_version: 4
92
- summary: Gem with a optimization algorithm framework that implements problems, algorithms
93
- and operator classes.
113
+ summary: Gem with an optimization algorithm framework who implements problems, algorithms
114
+ and operators classes.
94
115
  test_files: []