GithubHelp home page GithubHelp logo

annealing's Introduction

Top Langs

  • ๐Ÿ’ก I love to build software.
  • ๐Ÿ”ญ I'm always looking how to improve things.
  • ๐ŸŒฑ I always try to find the simpliest solution.
  • ๐Ÿ’ฌ Ask me anything about software development.
  • ๐Ÿง‘โ€๐Ÿซ I'm a iOSLab mentor
  • ๐Ÿข My first programming languaje was logo
  • ๐Ÿ‘พ I am a terrible gamer, but I love it when I have some time to play
  • โšก I like to make sourdoug bread ๐Ÿฅ– and cheese ๐Ÿง€

annealing's People

Contributors

3zcurdia avatar chrisbloom7 avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

chrisbloom7

annealing's Issues

Drop support from ruby 2.5 to 2.7

Why

Maintaining an open source library could be hard, specially when time goes by and newer ruby versions need to be supported and older versions start to get forgotten by the core team. Therefore in order to keep this project sustainable in the long term I plan to drop support for older ruby versions in the following releases:

  • 0.3.0 Will drop support for ruby 2.5
  • 0.4.0 Will drop support for ruby 2.7

Consider that ruby 2.5 was released in 2017 and their last update was on April 2021
And ruby 2.6 was released 2018 and their last update was on July 2021. Both versions are still maintained by the core team and eventually will stop receiving updates.

Normalize configuration interface

Now that #9 has merged, there are 7 global configuration options. Two of them, temperature and cooling_rate, can also be set via Simulator.new to apply to all subsequent #run calls. Four of them, energy_calculator, state_change, termination-condition, and cooling_rate, can be specified per Simulator#run call. None of the configuration options can be overridden when using the Annealing.simulate shorthand method.

To be honest, I'm not sure how often someone in the real world would need to override the global custom functions per run, or more specifically how many times someone would be making multiple runs of the simulator with different lambda functions. A more realistic scenario might be running multiple times with the same functions and different starting temperatures or cooling rate to measure performance, or alternately a preference for global versus just-in-time configuration. In any case, the current setup makes it difficult to explain which options can be set where. I'd like to propose that we simplify the interface for configuration at the expense of a little more complicated code.

The idea would be that you could pass any configuration option to Annealing.simulate, Simulator.new, or Simulator#run, the three primary interfaces of the gem, and they would be applied in reverse precedence, i.e. any config options passed in to Simulator#run would override those passed to Simulator.new, which would override those specified in (or the default of) Annealing.configuration. (Any passed in to Annealing.simulate would be forwarded to Simulator.new). Those APIs would then become:

Annealing.simulate(initial_state, config_hash)
Annealing::Simulator.new(config_hash)
Annealing::Simulator#run(initial_state, config_hash)

The API of Annealing::Metal would also change slightly to Annealing::Metal.new(current_state, current_temperature, config_hash), but in this case the config hash would only be concerned with the energy_calculator and state_change config options, and since this class isn't a primary interface it isn't really anything we need to be specific about in the documentation.

Normalize custom function interfaces

The 4 custom functions - energy_calculator, state_change, cool_down, and termination_condition - all have different method signatures that need to be adhered to when overriding them. I think we can normalize them pretty easily to make documenting their use a little easier.

  • Both energy_calculator and state_change currently expect one argument: the state of the current Metal instance being evaluated.
  • The newest function, cool_down, expects 4 arguments: the energy and temperature of the current Metal instance, the current cooling_rate config that has precedence (i.e. local versus global), and finally the steps the annealer has taken which make it possible to do exponential temperature reductions, etc. *
  • The termination_condition expects 3 arguments: the state, energy, and temperature of the current Metal instance *

With the exception of the cool_down function, all of the arguments are things the current Metal instance can tell us. So, I propose we:

  • Create a static, idempotent object that represents the current state of the annealing process during any given iteration. (Suggestions: Annealing::Step) Specifically, it would know the current state, energy, and temperature of the current metal instance, as well as the current cooling_rate and iteration (aka step) of the annealing simulator. The benefit of using a different class than Annealing::Metal is that some metal methods are not idempotent and shouldn't be called from outside the simulator itself, plus it lets us add info about the current simulation step without requiring Metal to start tracking things external to its own purpose.
  • Update the 4 custom function signatures to each accept a single argument representing this new object. Everything there is to know about the current state of the simulation becomes available to those custom functions and we don't have to try to guess at what might be helpful to someone in the future. And if we do need to add something, we can add it to to this new class and then it's available to all of the custom functions to use.

* For the two newest functions I could only make a reasonable guess as to what data might be helpful for all future use cases, though for my own purposes I only cared about cooling_rate and steps for the cool down function, and only energy for the termination condition.

Expanding customization

๐Ÿ‘‹๐Ÿป hello! I've recently started to experiment with simulated annealing libraries. In terms of ruby annealer gems, this one seems to be the most recently updated and has the most tests. I've used it in a project of mine and am happy with its performance, but it does make a few assumptions about the annealing process and I had to monkey patch a few things to get it working with my solution. I'd like to contribute those back to this project. Are you open to discussing them and to contributions? Here's what I'm proposing:

Add a way to specify a custom move function that defaults to what Metal#swap_collection does now.

Metal#swap_collection assumes that the collection is a flat array and a neighboring state can be found by swapping elements. In my case, I'm working with a two dimensional array and neighboring states are created from shifting elements of one internal array to another. I'm sure there are other use cases that might call for more complicated object manipulations. Being able to specify a custom move function that receives the current collection and returns the next collection state would allow this library to be able to anneal more complex objects.

Add a way to specify termination conditions

The simulated annealing algorithm definition typically provides for the ability to specify some condition that will halt the annealing process other than the temperature reaching 0. This could be a "good enough" energy threshold, a temperature other than 0, or some other arbitrary condition. Right now Simulator#run will continue until the temperature reaches 0 and then return whatever state it had settled on. It would be beneficial to be able to specify a function that receives the current metal and temperature, and returns a boolean result as to whether to continue annealing. In my case, for example, the first state that has an energy cost of 0, including the initial state, is considered "good enough" and there's no need to continue annealing.

Add a way to specify a different cooling function

Simulator#cool_down provides a linear temperature reduction algorithm, but simulated annealing is not always linear. There are allowances in the definition for raising, lowering, and holding the temperature until certain conditions are met. It would be useful to provide a way to specify a custom cooling method that takes the current metal, and temperature, and returns the new temperature, such that it could operate linearly, geometrically, exponentially, or based on some other custom formula with the current state in mind. It would use the linear Simulator#cool_down as the default.


With those three changes, each step of the annealing process becomes configurable with reasonable defaults. None of these changes are particularly difficult, and all seem to fit in the same framework as what you already provide for specifying a custom energy calculator:

  • provide a new configuration option that can hold a lambda
  • set a default if nothing is provided
  • allow lambdas to be passed in at run time
  • call the passed or configured lambda

The biggest change would be that we would probably want to switch to keyword arguments for Simulator#run and/or add the ability to pass them to Simulator#initialize, and that's why I wanted to run this by you first since it changes the interface a bit. (We could also do it with positional arguments without changing the existing interface, but that makes it harder to work with IMO.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.