Search Results for

    Show / Hide Table of Contents

    Solver Development

    A new solver is created by extending solver::AbstractSolver or solver::SteppingSolver. The latter has stepping logic already implemented and is currently used for all the built-in solvers. It is customary to template your solver for Model_T -- the class of the model to be simulated.

    The base class defines which methods must be implemented for the solver to work. For a SteppingSolver, they are:

    method purpose
    get_identifier() string identifying the solver -- this will be the target='...' value in the input.
    configure(...) method telling qiotoolkit how to read model configuration from input.
    init() called after configure(), allowing you to initialize based on configuration.
    make_step(step) perform the next step in the simulation.
    get_model_sweep_size() should return the sweep size of the model being simulated*
    get_lowest_cost() should return the lowest cost found so far (used for limit_cost condition)
    get_solutions() should render the best solution(s) found.

    Implementation

    The solver should rely on the interfaces provided by a markov::Model to perform its work. They are sufficient to build a markov chain, but might not cater to the need of more sophisticated solvers. For instance, the MUREX solver can currently only simulate the Poly model, because it relies on the additional parameter interfaces it provides.

    Example

    The following shows an implementation of a "steep descent" algorithm. Its deliberately not called "steepest" because the ::markov::Model interfaces do not allow us to enumerate all possible transitions from a given starting point. (And, depending on the model, this might be infeasible). Instead we settle for sampling a number of different candidates and picking the best choice (or none) at each step:

    
    #pragma once
    
    #include "utils/random_generator.h"
    #include "solver/stepping_solver.h"
    
    namespace examples
    {
    template <class Model_T>
    class Descent : public ::solver::SteppingSolver<Model_T>
    {
     public:
      using Base_T = ::solver::SteppingSolver<Model_T>;
      using State_T = typename Model_T::State_T;
      using Transition_T = typename Model_T::Transition_T;
    
      std::string get_identifier() const override
      {
        return "descent.qiotoolkit";
      }
    
      void configure(const utils::Json& json) override
      {
        Base_T::configure(json);
        this->param(json[utils::kParams], "samples", samples_)
            .description("number of samples to take for the gradient")
            .default_value(10)
            .matches(matcher::GreaterThan(0))
            .with_output();
      }
    
      std::string init_memory_check_error_message() const override
      {
        return (
            "Input problem is too large."
            "Expected to exceed machine's current available memory.");
      }
    
      size_t target_number_of_states() const override { return 1; }
    
      void init() override
      {
        this->init_memory_check();
        state_ = this->model_->get_random_state(*this->rng_);
        cost_ = this->model_->calculate_cost(state_);
      }
    
      void make_step(uint64_t) override
      {
        Transition_T transition;
        double best = 1.0;
        for (int i = 0; i < samples_; i++)
        {
          Transition_T candidate =
              this->model_->get_random_transition(state_, *this->rng_);
          double diff = this->model_->calculate_cost_difference(state_, candidate);
          if (diff < best)
          {
            best = diff;
            transition = candidate;
          }
        }
        if (best <= 0.0)
        {
          this->model_->apply_transition(transition, state_);
          cost_ += best;
          DEBUG("new best: ", cost_, " ", state_);
          this->update_lowest_cost(cost_, state_);
        }
      }
    
      void finalize() override { this->update_lowest_cost(cost_, state_); }
    
     protected:
      int samples_;
      double cost_;
      State_T state_;
    };
    
    }  // namespace examples
    
    In This Article
    Back to top Generated with Doxygen and DocFX