Ultra 0.9.4
Loading...
Searching...
No Matches
ultra::symbol_set Class Reference

#include <symbol_set.h>

Public Types

using weight_t = internal::w_symbol::weight_t

Public Member Functions

void clear ()
symbol * insert (std::unique_ptr< symbol >, weight_t=default_weight)
template<Symbol S, weight_t = default_weight, class ... Args>
requires std::constructible_from<S, Args...>
std::add_pointer_t< S > insert (Args &&...)
template<std::derived_from< function > F, weight_t W = default_weight, std::convertible_to< symbol::category_t > C = symbol::category_t>
std::add_pointer_t< F > insert (symbol::category_t, std::initializer_list< C >)
 Dedicated overload for function categories passed as a braced list.
template<std::derived_from< function > F, weight_t W = default_weight, std::convertible_to< symbol::category_t > C = symbol::category_t>
std::add_pointer_t< F > insert (std::initializer_list< C >)
 Convenience overload defaulting return type to symbol::default_category.
bool enough_terminals () const noexcept
symbol::category_t categories () const noexcept
std::size_t functions (symbol::category_t=symbol::default_category) const noexcept
std::size_t terminals (symbol::category_t=symbol::default_category) const noexcept
std::size_t variables (symbol::category_t=symbol::default_category) const noexcept
template<Symbol S>
std::size_t count_if (symbol::category_t=symbol::default_category) const noexcept
value_t random_argument (std::size_t, symbol::category_t, double) const
const symbol * roulette (symbol::category_t=symbol::default_category) const
const function * roulette_function (symbol::category_t=symbol::default_category) const
value_t roulette_terminal (symbol::category_t=symbol::default_category) const
const symbol * roulette_free (symbol::category_t=symbol::default_category) const
const symbol * decode (symbol::opcode_t) const
const symbol * decode (const std::string &) const
const terminal * front_terminal (symbol::category_t=symbol::default_category) const
weight_t weight (const symbol &) const
std::set< symbol::category_t > categories_missing_terminal () const
bool is_valid () const
template<Symbol S, symbol_set::weight_t W, class ... Args>
requires std::constructible_from<S, Args...>
std::add_pointer_t< S > insert (Args &&... args)

Static Public Attributes

static constexpr weight_t default_weight = internal::w_symbol::base_weight

Friends

std::ostream & operator<< (std::ostream &, const symbol_set &)

(Note that these are not member symbols.)

std::ostream & operator<< (std::ostream &o, const symbol_set &ss)

Detailed Description

A container for the symbols used by the engine.

Symbols are stored so as to be quickly recalled by category.

Note
The functions and terminals used should be powerful enough to be able to represent a solution to the problem. On the other hand, it's better not to use a symbol set too large (this enlarges the search space and makes harder the search for a solution).

Member Function Documentation

◆ categories()

symbol::category_t ultra::symbol_set::categories ( ) const
nodiscardnoexcept
Returns
number of categories in the symbol set (>= 1)

◆ categories_missing_terminal()

std::set< symbol::category_t > ultra::symbol_set::categories_missing_terminal ( ) const
nodiscard

Calculates the set of categories that need a terminal before the correct representation of a SLP gp::individual would be possible.

Returns
the set of categories

Consider that:

  • random generation of individuals may put whatever available function at index 0;
  • input values of a function at index 0 can only be terminals.

So we want, at least, one terminal for every category used by a function.

◆ clear()

void ultra::symbol_set::clear ( )

Clears the current symbol set.

◆ count_if()

template<Symbol S>
std::size_t ultra::symbol_set::count_if ( symbol::category_t c = symbol::default_category) const
nodiscardnoexcept
Template Parameters
Sa type of symbol
Parameters
[in]ca category
Returns
number of symbols of type S in category c

◆ decode() [1/2]

