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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5435b7e34667fdfd63782d895080435f7f2dffb685b2a918bba83bf6781f432
4
- data.tar.gz: 82bfb71e31afed6d53e0649b35c373fc5ea27bcc19e6b72ae8522983df1d4734
3
+ metadata.gz: f42d7b6ef54f628c761f716ab2dffe55f227b1c3bac9c4e962c971bddc835961
4
+ data.tar.gz: 6a4a6673ce1e9893d6da3d8e4ff37781f98dd6108ab33819e6d1a1bb7d9cbf6b
5
5
  SHA512:
6
- metadata.gz: 54dd58f3c4c2007aa0c6cd0ca264dc9a53ddb9680a354ea2808ff3c7a8ebcae5fc032aefb70f9cdbb6fe023cd23d0dff014254c99a577e2119172597cefd5202
7
- data.tar.gz: 21c78d1a11bc7ddf2e9b02e916f3bb94986944ad37ceb08cddf5a70178b82477be414e8478d1d51f26220a147f8442f5594667152bce496b7b98897204ec221f
6
+ metadata.gz: 03b9fbc0ef5c027ba6f9d33a9eee1ae120c134f4d436916f076b1829ca170343b778da279096e01eda72d377c7370baf170e88315951c70e23fe39cd86315579
7
+ data.tar.gz: 3402a3824fdc915abccda29fc57ce0ab320547b44fd74a7df5b70c3171e1a08fe88b55d81582419813fb13b71e182f0dae51d4967e309a3017517abe210ffa8b
@@ -18,9 +18,9 @@ jobs:
18
18
  runs-on: ubuntu-latest
19
19
  strategy:
20
20
  matrix:
21
- ruby-version: ['3.0']
21
+ ruby-version: ['4.0']
22
22
  steps:
23
- - uses: actions/checkout@v2
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.0', '3.1', '3.2']
35
+ ruby-version: ['3.4', '4.0']
36
36
 
37
37
  steps:
38
- - uses: actions/checkout@v2
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
- require:
3
+ plugins:
4
4
  - rubocop-performance
5
5
  - rubocop-minitest
6
6
  - rubocop-rake
7
7
 
8
8
  AllCops:
9
- TargetRubyVersion: 3.0
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
- ## [Unreleased]
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
- gem "debug", ">= 1.0.0", require: false
9
- gem "minitest", "~> 5.0"
10
- gem "rake", "~> 13.0.0", ">= 13.0.6"
11
- gem "rubocop", "~> 1.48.0"
12
- gem "rubocop-minitest", "~> 0.29.0"
13
- gem "rubocop-performance", "~> 1.16.0"
14
- gem "rubocop-rake", "~> 0.6.0"
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.0)
4
+ annealing (0.4.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ast (2.4.2)
10
- debug (1.4.0)
11
- irb (>= 1.3.6)
12
- reline (>= 0.2.7)
13
- io-console (0.6.0)
14
- irb (1.6.3)
15
- reline (>= 0.3.0)
16
- json (2.6.3)
17
- minitest (5.18.0)
18
- parallel (1.22.1)
19
- parser (3.2.1.1)
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.0.6)
23
- regexp_parser (2.7.0)
24
- reline (0.3.2)
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
- rexml (3.2.5)
27
- rubocop (1.48.0)
49
+ rubocop (1.88.2)
28
50
  json (~> 2.3)
29
- parallel (~> 1.10)
30
- parser (>= 3.2.0.0)
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 (>= 1.8, < 3.0)
33
- rexml (>= 3.2.5, < 4.0)
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, < 3.0)
37
- rubocop-ast (1.27.0)
38
- parser (>= 3.2.1.0)
39
- rubocop-minitest (0.29.0)
40
- rubocop (>= 1.39, < 2.0)
41
- rubocop-performance (1.16.0)
42
- rubocop (>= 1.7.0, < 2.0)
43
- rubocop-ast (>= 0.4.0)
44
- rubocop-rake (0.6.0)
45
- rubocop (~> 1.0)
46
- ruby-prof (1.6.1)
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
- unicode-display_width (2.4.2)
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.0)
57
- rake (~> 13.0.0, >= 13.0.6)
58
- rubocop (~> 1.48.0)
59
- rubocop-minitest (~> 0.29.0)
60
- rubocop-performance (~> 1.16.0)
61
- rubocop-rake (~> 0.6.0)
62
- ruby-prof (~> 1.6, >= 1.6.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.4.4
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.0.0")
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: #{energy_calculator.call(locations)}"
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
@@ -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
- return true if cooled_metal.energy < energy
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Annealing
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ ruby = "4.0.5"
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.0
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: 2023-03-09 00:00:00.000000000 Z
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.0.0
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: 3.4.6
88
- signing_key:
67
+ rubygems_version: 4.0.10
89
68
  specification_version: 4
90
69
  summary: Simulated Annealing
91
70
  test_files: []