opt_alg_framework 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: []