const symbol * ultra::symbol_set::decode ( const std::string & dex) const
nodiscard
Parameters
[in]dexthe name of a symbol
Returns
a pointer to the symbol identified by dex (0 if not found)
Attention
Please note that opcodes are automatically generated and fully identify a symbol (they're primary keys). Conversely the name of a symbol is chosen by the user, so, if you don't pay attention, different symbols may have the same name.

◆ decode() [2/2]

const symbol * ultra::symbol_set::decode ( symbol::opcode_t opcode) const
nodiscard
Parameters
[in]opcodenumerical code used as primary key for a symbol
Returns
a pointer to the ultra::symbol identified by opcode (nullptr if not found).

◆ enough_terminals()

bool ultra::symbol_set::enough_terminals ( ) const
nodiscardnoexcept
Returns
true if there are enough terminals for secure individual generation

◆ front_terminal()

const terminal * ultra::symbol_set::front_terminal ( symbol::category_t c = symbol::default_category) const
nodiscard

Extracts the first terminal of a given category.

Parameters
[in]ca category
Returns
first terminal of category c

◆ functions()

std::size_t ultra::symbol_set::functions ( symbol::category_t c = symbol::default_category) const
nodiscardnoexcept
Parameters
[in]ca category
Returns
number of functions in category c

◆ insert() [1/2]

template<Symbol S, symbol_set::weight_t W, class ... Args>
requires std::constructible_from<S, Args...>
std::add_pointer_t< S > ultra::symbol_set::insert ( Args &&... args)

General factory for any Symbol directly constructible from Args....

Template Parameters
Ssymbol to be added
Wweight associated to S
Parameters
[in]argsarguments used to build S
Returns
a raw pointer to the symbol just added (or nullptr in case of error)

Insert a symbol in the symbol set without the user having to allocate memory.

Note
Only partially replaces the insert(std::unique_ptr) method (e.g. building from factory).

◆ insert() [2/2]

symbol * ultra::symbol_set::insert ( std::unique_ptr< symbol > new_sym,
weight_t w = default_weight )

Adds a new symbol to the set.

Parameters
[in]new_symsymbol to be added
[in]wthe weight of new_sym (default_weight means standard frequency, 2 * default_weight doubles the selection probability)
Returns
a raw pointer to the symbol just added (or nullptr in case of error)

A symbol with undefined category will be changed to the first free category.

◆ is_valid()

bool ultra::symbol_set::is_valid ( ) const
nodiscard
Returns
true if the object passes the internal consistency check

◆ random_argument()

value_t ultra::symbol_set::random_argument ( std::size_t address_sup,
symbol::category_t c,
double p_address ) const
nodiscard

Generates a random argument for a program instruction.

Parameters
[in]address_supnumber of preceding instructions available
[in]crequired argument category
[in]p_addressprobability of referencing a preceding instruction
Returns
a random argument compatible with category c

The argument can be either a literal value or a reference to a preceding instruction.

◆ roulette()

const symbol * ultra::symbol_set::roulette ( symbol::category_t c = symbol::default_category) const
nodiscard

Extracts a random symbol from the symbol set without bias between terminals and functions.

Parameters
[in]ca category
Returns
a random symbol of category c
Attention
  • $P(terminal) = P(function) = 1/2$
  • $P(terminal_i|terminal) = \frac{w_i}{\sum_{t \in terminals} w_t}$
  • $P(function_i|function) = \frac{w_i}{\sum_{f \in functions} w_f}$
Note
If all symbols have the same probability to appear into a chromosome, there could be some problems. For instance, if our problem has many variables (let's say 100) and the function set has only 4 symbols we cannot get too complex trees because the functions have a reduced chance to appear in the chromosome.

◆ roulette_free()

const symbol * ultra::symbol_set::roulette_free ( symbol::category_t c = symbol::default_category) const
nodiscard

Extracts a random symbol from the symbol set.

Parameters
[in]ca category
Returns
a random symbol of category c
Attention
Given $S_t = \sum_{i \in terminals} {w_i}$ and $S_f = \sum_{i \in functions} {w_i}$ we have:
  • $P(terminal_i|terminal) = \frac {w_i} {S_t}$
  • $P(function_i|function) = \frac {w_i} {S_f}$
  • $P(terminal) = \frac {S_t} {S_t + S_f}$
  • $P(function) = \frac {S_f} {S_t + S_f}$

◆ roulette_function()

const function * ultra::symbol_set::roulette_function ( symbol::category_t c = symbol::default_category) const
nodiscard
Parameters
[in]ca category
Returns
a random function of category c

◆ roulette_terminal()

value_t ultra::symbol_set::roulette_terminal ( symbol::category_t c = symbol::default_category) const
nodiscard

Extracts a literal terminal value.

Parameters
[in]ca category
Returns
a random value of category c

◆ terminals()

std::size_t ultra::symbol_set::terminals ( symbol::category_t c = symbol::default_category) const
nodiscardnoexcept
Parameters
[in]ca category
Returns
number of terminals in category c

◆ weight()

symbol_set::weight_t ultra::symbol_set::weight ( const symbol & s) const
nodiscard
Parameters
[in]sa symbol
Returns
the weight of s
Precondition
s must be a symbol previously inserted into this symbol set, or at least have a category valid for this set

◆ operator<<()

std::ostream & operator<< ( std::ostream & o,
const symbol_set & ss )
related

Prints the symbol set to an output stream.

Parameters
[out]ooutput stream
[in]sssymbol set to be printed
Returns
output stream including ss
Note
Useful for debugging purpose.

The documentation for this class was generated from the following files: