fn next_iter(
        &mut self,
        op: &mut OpWrapper<O>,
        state: &IterState<O>,
    ) -> Result<ArgminIterData<O>, Error> {
        // Careful: The order in here is *very* important, even if it may not seem so. Everything
        // is linked to the iteration number, and getting things mixed up will lead to strange
        // behaviour.

        let prev_param = state.get_param();
        let prev_cost = state.get_cost();

        // Make a move
        let new_param = op.modify(&prev_param, self.cur_temp)?;
        // let new_param = op.modify(&prev_param, self.cur_temp)?;

        // Evaluate cost function with new parameter vector
        let new_cost = op.apply(&new_param)?;

        // Acceptance function
        //
        // Decide whether new parameter vector should be accepted.
        // If no, move on with old parameter vector.
        //
        // Any solution which satisfies `next_cost < prev_cost` will be accepted. Solutions worse
        // than the previous one are accepted with a probability given as:
        //
        // `1 / (1 + exp((next_cost - prev_cost) / current_temperature))`,
        //
        // which will always be between 0 and 0.5.
        let prob: f64 = self.rng.gen();
        let prob = F::from_f64(prob).unwrap();
        let accepted = (new_cost < state.get_prev_cost())
            || (F::from_f64(1.0).unwrap()
                / (F::from_f64(1.0).unwrap()
                    + ((new_cost - state.get_prev_cost()) / self.cur_temp).exp())
                > prob);

        // Update stall iter variables
        self.update_stall_and_reanneal_iter(accepted, new_cost <= state.get_best_cost());

        let (r_fixed, r_accepted, r_best) = self.reanneal();

        // Update temperature for next iteration.
        self.temp_iter += 1;
        // Todo: this variable may not be necessary (temp_iter does the same?)
        self.reanneal_iter_fixed += 1;

        self.update_temperature();

        Ok(if accepted {
            ArgminIterData::new().param(new_param).cost(new_cost)
        } else {
            ArgminIterData::new().param(prev_param).cost(prev_cost)
        }
        .kv(make_kv!(
            "t" => self.cur_temp;
            "new_be" => new_cost <= state.get_best_cost();
            "acc" => accepted;
            "st_i_be" => self.stall_iter_best;
            "st_i_ac" => self.stall_iter_accepted;
            "ra_i_fi" => self.reanneal_iter_fixed;
            "ra_i_be" => self.reanneal_iter_best;
            "ra_i_ac" => self.reanneal_iter_accepted;
            "ra_fi" => r_fixed;
            "ra_be" => r_best;
            "ra_ac" => r_accepted;
        )))
    }
