Trait abc::Context [] [src]

pub trait Context: Send + Sync {
    type Solution: Clone + Send + Sync + 'static;
    fn make(&self) -> Self::Solution;
    fn evaluate_fitness(&self, solution: &Self::Solution) -> f64;
    fn explore(&self, field: &[Candidate<Self::Solution>], index: usize) -> Self::Solution;
}

Context for generating and evaluating solutions.

The ABC algorithm is abstract enough to work on a variety of problems, some of which may involve a fairly complex interaction with the search space. The Context is responsible for maintaining an understanding of that space. That could involve communication or the like. If the problem is straightforward enough not to require this kind of information, a Context can be a unit-like struct.

Note that the Context methods all take an immutable &self reference. While the algorithm is running, several worker threads will share read- only references to the context. So, if there is any mutable data in the context, it is up to the user to wrap it in a Mutex or other locking mechanism. This will allow you to access the fields from multiple threads, without needing a &mut reference.

Examples

extern crate rand;

use abc::{Context, Candidate};
use rand::Rng;

struct Ctx;

impl Context for Ctx {
    type Solution = i32;

    fn make(&self) -> i32 {
        let mut rng = rand::thread_rng();
        rng.gen_range(0, 100)
    }

    // Minimize the numerical value.
    fn evaluate_fitness(&self, solution: &i32) -> f64 {
        1f64 / *solution as f64
    }

    fn explore(&self, field: &[Candidate<i32>], n: usize) -> i32 {
        let mut rng = rand::thread_rng();
        field[n].solution + rng.gen_range(-10, 10)
    }
}

Associated Types

type Solution: Clone + Send + Sync + 'static

Type of solutions generated and evaluated by the ABC.

For example, a solution for finding the highest point on a 2D map would be a pair of X and Y coordinates. For more complicated tasks, like playing a game, this could be a struct with fields for the various tuning knobs relevant to gameplay.

Required Methods

fn make(&self) -> Self::Solution

Generates a fresh, random solution.

fn evaluate_fitness(&self, solution: &Self::Solution) -> f64

Discovers the fitness of a solution (the algorithm will maximize this).

Finding an optimal solution depends on having a way to determine the fitness of one solution compared with another. Because there are diverse goals for optimization, the user must implement their own evaluate_fitness function.

The user may wish to use information from the other solutions to evaluate a given solution. So, rather than simply providing the solution to be varied, evaluate_fitness receives a slice of solution refs that give information on the existing solutions, and the index of the solution to be evaluated.

fn explore(&self, field: &[Candidate<Self::Solution>], index: usize) -> Self::Solution

Looks "near" an existing solution.

The user may wish to use information from the other solutions to build a variant of a given solution. So, rather than simply providing the solution to be varied, explore receives a slice of solution refs that give information on the existing solutions, and the index of the solution to be modified.

Implementors