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 +5 -13
- data/Gemfile +1 -0
- data/README.md +8 -26
- data/lib/opt_alg_framework.rb +13 -3
- data/lib/opt_alg_framework/algorithm/README.md +8 -0
- data/lib/opt_alg_framework/algorithm/algorithm_interface.rb +10 -0
- data/lib/opt_alg_framework/algorithm/local_search/hill_climbing.rb +10 -8
- data/lib/opt_alg_framework/algorithm/local_search/simulated_annealing.rb +11 -9
- data/lib/opt_alg_framework/algorithm/local_search/tabu_search.rb +16 -13
- data/lib/opt_alg_framework/operator/README.md +8 -0
- data/lib/opt_alg_framework/operator/crossover/crossover_interface.rb +10 -0
- data/lib/opt_alg_framework/operator/crossover/permutation/two_point_crossover.rb +3 -2
- data/lib/opt_alg_framework/operator/selector/selector_interface.rb +10 -0
- data/lib/opt_alg_framework/operator/selector/tournament_selection.rb +2 -2
- data/lib/opt_alg_framework/operator/tweak/random_swap.rb +2 -3
- data/lib/opt_alg_framework/operator/tweak/tweak_interface.rb +10 -0
- data/lib/opt_alg_framework/problem/README.md +12 -6
- data/lib/opt_alg_framework/problem/fsp.rb +58 -54
- data/lib/opt_alg_framework/problem/problem_interface.rb +10 -0
- data/lib/opt_alg_framework/version.rb +1 -1
- data/opt_alg_framework.gemspec +4 -3
- metadata +38 -17
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZmUwM2I2ZjM1YjBhNzY0YjBlOTNmYWVhM2JlY2Q5YTkyOTcwMGY1NA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e5238e0506bf85414aee3fb138a49038c83ebb2d
|
4
|
+
data.tar.gz: e0f07c319a8d4f8e8bac291f1a9f73862153d370
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
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
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# opt-alg-framework (Optimization Algorithm Framework)
|
2
2
|
|
3
|
-
|
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:
|
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
|
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'`)
|
data/lib/opt_alg_framework.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
-
|
2
|
-
|
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
|
-
|
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.
|
@@ -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
|
-
#
|
12
|
+
# solution_b = best solution
|
13
|
+
# solution_n = neighbor solution
|
11
14
|
def start
|
12
|
-
|
15
|
+
solution_b = encapsulate_solution(@problem.default_solution.shuffle)
|
13
16
|
while true do
|
14
|
-
|
15
|
-
if
|
16
|
-
|
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
|
-
|
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(
|
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
|
-
#
|
17
|
+
# solution_b = best solution
|
18
|
+
# solution_n = neighbor solution
|
19
|
+
# solution_c = current solution
|
18
20
|
def start
|
19
|
-
|
20
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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(
|
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
|
-
|
20
|
-
|
21
|
-
@tabu_list <<
|
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
|
-
|
25
|
+
solution_bn = solution_n1 = encapsulate_solution(@tweak_operator.tweak(solution_c[:solution]))
|
25
26
|
(@tweak_number - 1).times do
|
26
|
-
|
27
|
-
|
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?(
|
30
|
-
|
31
|
-
@tabu_list <<
|
32
|
+
if !@tabu_list.include?(solution_bn[:solution])
|
33
|
+
solution_c = solution_bn.dup
|
34
|
+
@tabu_list << solution_n1
|
32
35
|
end
|
33
|
-
|
36
|
+
solution_s = solution_c.dup if solution_c[:fitness] < solution_s[:fitness]
|
34
37
|
end
|
35
|
-
|
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(
|
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
|
+
|
@@ -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
|
@@ -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
|
-
|
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
|
@@ -1,7 +1,15 @@
|
|
1
|
-
#
|
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.
|
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
|
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
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
34
|
+
# Initialize the FSP problem with a empty schedule
|
35
|
+
def initialize
|
36
|
+
@production = Production.new
|
37
|
+
end
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
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
|
data/opt_alg_framework.gemspec
CHANGED
@@ -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 = ["
|
9
|
+
spec.authors = ["rwehresmann"]
|
10
10
|
spec.email = ["igoehresmann@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{Gem with
|
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.
|
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.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- rwehresmann
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
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.
|
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.
|
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.
|
110
|
+
rubygems_version: 2.5.1
|
90
111
|
signing_key:
|
91
112
|
specification_version: 4
|
92
|
-
summary: Gem with
|
93
|
-
and
|
113
|
+
summary: Gem with an optimization algorithm framework who implements problems, algorithms
|
114
|
+
and operators classes.
|
94
115
|
test_files: []
|