/// Perform one iteration of SA algorithm
Perform one iteration of SA algorithm
Perform one iteration of SA algorithm
fn next_iter(
        &mut self,
        op: &mut OpWrapper<O>,
        state: &IterState<O>,
    ) -> Result<ArgminIterData<O>, Error> {
        // Careful: The order in here is *very* important, even if it may not seem so. Everything
        // is linked to the iteration number, and getting things mixed up will lead to strange
        // behaviour.
        let prev_param = state.get_param();
        let prev_cost = state.get_cost();
        // Make a move
        let new_param = op.modify(&prev_param, self.cur_temp)?;
        // let new_param = op.modify(&prev_param, self.cur_temp)?;
        // Evaluate cost function with new parameter vector
        let new_cost = op.apply(&new_param)?;
        // Acceptance function
        //
        // Decide whether new parameter vector should be accepted.
        // If no, move on with old parameter vector.
        //
        // Any solution which satisfies `next_cost < prev_cost` will be accepted. Solutions worse
        // than the previous one are accepted with a probability given as:
        //
        // `1 / (1 + exp((next_cost - prev_cost) / current_temperature))`,
        //
        // which will always be between 0 and 0.5.
        let prob: f64 = self.rng.gen();
        let prob = F::from_f64(prob).unwrap();
        let accepted = (new_cost < state.get_prev_cost())
            || (F::from_f64(1.0).unwrap()
                / (F::from_f64(1.0).unwrap()
                    + ((new_cost - state.get_prev_cost()) / self.cur_temp).exp())
                > prob);
        // Update stall iter variables
        self.update_stall_and_reanneal_iter(accepted, new_cost <= state.get_best_cost());
        let (r_fixed, r_accepted, r_best) = self.reanneal();
        // Update temperature for next iteration.
        self.temp_iter += 1;
        // Todo: this variable may not be necessary (temp_iter does the same?)
        self.reanneal_iter_fixed += 1;
        self.update_temperature();
        Ok(if accepted {
            ArgminIterData::new().param(new_param).cost(new_cost)
        } else {
            ArgminIterData::new().param(prev_param).cost(prev_cost)
        }
        .kv(make_kv!(
            "t" => self.cur_temp;
            "new_be" => new_cost <= state.get_best_cost();
            "acc" => accepted;
            "st_i_be" => self.stall_iter_best;
            "st_i_ac" => self.stall_iter_accepted;
            "ra_i_fi" => self.reanneal_iter_fixed;
            "ra_i_be" => self.reanneal_iter_best;
            "ra_i_ac" => self.reanneal_iter_accepted;
            "ra_fi" => r_fixed;
            "ra_be" => r_best;
            "ra_ac" => r_accepted;
        )))
    }
fn next_iter ( & mut self , op : & mut OpWrapper < O > , state : & IterState < O > , ) -> Result < ArgminIterData < O > , Error > { // Careful: The order in here is *very* important, even if it may not seem so. Everything // is linked to the iteration number, and getting things mixed up will lead to strange // behaviour. let prev_param = state . get_param ( ) ; let prev_cost = state . get_cost ( ) ; // Make a move let new_param = op . modify ( & prev_param , self . cur_temp ) ? ; // let new_param = op.modify(&prev_param, self.cur_temp)?; // Evaluate cost function with new parameter vector let new_cost = op . apply ( & new_param ) ? ; // Acceptance function // // Decide whether new parameter vector should be accepted. // If no, move on with old parameter vector. // // Any solution which satisfies `next_cost < prev_cost` will be accepted. Solutions worse // than the previous one are accepted with a probability given as: // // `1 / (1 + exp((next_cost - prev_cost) / current_temperature))`, // // which will always be between 0 and 0.5. let prob : f64 = self . rng . gen ( ) ; let prob = F :: from_f64 ( prob ) . unwrap ( ) ; let accepted = ( new_cost < state . get_prev_cost ( ) ) || ( F :: from_f64 ( 1.0 ) . unwrap ( ) / ( F :: from_f64 ( 1.0 ) . unwrap ( ) + ( ( new_cost - state . get_prev_cost ( ) ) / self . cur_temp ) . exp ( ) ) > prob ) ; // Update stall iter variables self . update_stall_and_reanneal_iter ( accepted , new_cost <= state . get_best_cost ( ) ) ; let ( r_fixed , r_accepted , r_best ) = self . reanneal ( ) ; // Update temperature for next iteration. self . temp_iter += 1 ; // Todo: this variable may not be necessary (temp_iter does the same?) self . reanneal_iter_fixed += 1 ; self . update_temperature ( ) ; Ok ( if accepted { ArgminIterData :: new ( ) . param ( new_param ) . cost ( new_cost ) } else { ArgminIterData :: new ( ) . param ( prev_param ) . cost ( prev_cost ) } . kv ( make_kv ! ( " " self cur_temp " " new_cost state get_best_cost ( ) " " accepted " " self stall_iter_best " " self stall_iter_accepted " " self reanneal_iter_fixed " " self reanneal_iter_best " " self reanneal_iter_accepted " " r_fixed " " r_best " " r_accepted ) ) ) }
Perform one iteration of SA algorithm
Perform one iteration of SA algorithm
&mut self
op
&mut OpWrapper<O>
state
&IterState<O>