annealing 0.4.0 → 0.4.1
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 +4 -4
- data/.github/workflows/ruby.yml +4 -4
- data/.rubocop.yml +2 -2
- data/AGENTS.md +53 -0
- data/CHANGELOG.md +13 -1
- data/Gemfile +10 -7
- data/Gemfile.lock +74 -42
- data/README.md +4 -0
- data/annealing.gemspec +1 -2
- data/bin/run +7 -1
- data/lib/annealing/configuration.rb +6 -0
- data/lib/annealing/metal.rb +7 -1
- data/lib/annealing/simulator.rb +16 -1
- data/lib/annealing/version.rb +1 -1
- data/mise.toml +2 -0
- metadata +7 -28
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f42d7b6ef54f628c761f716ab2dffe55f227b1c3bac9c4e962c971bddc835961
|
|
4
|
+
data.tar.gz: 6a4a6673ce1e9893d6da3d8e4ff37781f98dd6108ab33819e6d1a1bb7d9cbf6b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 03b9fbc0ef5c027ba6f9d33a9eee1ae120c134f4d436916f076b1829ca170343b778da279096e01eda72d377c7370baf170e88315951c70e23fe39cd86315579
|
|
7
|
+
data.tar.gz: 3402a3824fdc915abccda29fc57ce0ab320547b44fd74a7df5b70c3171e1a08fe88b55d81582419813fb13b71e182f0dae51d4967e309a3017517abe210ffa8b
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -18,9 +18,9 @@ jobs:
|
|
|
18
18
|
runs-on: ubuntu-latest
|
|
19
19
|
strategy:
|
|
20
20
|
matrix:
|
|
21
|
-
ruby-version: ['
|
|
21
|
+
ruby-version: ['4.0']
|
|
22
22
|
steps:
|
|
23
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
24
|
- name: Set up Ruby
|
|
25
25
|
uses: ruby/setup-ruby@v1
|
|
26
26
|
with:
|
|
@@ -32,10 +32,10 @@ jobs:
|
|
|
32
32
|
runs-on: ubuntu-latest
|
|
33
33
|
strategy:
|
|
34
34
|
matrix:
|
|
35
|
-
ruby-version: ['3.
|
|
35
|
+
ruby-version: ['3.4', '4.0']
|
|
36
36
|
|
|
37
37
|
steps:
|
|
38
|
-
- uses: actions/checkout@
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
39
|
- name: Set up Ruby
|
|
40
40
|
uses: ruby/setup-ruby@v1
|
|
41
41
|
with:
|
data/.rubocop.yml
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
inherit_from: .rubocop_todo.yml
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
plugins:
|
|
4
4
|
- rubocop-performance
|
|
5
5
|
- rubocop-minitest
|
|
6
6
|
- rubocop-rake
|
|
7
7
|
|
|
8
8
|
AllCops:
|
|
9
|
-
TargetRubyVersion: 3.
|
|
9
|
+
TargetRubyVersion: 3.4
|
|
10
10
|
NewCops: enable
|
|
11
11
|
DefaultFormatter: progress
|
|
12
12
|
DisplayCopNames: true
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Reference for AI agents (and humans) working in this repo. A Ruby gem implementing
|
|
4
|
+
simulated annealing. See `README.md` for the public API and configuration precedence
|
|
5
|
+
(global < instance < just-in-time).
|
|
6
|
+
|
|
7
|
+
## Commands
|
|
8
|
+
|
|
9
|
+
- Setup: `bin/setup` (runs `bundle install`).
|
|
10
|
+
- Full default check (order matters): `bundle exec rake` — runs `test`, then `end_to_end_test`, then `rubocop`.
|
|
11
|
+
- Run tests only: `bundle exec rake test`.
|
|
12
|
+
- Run a single test file: `bundle exec ruby -Ilib:test test/path/to_test.rb` (or `rake test TEST=...`).
|
|
13
|
+
- Lint only: `bundle exec rubocop` (or `bundle exec rake rubocop`).
|
|
14
|
+
- Interactive console: `bin/console`. Runnable demo: `bin/run`.
|
|
15
|
+
|
|
16
|
+
## Gotchas
|
|
17
|
+
|
|
18
|
+
- `rake`'s default task includes `bin/run` via the `end_to_end_test` task. It runs a
|
|
19
|
+
real (slow, non-deterministic due to `rand`) annealing simulation; skip it with
|
|
20
|
+
`rake test rubocop` when you only want fast feedback.
|
|
21
|
+
- Tests use Minitest. `test/test_helper.rb` requires `ruby-prof` and `debug` — both are
|
|
22
|
+
dev deps in the `Gemfile`; ensure they're installed (`bundle install`) before running tests.
|
|
23
|
+
- `Annealing.configuration` is a global singleton. Tests reset it in
|
|
24
|
+
`Minitest::Test#teardown` by setting `Annealing.configuration = nil`. When writing
|
|
25
|
+
tests that touch global config, favor scoped instance/JIT config or rely on teardown.
|
|
26
|
+
- `Metal#cool!` is non-idempotent and depends on `rand`; never assume deterministic
|
|
27
|
+
output from a single run.
|
|
28
|
+
- `Simulator#run` raises `ConfigurationError` ( subclass of `Annealing::Error`) on
|
|
29
|
+
invalid config; validation happens lazily at run time, not at `Simulator.new`.
|
|
30
|
+
|
|
31
|
+
## Style / rubocop
|
|
32
|
+
|
|
33
|
+
- Inherited from `.rubocop.yml` + `.rubocop_todo.yml`. `TargetRubyVersion: 3.4`,
|
|
34
|
+
`Layout/LineLength: Max 120`, double-quoted strings, NewCops enabled with rubocop-
|
|
35
|
+
performance/-minitest/-rake plugins loaded.
|
|
36
|
+
- CI lint job runs `bundle exec rubocop --parallel` on Ruby 4.0; test matrix is 3.4/4.0
|
|
37
|
+
(see `.github/workflows/ruby.yml`). Keep code compatible with 3.4.
|
|
38
|
+
|
|
39
|
+
## Architecture
|
|
40
|
+
|
|
41
|
+
- Entry: `Annealing.simulate` (lib/annealing.rb) — thin wrapper over
|
|
42
|
+
`Annealing::Simulator.new(...).run(...).state`.
|
|
43
|
+
- `Simulator` (lib/annealing/simulator.rb) drives the loop, merging configs at runtime
|
|
44
|
+
and calling `Metal#cool!` each step until `termination_condition` returns truthy.
|
|
45
|
+
- `Metal` (lib/annealing/metal.rb) holds current `state`, `temperature`, and lazily
|
|
46
|
+
computed `energy`; `cool!` applies the probabilistic accept/reject step.
|
|
47
|
+
- `Configuration` (lib/annealing/configuration.rb) plus concrete
|
|
48
|
+
`Configuration::Coolers` and `Configuration::Terminators` provide built-in callables.
|
|
49
|
+
|
|
50
|
+
## Release
|
|
51
|
+
|
|
52
|
+
Bump `lib/annealing/version.rb`, then `bundle exec rake release` (tags, pushes, releases
|
|
53
|
+
to rubygems.org; `rubygems_mfa_required` is set in the gemspec).
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
## [
|
|
1
|
+
## [0.4.1] - 2026-07-16
|
|
2
2
|
|
|
3
|
+
- Add return_best config option. When true, returns the best (lowest energy) state. When false, returns the final state (preserves old behavior).
|
|
4
|
+
- Bump minimum supported Ruby version to 3.4.0 and add Ruby 4.0 support.
|
|
5
|
+
- Refresh development dependencies (rubocop, ruby-prof, and plugins) to versions
|
|
6
|
+
compatible with Ruby 4.0.
|
|
7
|
+
- Bump RuboCop `TargetRubyVersion` to 3.4 and CI test matrix to 3.4 / 4.0.
|
|
8
|
+
|
|
9
|
+
## [0.4.0] - 2023-03-09
|
|
10
|
+
|
|
11
|
+
- Rename method and add comments to clarify use by @chrisbloom7 in #20
|
|
12
|
+
- Config Cleanup: remove logger config by @chrisbloom7 in #21
|
|
13
|
+
- Simply configuration and overrides by @chrisbloom7 in #22
|
|
14
|
+
- Idea: Add library of built-in functions by @chrisbloom7 in #23
|
|
3
15
|
|
|
4
16
|
## [0.3.0] - 2022-02-21
|
|
5
17
|
|
data/Gemfile
CHANGED
|
@@ -5,10 +5,13 @@ source "https://rubygems.org"
|
|
|
5
5
|
# Specify your gem's dependencies in annealing.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
gem "
|
|
10
|
-
gem "
|
|
11
|
-
gem "
|
|
12
|
-
gem "rubocop
|
|
13
|
-
gem "rubocop-
|
|
14
|
-
gem "rubocop-
|
|
8
|
+
group :development do
|
|
9
|
+
gem "debug", ">= 1.0.0", require: false
|
|
10
|
+
gem "minitest", "~> 5.22"
|
|
11
|
+
gem "rake", "~> 13.0", ">= 13.0.6"
|
|
12
|
+
gem "rubocop", "~> 1.78"
|
|
13
|
+
gem "rubocop-minitest", "~> 0.37"
|
|
14
|
+
gem "rubocop-performance", "~> 1.25"
|
|
15
|
+
gem "rubocop-rake", "~> 0.7"
|
|
16
|
+
gem "ruby-prof", "~> 1.7", ">= 1.7.0"
|
|
17
|
+
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,51 +1,83 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
annealing (0.4.
|
|
4
|
+
annealing (0.4.1)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
-
ast (2.4.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
ast (2.4.3)
|
|
10
|
+
base64 (0.3.0)
|
|
11
|
+
debug (1.11.1)
|
|
12
|
+
irb (~> 1.10)
|
|
13
|
+
reline (>= 0.3.8)
|
|
14
|
+
erb (6.0.4)
|
|
15
|
+
io-console (0.8.2)
|
|
16
|
+
irb (1.18.0)
|
|
17
|
+
pp (>= 0.6.0)
|
|
18
|
+
prism (>= 1.3.0)
|
|
19
|
+
rdoc (>= 4.0.0)
|
|
20
|
+
reline (>= 0.4.2)
|
|
21
|
+
json (2.21.1)
|
|
22
|
+
language_server-protocol (3.17.0.6)
|
|
23
|
+
lint_roller (1.1.0)
|
|
24
|
+
logger (1.7.0)
|
|
25
|
+
minitest (5.27.0)
|
|
26
|
+
parallel (2.1.0)
|
|
27
|
+
parser (3.3.12.0)
|
|
20
28
|
ast (~> 2.4.1)
|
|
29
|
+
racc
|
|
30
|
+
pp (0.6.4)
|
|
31
|
+
prettyprint
|
|
32
|
+
prettyprint (0.2.0)
|
|
33
|
+
prism (1.9.0)
|
|
34
|
+
racc (1.8.1)
|
|
21
35
|
rainbow (3.1.1)
|
|
22
|
-
rake (13.
|
|
23
|
-
|
|
24
|
-
|
|
36
|
+
rake (13.4.2)
|
|
37
|
+
rbs (4.0.3)
|
|
38
|
+
logger
|
|
39
|
+
prism (>= 1.6.0)
|
|
40
|
+
tsort
|
|
41
|
+
rdoc (8.0.0)
|
|
42
|
+
erb
|
|
43
|
+
prism (>= 1.6.0)
|
|
44
|
+
rbs (>= 4.0.0)
|
|
45
|
+
tsort
|
|
46
|
+
regexp_parser (2.12.0)
|
|
47
|
+
reline (0.6.3)
|
|
25
48
|
io-console (~> 0.5)
|
|
26
|
-
|
|
27
|
-
rubocop (1.48.0)
|
|
49
|
+
rubocop (1.88.2)
|
|
28
50
|
json (~> 2.3)
|
|
29
|
-
|
|
30
|
-
|
|
51
|
+
language_server-protocol (~> 3.17.0.2)
|
|
52
|
+
lint_roller (~> 1.1.0)
|
|
53
|
+
parallel (>= 1.10)
|
|
54
|
+
parser (>= 3.3.0.2)
|
|
31
55
|
rainbow (>= 2.2.2, < 4.0)
|
|
32
|
-
regexp_parser (>=
|
|
33
|
-
|
|
34
|
-
rubocop-ast (>= 1.26.0, < 2.0)
|
|
56
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
57
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
35
58
|
ruby-progressbar (~> 1.7)
|
|
36
|
-
unicode-display_width (>= 2.4.0, <
|
|
37
|
-
rubocop-ast (1.
|
|
38
|
-
parser (>= 3.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
rubocop (>= 1.
|
|
43
|
-
rubocop-ast (>=
|
|
44
|
-
rubocop-
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
60
|
+
rubocop-ast (1.50.0)
|
|
61
|
+
parser (>= 3.3.7.2)
|
|
62
|
+
prism (~> 1.7)
|
|
63
|
+
rubocop-minitest (0.39.1)
|
|
64
|
+
lint_roller (~> 1.1)
|
|
65
|
+
rubocop (>= 1.75.0, < 2.0)
|
|
66
|
+
rubocop-ast (>= 1.38.0, < 2.0)
|
|
67
|
+
rubocop-performance (1.26.1)
|
|
68
|
+
lint_roller (~> 1.1)
|
|
69
|
+
rubocop (>= 1.75.0, < 2.0)
|
|
70
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
71
|
+
rubocop-rake (0.7.1)
|
|
72
|
+
lint_roller (~> 1.1)
|
|
73
|
+
rubocop (>= 1.72.1)
|
|
74
|
+
ruby-prof (1.7.2)
|
|
75
|
+
base64
|
|
47
76
|
ruby-progressbar (1.13.0)
|
|
48
|
-
|
|
77
|
+
tsort (0.2.0)
|
|
78
|
+
unicode-display_width (3.2.0)
|
|
79
|
+
unicode-emoji (~> 4.1)
|
|
80
|
+
unicode-emoji (4.2.0)
|
|
49
81
|
|
|
50
82
|
PLATFORMS
|
|
51
83
|
ruby
|
|
@@ -53,13 +85,13 @@ PLATFORMS
|
|
|
53
85
|
DEPENDENCIES
|
|
54
86
|
annealing!
|
|
55
87
|
debug (>= 1.0.0)
|
|
56
|
-
minitest (~> 5.
|
|
57
|
-
rake (~> 13.0
|
|
58
|
-
rubocop (~> 1.
|
|
59
|
-
rubocop-minitest (~> 0.
|
|
60
|
-
rubocop-performance (~> 1.
|
|
61
|
-
rubocop-rake (~> 0.
|
|
62
|
-
ruby-prof (~> 1.
|
|
88
|
+
minitest (~> 5.22)
|
|
89
|
+
rake (~> 13.0, >= 13.0.6)
|
|
90
|
+
rubocop (~> 1.78)
|
|
91
|
+
rubocop-minitest (~> 0.37)
|
|
92
|
+
rubocop-performance (~> 1.25)
|
|
93
|
+
rubocop-rake (~> 0.7)
|
|
94
|
+
ruby-prof (~> 1.7, >= 1.7.0)
|
|
63
95
|
|
|
64
96
|
BUNDLED WITH
|
|
65
|
-
2.
|
|
97
|
+
2.7.2
|
data/README.md
CHANGED
|
@@ -213,6 +213,10 @@ Annealing.configuration.termination_condition = lambda do |_state, energy, tempe
|
|
|
213
213
|
end
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
+
### 'return_best'
|
|
217
|
+
|
|
218
|
+
If true (the default), will return the best (lowest energy) state seen during the simulation. If false, Simulator#run will return the final state reached when the simulation completes.
|
|
219
|
+
|
|
216
220
|
## Configuration precedence
|
|
217
221
|
|
|
218
222
|
Configuration options can be set globally using `Annealing.configuration` or `Annealing.configure`, on `Annealing::Simulator.new` to be used on all subsequent runs of that instance, and just-in-time on `Annealing.simulate` and `Annealing::Simulator#run`. They are applied in reverse order of precedence.
|
data/annealing.gemspec
CHANGED
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
|
12
12
|
spec.summary = "Simulated Annealing"
|
|
13
13
|
spec.description = "Simulated Annealing algoritm implementation."
|
|
14
14
|
spec.homepage = "https://github.com/3zcurdia/annealing"
|
|
15
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 3.
|
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.4.0")
|
|
16
16
|
|
|
17
17
|
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
|
18
18
|
|
|
@@ -29,6 +29,5 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
30
30
|
spec.require_paths = ["lib"]
|
|
31
31
|
|
|
32
|
-
spec.add_development_dependency "ruby-prof", "~> 1.6", ">= 1.6.1"
|
|
33
32
|
spec.metadata["rubygems_mfa_required"] = "true"
|
|
34
33
|
end
|
data/bin/run
CHANGED
|
@@ -44,14 +44,20 @@ solution = simulator.run(locations,
|
|
|
44
44
|
energy_calculator: energy_calculator,
|
|
45
45
|
state_change: state_change)
|
|
46
46
|
|
|
47
|
+
initial_energy = energy_calculator.call(locations)
|
|
47
48
|
puts "\nInitial itinerary:"
|
|
48
49
|
locations.each_cons(2).with_index do |(location1, location2), index|
|
|
49
50
|
puts "Stop ##{index + 1}: #{location1.name} -> #{location2.name} (#{location1.distance(location2)})"
|
|
50
51
|
end
|
|
51
|
-
puts "-------\nEnergy: #{
|
|
52
|
+
puts "-------\nEnergy: #{initial_energy}"
|
|
52
53
|
|
|
53
54
|
puts "\nAnnealed itinerary:"
|
|
54
55
|
solution.state.each_cons(2).with_index do |(location1, location2), index|
|
|
55
56
|
puts "Stop ##{index + 1}: #{location1.name} -> #{location2.name} (#{location1.distance(location2)})"
|
|
56
57
|
end
|
|
57
58
|
puts "-------\nEnergy: #{solution.energy}"
|
|
59
|
+
|
|
60
|
+
if solution.energy > initial_energy
|
|
61
|
+
raise "Annealing failed: solution energy #{solution.energy}\
|
|
62
|
+
ought to be less than or equal to than initial energy #{initial_energy}"
|
|
63
|
+
end
|
|
@@ -5,12 +5,14 @@ module Annealing
|
|
|
5
5
|
class Configuration
|
|
6
6
|
DEFAULT_COOLING_RATE = 0.0003
|
|
7
7
|
DEFAULT_INITIAL_TEMPERATURE = 10_000.0
|
|
8
|
+
DEFAULT_RETURN_BEST = false
|
|
8
9
|
|
|
9
10
|
class ConfigurationError < Annealing::Error; end
|
|
10
11
|
|
|
11
12
|
attr_accessor :cool_down,
|
|
12
13
|
:cooling_rate,
|
|
13
14
|
:energy_calculator,
|
|
15
|
+
:return_best,
|
|
14
16
|
:state_change,
|
|
15
17
|
:temperature,
|
|
16
18
|
:termination_condition
|
|
@@ -20,6 +22,7 @@ module Annealing
|
|
|
20
22
|
@cooling_rate = config_hash.fetch(:cooling_rate,
|
|
21
23
|
DEFAULT_COOLING_RATE).to_f
|
|
22
24
|
@energy_calculator = config_hash.fetch(:energy_calculator, nil)
|
|
25
|
+
@return_best = config_hash.fetch(:return_best, DEFAULT_RETURN_BEST)
|
|
23
26
|
@state_change = config_hash.fetch(:state_change, nil)
|
|
24
27
|
@temperature = config_hash.fetch(:temperature,
|
|
25
28
|
DEFAULT_INITIAL_TEMPERATURE).to_f
|
|
@@ -39,6 +42,8 @@ module Annealing
|
|
|
39
42
|
"Cooling rate cannot be negative"
|
|
40
43
|
elsif !callable?(energy_calculator)
|
|
41
44
|
"Missing energy calculator function"
|
|
45
|
+
elsif ![true, false].include?(return_best)
|
|
46
|
+
"'Return best' specification must be either true or false"
|
|
42
47
|
elsif !callable?(state_change)
|
|
43
48
|
"Missing state change function"
|
|
44
49
|
elsif temperature.negative?
|
|
@@ -56,6 +61,7 @@ module Annealing
|
|
|
56
61
|
cool_down: cool_down,
|
|
57
62
|
cooling_rate: cooling_rate,
|
|
58
63
|
energy_calculator: energy_calculator,
|
|
64
|
+
return_best: return_best,
|
|
59
65
|
state_change: state_change,
|
|
60
66
|
temperature: temperature,
|
|
61
67
|
termination_condition: termination_condition
|
data/lib/annealing/metal.rb
CHANGED
|
@@ -27,14 +27,20 @@ module Annealing
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def lower_energy?(cooled_metal)
|
|
31
|
+
cooled_metal.energy < energy
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
private
|
|
31
35
|
|
|
32
36
|
# True if cooled_metal.energy is lower than current energy, otherwise let
|
|
33
37
|
# probability determine if we should accept a higher value over a lower
|
|
34
38
|
# value
|
|
35
39
|
def prefer?(cooled_metal)
|
|
36
|
-
|
|
40
|
+
lower_energy?(cooled_metal) || prefer_despite_higher_energy?(cooled_metal)
|
|
41
|
+
end
|
|
37
42
|
|
|
43
|
+
def prefer_despite_higher_energy?(cooled_metal)
|
|
38
44
|
energy_delta = energy - cooled_metal.energy
|
|
39
45
|
(Math::E**(energy_delta / cooled_metal.temperature)) > rand
|
|
40
46
|
end
|
data/lib/annealing/simulator.rb
CHANGED
|
@@ -9,18 +9,24 @@ module Annealing
|
|
|
9
9
|
@configuration = Annealing.configuration.merge(config_hash)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
# rubocop:disable Metrics/MethodLength
|
|
12
13
|
def run(initial_state, config_hash = {})
|
|
13
14
|
with_runtime_config(config_hash) do |runtime_config|
|
|
14
15
|
initial_temperature = runtime_config.temperature
|
|
15
16
|
current = Metal.new(initial_state, initial_temperature, runtime_config)
|
|
17
|
+
best = current
|
|
16
18
|
steps = 0
|
|
17
19
|
until termination_condition_met?(current, runtime_config)
|
|
18
20
|
steps += 1
|
|
19
21
|
current = reduce_temperature(current, steps, runtime_config)
|
|
22
|
+
# If the current state has lower energy than the previous best (lowest energy) state
|
|
23
|
+
# we've seen so far, the current state is the new best state.
|
|
24
|
+
best = current if best.lower_energy?(current)
|
|
20
25
|
end
|
|
21
|
-
current
|
|
26
|
+
final_or_best(current, best, runtime_config)
|
|
22
27
|
end
|
|
23
28
|
end
|
|
29
|
+
# rubocop:enable Metrics/MethodLength
|
|
24
30
|
|
|
25
31
|
private
|
|
26
32
|
|
|
@@ -48,5 +54,14 @@ module Annealing
|
|
|
48
54
|
metal.energy,
|
|
49
55
|
metal.temperature)
|
|
50
56
|
end
|
|
57
|
+
|
|
58
|
+
def final_or_best(final, best, config)
|
|
59
|
+
if config.return_best
|
|
60
|
+
# preserve the temperature
|
|
61
|
+
Metal.new(best.state, final.temperature, config)
|
|
62
|
+
else
|
|
63
|
+
final
|
|
64
|
+
end
|
|
65
|
+
end
|
|
51
66
|
end
|
|
52
67
|
end
|
data/lib/annealing/version.rb
CHANGED
data/mise.toml
ADDED
metadata
CHANGED
|
@@ -1,36 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: annealing
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Luis Ezcurdia
|
|
8
8
|
- Chris Bloom
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: exe
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
13
|
-
dependencies:
|
|
14
|
-
- !ruby/object:Gem::Dependency
|
|
15
|
-
name: ruby-prof
|
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
requirements:
|
|
18
|
-
- - "~>"
|
|
19
|
-
- !ruby/object:Gem::Version
|
|
20
|
-
version: '1.6'
|
|
21
|
-
- - ">="
|
|
22
|
-
- !ruby/object:Gem::Version
|
|
23
|
-
version: 1.6.1
|
|
24
|
-
type: :development
|
|
25
|
-
prerelease: false
|
|
26
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
27
|
-
requirements:
|
|
28
|
-
- - "~>"
|
|
29
|
-
- !ruby/object:Gem::Version
|
|
30
|
-
version: '1.6'
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.6.1
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
34
13
|
description: Simulated Annealing algoritm implementation.
|
|
35
14
|
email:
|
|
36
15
|
- ing.ezcurdia@gmail.com
|
|
@@ -43,6 +22,7 @@ files:
|
|
|
43
22
|
- ".gitignore"
|
|
44
23
|
- ".rubocop.yml"
|
|
45
24
|
- ".rubocop_todo.yml"
|
|
25
|
+
- AGENTS.md
|
|
46
26
|
- CHANGELOG.md
|
|
47
27
|
- CODE_OF_CONDUCT.md
|
|
48
28
|
- Gemfile
|
|
@@ -61,6 +41,7 @@ files:
|
|
|
61
41
|
- lib/annealing/metal.rb
|
|
62
42
|
- lib/annealing/simulator.rb
|
|
63
43
|
- lib/annealing/version.rb
|
|
44
|
+
- mise.toml
|
|
64
45
|
homepage: https://github.com/3zcurdia/annealing
|
|
65
46
|
licenses:
|
|
66
47
|
- MIT
|
|
@@ -69,7 +50,6 @@ metadata:
|
|
|
69
50
|
source_code_uri: https://github.com/3zcurdia/annealing
|
|
70
51
|
changelog_uri: https://github.com/3zcurdia/annealing/blob/main/CHANGELOG.md
|
|
71
52
|
rubygems_mfa_required: 'true'
|
|
72
|
-
post_install_message:
|
|
73
53
|
rdoc_options: []
|
|
74
54
|
require_paths:
|
|
75
55
|
- lib
|
|
@@ -77,15 +57,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
77
57
|
requirements:
|
|
78
58
|
- - ">="
|
|
79
59
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: 3.
|
|
60
|
+
version: 3.4.0
|
|
81
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
62
|
requirements:
|
|
83
63
|
- - ">="
|
|
84
64
|
- !ruby/object:Gem::Version
|
|
85
65
|
version: '0'
|
|
86
66
|
requirements: []
|
|
87
|
-
rubygems_version:
|
|
88
|
-
signing_key:
|
|
67
|
+
rubygems_version: 4.0.10
|
|
89
68
|
specification_version: 4
|
|
90
69
|
summary: Simulated Annealing
|
|
91
70
|
test_files: []
|