# hub.solver.openevolve.openevolve_wrapper

Domain specification

Domain

# Planner

Protocol for the class defined in the evolving program.

# sample_action Planner

sample_action(
  self,
obs: typing.Any,
applicable_actions: typing.Optional[typing.Any] = None
) -> typing.Any

Sample action method from the planner.

Potentially the types are different from the scikit-decide solver's sample_action method.

# Parameters

  • obs: current observation
  • applicable_actions: applicable actions depending on current domain state Not used if the domain derives from UnrestrictedActions.

# Returns

sampled action

# _BaseOpenEvolve

Wrapper around openevolve to evolve a greedy heuristic adapted to a given domain class.

We start from an initial program that should

  • define a Planner class (instantiated from characteristics of the domain)
  • define a Planner.sample_action(obs, applicable_actions) sampling an action from a domain observation (or a characteristics of it)
  • have # EVOLVE-BLOCK-START and # EVOLVE-BLOCK-END around the class definition

Openevolve makes it evolve and the resulting program is loaded to be called in the solver's sample_action().

# check_domain Solver

check_domain(
  domain: Domain
) -> bool

Check whether a domain is compliant with this solver type.

By default, Solver.check_domain() provides some boilerplate code and internally calls Solver._check_domain_additional() (which returns True by default but can be overridden to define specific checks in addition to the "domain requirements"). The boilerplate code automatically checks whether all domain requirements are met.

# Parameters

  • domain: The domain to check.

# Returns

True if the domain is compliant with the solver type (False otherwise).

# complete_with_default_hyperparameters Hyperparametrizable

complete_with_default_hyperparameters(
  kwargs: dict[str, Any],
names: Optional[list[str]] = None
)

Add missing hyperparameters to kwargs by using default values

Args: kwargs: keyword arguments to complete (e.g. for __init__, init_model, or solve) names: names of the hyperparameters to add if missing. By default, all available hyperparameters.

Returns: a new dictionary, completion of kwargs

# copy_and_update_hyperparameters Hyperparametrizable

copy_and_update_hyperparameters(
  names: Optional[list[str]] = None,
**kwargs_by_name: dict[str, Any]
) -> list[Hyperparameter]

Copy hyperparameters definition of this class and update them with specified kwargs.

This is useful to define hyperparameters for a child class for which only choices of the hyperparameter change for instance.

Args: names: names of hyperparameters to copy. Default to all. **kwargs_by_name: for each hyperparameter specified by its name, the attributes to update. If a given hyperparameter name is not specified, the hyperparameter is copied without further update.

Returns:

# evaluate_program_code _BaseOpenEvolve

evaluate_program_code(
  self,
code:
) ->

Evaluate the program code as openevolve does during evolution.

# Parameters

  • code: code of the program to evaluate

# Returns

evaluation result computed by the opensolve controller using the underlying evaluator file

# get_best_program_code _BaseOpenEvolve

get_best_program_code(
  self
) ->

Get best program code found so far.

# Returns

# get_default_hyperparameters Hyperparametrizable

get_default_hyperparameters(
  names: Optional[list[str]] = None
) -> dict[str, Any]

Get hyperparameters default values.

Args: names: names of the hyperparameters to choose. By default, all available hyperparameters will be suggested.

Returns: a mapping between hyperparameter's name_in_kwargs and its default value (None if not specified)

# get_domain_requirements Solver

get_domain_requirements(
) -> list[type]

Get domain requirements for this solver class to be applicable.

Domain requirements are classes from the skdecide.builders.domain package that the domain needs to inherit from.

# Returns

A list of classes to inherit from.

# get_hyperparameter Hyperparametrizable

get_hyperparameter(
  name: str
) -> Hyperparameter

Get hyperparameter from given name.

# get_hyperparameters_by_name Hyperparametrizable

get_hyperparameters_by_name(
) -> dict[str, Hyperparameter]

Mapping from name to corresponding hyperparameter.

# get_hyperparameters_names Hyperparametrizable

get_hyperparameters_names(
) -> list[str]

List of hyperparameters names.

# is_policy_defined_for Policies

is_policy_defined_for(
  self,
observation: StrDict[D.T_observation]
) -> bool

Check whether the solver's current policy is defined for the given observation.

# Parameters

  • observation: The observation to consider.

# Returns

True if the policy is defined for the given observation memory (False otherwise).

# load Restorable

load(
  self,
path: str
) -> None

Restore the solver state from given path.

# Parameters

  • path: The path where the solver state was saved.

# reset Solver

reset(
  self
) -> None

Reset whatever is needed on this solver before running a new episode.

This function does nothing by default but can be overridden if needed (e.g. to reset the hidden state of a LSTM policy network, which carries information about past observations seen in the previous episode).

# sample_action Policies

sample_action(
  self,
observation: StrDict[D.T_observation],
domain: Optional[Domain] = None
) -> StrDict[list[D.T_event]]

Sample an action for the given observation (from the solver's current policy).

# Parameters

  • observation: The observation for which an action must be sampled.
  • domain: the domain source of the observation. Typically used to get current applicable actions or action mask.

# Returns

The sampled action.

# sample_prompt _BaseOpenEvolve

sample_prompt(
  self
) -> dict[str, str]

Sample a prompt for LLM as done during openevolve evolution with current settings.

# Returns

a dictionary

  • system -> system prompt
  • user -> user prompt

# save Restorable

save(
  self,
path: str
) -> None

Save the solver state to given path.

# Parameters

  • path: The path to store the saved state.

# solve FromInitialState

solve(
  self
) -> None

Run the solving process.

TIP

The nature of the solutions produced here depends on other solver's characteristics like policy and assessibility.

# suggest_hyperparameter_with_optuna Hyperparametrizable

suggest_hyperparameter_with_optuna(
  trial: optuna.trial.Trial,
name: str,
prefix: str,
**kwargs
) -> Any

Suggest hyperparameter value during an Optuna trial.

This can be used during Optuna hyperparameters tuning.

Args: trial: optuna trial during hyperparameters tuning name: name of the hyperparameter to choose prefix: prefix to add to optuna corresponding parameter name (useful for disambiguating hyperparameters from subsolvers in case of meta-solvers) **kwargs: options for optuna hyperparameter suggestions

Returns:

kwargs can be used to pass relevant arguments to

  • trial.suggest_float()
  • trial.suggest_int()
  • trial.suggest_categorical()

For instance it can

  • add a low/high value if not existing for the hyperparameter or override it to narrow the search. (for float or int hyperparameters)
  • add a step or log argument (for float or int hyperparameters, see optuna.trial.Trial.suggest_float())
  • override choices for categorical or enum parameters to narrow the search

# suggest_hyperparameters_with_optuna Hyperparametrizable

suggest_hyperparameters_with_optuna(
  trial: optuna.trial.Trial,
names: Optional[list[str]] = None,
kwargs_by_name: Optional[dict[str, dict[str, Any]]] = None,
fixed_hyperparameters: Optional[dict[str, Any]] = None,
prefix: str
) -> dict[str, Any]

Suggest hyperparameters values during an Optuna trial.

Args: trial: optuna trial during hyperparameters tuning names: names of the hyperparameters to choose. By default, all available hyperparameters will be suggested. If fixed_hyperparameters is provided, the corresponding names are removed from names. kwargs_by_name: options for optuna hyperparameter suggestions, by hyperparameter name fixed_hyperparameters: values of fixed hyperparameters, useful for suggesting subbrick hyperparameters, if the subbrick class is not suggested by this method, but already fixed. Will be added to the suggested hyperparameters. prefix: prefix to add to optuna corresponding parameters (useful for disambiguating hyperparameters from subsolvers in case of meta-solvers)

Returns: mapping between the hyperparameter name and its suggested value. If the hyperparameter has an attribute name_in_kwargs, this is used as the key in the mapping instead of the actual hyperparameter name. the mapping is updated with fixed_hyperparameters.

kwargs_by_name[some_name] will be passed as **kwargs to suggest_hyperparameter_with_optuna(name=some_name)

# Constructor _BaseOpenEvolve

_BaseOpenEvolve(
  domain_factory: typing.Callable[[], skdecide.domains.Domain],
initial_program_path: ,
evaluator_path: ,
config: typing.Union[str, pathlib.Path, openevolve.config.Config, NoneType] = None,
output_dir: typing.Optional[str] = None,
target_score: typing.Optional[float] = None,
prompt_add_blockevolve_instruction: = True,
nb_iterations: typing.Optional[int] = None,
**kwargs: typing.Any
)

# Parameters

  • domain_factory: domain factory on which the solver works
  • initial_program_path: path to the initial program to evolve (see above for hypotheses on it)
  • evaluator_path: path to the evaluation script used by openevolve
  • config: config yaml file to be used by openevolve (or openevolve.Config object). Potentially contains the prompt header used to describe the domain to work on. If a config object is given, it is copied to avoid prompt automatic modifications to be stored in the original config.
  • output_dir: output directory for openevolve evolution
  • target_score: target score used by openevolve
  • prompt_add_blockevolve_instruction: if True, add an instruction at the end of the system prompt found in the config to restrict changes between the # EVOLVE-BLOCK-START and # EVOLVE-BLOCK-END token.
  • nb_iterations: override number of iterations found in config
  • kwargs:

# _check_domain_additional Solver

_check_domain_additional(
  domain: Domain
) -> bool

Check whether the given domain is compliant with the specific requirements of this solver type (i.e. the ones in addition to "domain requirements").

This is a helper function called by default from Solver.check_domain(). It focuses on specific checks, as opposed to taking also into account the domain requirements for the latter.

# Parameters

  • domain: The domain to check.

# Returns

True if the domain is compliant with the specific requirements of this solver type (False otherwise).

# _cleanup Solver

_cleanup(
  self
)

Runs cleanup code here, or code to be executed at the exit of a 'with' context statement.

# _convert_action_from_planner _BaseOpenEvolve

_convert_action_from_planner(
  self,
pre_action: typing.Any
) -> skdecide.domains.T_event

Conversion of planner action.

By default, identity.

# _convert_applicable_actions_for_planner _BaseOpenEvolve

_convert_applicable_actions_for_planner(
  self,
applicable_actions: skdecide.core.Space[skdecide.domains.T_event]
) -> typing.Any

Convert into planner actions format.

By default, identity.

# _convert_obs_for_planner _BaseOpenEvolve

_convert_obs_for_planner(
  self,
observation: skdecide.domains.T_observation
) -> typing.Any

Convert into planner observation format.

By default, identity.

# _initialize Solver

_initialize(
  self
)

Runs long-lasting initialization code here.

# _is_policy_defined_for Policies

_is_policy_defined_for(
  self,
observation: skdecide.domains.T_observation
) ->

Check whether the solver's current policy is defined for the given observation.

# Parameters

  • observation: The observation to consider.

# Returns

True if the policy is defined for the given observation memory (False otherwise).

# _load Restorable

_load(
  self,
path:
)

Restore the solver state from given path.

Load the given checkpoint directory into the openevolve database.

# Parameters

  • path: The path where the solver state was saved.

# _reset Solver

_reset(
  self
) -> None

Reset whatever is needed on this solver before running a new episode.

This function does nothing by default but can be overridden if needed (e.g. to reset the hidden state of a LSTM policy network, which carries information about past observations seen in the previous episode).

# _sample_action Policies

_sample_action(
  self,
observation: skdecide.domains.T_observation,
domain: typing.Optional[skdecide.domains.Domain] = None
) -> skdecide.domains.T_event

Sample an action for the given observation (from the solver's current policy).

# Parameters

  • observation: The observation for which an action must be sampled.
  • domain: the domain source of the observation. Typically used to get current applicable actions or action mask. NB: Be careful that the domain has not been autocast, so may not respect the T_domain specs.

# Returns

The sampled action.

# _save Restorable

_save(
  self,
path:
)

Save the solver state to given path.

Save the openevolve database to the given path (as it does for checkpoint)

# Parameters

  • path: The path to store the saved state. (Must be a directory path, potentially to be created)

# _solve FromInitialState

_solve(
  self
)

Run the solving process.

TIP

The nature of the solutions produced here depends on other solver's characteristics like policy and assessibility.

# ProxyOpenEvolve

Wrapper around openevolve without LLM knowing about scikit-decide.

We start from an initial program that should

  • define a Planner class (instantiated from characteristics of the domain)
  • define a Planner.sample_action(obs, applicable_actions=None) sampling an action from a domain observation (or a characteristics of it), and applicable actions (potentially in a custom format) in the case of a domain with restricted actions
  • have # EVOLVE-BLOCK-START and # EVOLVE-BLOCK-END around the class definition
  • avoid any reference to scikit-decide api (not mandatory but recommended)

The idea here is that the initial program should be self-contained to make openevolve works more efficiently without the LLM needing to know about scikit-decide.

We then have functions to be provided by the user:

  • planner_kwargs_factory: extract needed args to instantiate Planner from the domain
  • planner_obs_converter: convert domain observation into first arg needed by Planner.sample_action()
  • planner_action_converter: convert output of Planner.sample_action into domain action
  • planner_applicable_actions_converter: convert applicable actions from domain.get_applicable_actions() into second arg needed by Planner.sample_action() (this arg is not used for domains deriving from UnrestrictedActions)

Note: the evaluator can reference the scikit-decide as it is not sent to the LLM.

# Constructor ProxyOpenEvolve

ProxyOpenEvolve(
  domain_factory: typing.Callable[[], skdecide.domains.Domain],
initial_program_path: ,
evaluator_path: ,
planner_kwargs_factory: typing.Callable[[skdecide.domains.Domain], dict[str, typing.Any]],
planner_obs_converter: typing.Callable[[skdecide.domains.T_observation], typing.Any] = <lambda function>,
planner_action_converter: typing.Callable[[typing.Any], skdecide.domains.T_event] = <lambda function>,
planner_applicable_actions_converter: typing.Callable[[skdecide.core.Space[skdecide.domains.T_event]], typing.Any] = <lambda function>,
config: typing.Union[str, pathlib.Path, openevolve.config.Config, NoneType] = None,
output_dir: typing.Optional[str] = None,
target_score: typing.Optional[float] = None,
prompt_add_blockevolve_instruction: = True,
nb_iterations: typing.Optional[int] = None,
**kwargs: typing.Any
)

# Parameters

  • domain_factory: domain factory on which the solver works
  • initial_program_path: path to the initial program to evolve (see above for hypotheses on it)
  • evaluator_path: path to the evaluation script used by openevolve
  • planner_kwargs_factory: function generating the kwargs to instanciate the evolved planner from the domain
  • planner_obs_converter: function converting domain observation into first arg needed by the evolved planner sample_action method (default to identity) planner_action_converter: function converting the action returned by the evolved planner into an actual action of the domain (default to identity) planner_applicable_actions_converter: function converting applicable actions space into second arg needed by the evolved planner sample_action method (default to identity). Not used if the domain derives from UnrestrictedActions. config: config yaml file to be used by openevolve (or openevolve.Config object). Potentially contains the prompt header used to describe the domain to work on. output_dir: output directory for openevolve evolution target_score: target score used by openevolve prompt_add_blockevolve_instruction: if True, add an instruction at the end of the system prompt found in the config to restrict changes between the # EVOLVE-BLOCK-START and # EVOLVE-BLOCK-END token. nb_iterations: override number of iterations found in config kwargs:

# check_domain Solver

check_domain(
  domain: Domain
) -> bool

Check whether a domain is compliant with this solver type.

By default, Solver.check_domain() provides some boilerplate code and internally calls Solver._check_domain_additional() (which returns True by default but can be overridden to define specific checks in addition to the "domain requirements"). The boilerplate code automatically checks whether all domain requirements are met.

# Parameters

  • domain: The domain to check.

# Returns

True if the domain is compliant with the solver type (False otherwise).

# complete_with_default_hyperparameters Hyperparametrizable

complete_with_default_hyperparameters(
  kwargs: dict[str, Any],
names: Optional[list[str]] = None
)

Add missing hyperparameters to kwargs by using default values

Args: kwargs: keyword arguments to complete (e.g. for __init__, init_model, or solve) names: names of the hyperparameters to add if missing. By default, all available hyperparameters.

Returns: a new dictionary, completion of kwargs

# copy_and_update_hyperparameters Hyperparametrizable

copy_and_update_hyperparameters(
  names: Optional[list[str]] = None,
**kwargs_by_name: dict[str, Any]
) -> list[Hyperparameter]

Copy hyperparameters definition of this class and update them with specified kwargs.

This is useful to define hyperparameters for a child class for which only choices of the hyperparameter change for instance.

Args: names: names of hyperparameters to copy. Default to all. **kwargs_by_name: for each hyperparameter specified by its name, the attributes to update. If a given hyperparameter name is not specified, the hyperparameter is copied without further update.

Returns:

# evaluate_program_code _BaseOpenEvolve

evaluate_program_code(
  self,
code:
) ->

Evaluate the program code as openevolve does during evolution.

# Parameters

  • code: code of the program to evaluate

# Returns

evaluation result computed by the opensolve controller using the underlying evaluator file

# get_best_program_code _BaseOpenEvolve

get_best_program_code(
  self
) ->

Get best program code found so far.

# Returns

# get_default_hyperparameters Hyperparametrizable

get_default_hyperparameters(
  names: Optional[list[str]] = None
) -> dict[str, Any]

Get hyperparameters default values.

Args: names: names of the hyperparameters to choose. By default, all available hyperparameters will be suggested.

Returns: a mapping between hyperparameter's name_in_kwargs and its default value (None if not specified)

# get_domain_requirements Solver

get_domain_requirements(
) -> list[type]

Get domain requirements for this solver class to be applicable.

Domain requirements are classes from the skdecide.builders.domain package that the domain needs to inherit from.

# Returns

A list of classes to inherit from.

# get_hyperparameter Hyperparametrizable

get_hyperparameter(
  name: str
) -> Hyperparameter

Get hyperparameter from given name.

# get_hyperparameters_by_name Hyperparametrizable

get_hyperparameters_by_name(
) -> dict[str, Hyperparameter]

Mapping from name to corresponding hyperparameter.

# get_hyperparameters_names Hyperparametrizable

get_hyperparameters_names(
) -> list[str]

List of hyperparameters names.

# is_policy_defined_for Policies

is_policy_defined_for(
  self,
observation: StrDict[D.T_observation]
) -> bool

Check whether the solver's current policy is defined for the given observation.

# Parameters

  • observation: The observation to consider.

# Returns

True if the policy is defined for the given observation memory (False otherwise).

# load Restorable

load(
  self,
path: str
) -> None

Restore the solver state from given path.

# Parameters

  • path: The path where the solver state was saved.

# reset Solver

reset(
  self
) -> None

Reset whatever is needed on this solver before running a new episode.

This function does nothing by default but can be overridden if needed (e.g. to reset the hidden state of a LSTM policy network, which carries information about past observations seen in the previous episode).

# sample_action Policies

sample_action(
  self,
observation: StrDict[D.T_observation],
domain: Optional[Domain] = None
) -> StrDict[list[D.T_event]]

Sample an action for the given observation (from the solver's current policy).

# Parameters

  • observation: The observation for which an action must be sampled.
  • domain: the domain source of the observation. Typically used to get current applicable actions or action mask.

# Returns

The sampled action.

# sample_prompt _BaseOpenEvolve

sample_prompt(
  self
) -> dict[str, str]

Sample a prompt for LLM as done during openevolve evolution with current settings.

# Returns

a dictionary

  • system -> system prompt
  • user -> user prompt

# save Restorable

save(
  self,
path: str
) -> None

Save the solver state to given path.

# Parameters

  • path: The path to store the saved state.

# solve FromInitialState

solve(
  self
) -> None

Run the solving process.

TIP

The nature of the solutions produced here depends on other solver's characteristics like policy and assessibility.

# suggest_hyperparameter_with_optuna Hyperparametrizable

suggest_hyperparameter_with_optuna(
  trial: optuna.trial.Trial,
name: str,
prefix: str,
**kwargs
) -> Any

Suggest hyperparameter value during an Optuna trial.

This can be used during Optuna hyperparameters tuning.

Args: trial: optuna trial during hyperparameters tuning name: name of the hyperparameter to choose prefix: prefix to add to optuna corresponding parameter name (useful for disambiguating hyperparameters from subsolvers in case of meta-solvers) **kwargs: options for optuna hyperparameter suggestions

Returns:

kwargs can be used to pass relevant arguments to

  • trial.suggest_float()
  • trial.suggest_int()
  • trial.suggest_categorical()

For instance it can

  • add a low/high value if not existing for the hyperparameter or override it to narrow the search. (for float or int hyperparameters)
  • add a step or log argument (for float or int hyperparameters, see optuna.trial.Trial.suggest_float())
  • override choices for categorical or enum parameters to narrow the search

# suggest_hyperparameters_with_optuna Hyperparametrizable

suggest_hyperparameters_with_optuna(
  trial: optuna.trial.Trial,
names: Optional[list[str]] = None,
kwargs_by_name: Optional[dict[str, dict[str, Any]]] = None,
fixed_hyperparameters: Optional[dict[str, Any]] = None,
prefix: str
) -> dict[str, Any]

Suggest hyperparameters values during an Optuna trial.

Args: trial: optuna trial during hyperparameters tuning names: names of the hyperparameters to choose. By default, all available hyperparameters will be suggested. If fixed_hyperparameters is provided, the corresponding names are removed from names. kwargs_by_name: options for optuna hyperparameter suggestions, by hyperparameter name fixed_hyperparameters: values of fixed hyperparameters, useful for suggesting subbrick hyperparameters, if the subbrick class is not suggested by this method, but already fixed. Will be added to the suggested hyperparameters. prefix: prefix to add to optuna corresponding parameters (useful for disambiguating hyperparameters from subsolvers in case of meta-solvers)

Returns: mapping between the hyperparameter name and its suggested value. If the hyperparameter has an attribute name_in_kwargs, this is used as the key in the mapping instead of the actual hyperparameter name. the mapping is updated with fixed_hyperparameters.

kwargs_by_name[some_name] will be passed as **kwargs to suggest_hyperparameter_with_optuna(name=some_name)

# _check_domain_additional Solver

_check_domain_additional(
  domain: Domain
) -> bool

Check whether the given domain is compliant with the specific requirements of this solver type (i.e. the ones in addition to "domain requirements").

This is a helper function called by default from Solver.check_domain(). It focuses on specific checks, as opposed to taking also into account the domain requirements for the latter.

# Parameters

  • domain: The domain to check.

# Returns

True if the domain is compliant with the specific requirements of this solver type (False otherwise).

# _cleanup Solver

_cleanup(
  self
)

Runs cleanup code here, or code to be executed at the exit of a 'with' context statement.

# _convert_action_from_planner _BaseOpenEvolve

_convert_action_from_planner(
  self,
pre_action: typing.Any
) -> skdecide.domains.T_event

Conversion of planner action.

By default, identity.

# _convert_applicable_actions_for_planner _BaseOpenEvolve

_convert_applicable_actions_for_planner(
  self,
applicable_actions: skdecide.core.Space[skdecide.domains.T_event]
) -> typing.Any

Convert into planner actions format.

By default, identity.

# _convert_obs_for_planner _BaseOpenEvolve

_convert_obs_for_planner(
  self,
observation: skdecide.domains.T_observation
) -> typing.Any

Convert into planner observation format.

By default, identity.

# _initialize Solver

_initialize(
  self
)

Runs long-lasting initialization code here.

# _is_policy_defined_for Policies

_is_policy_defined_for(
  self,
observation: skdecide.domains.T_observation
) ->

Check whether the solver's current policy is defined for the given observation.

# Parameters

  • observation: The observation to consider.

# Returns

True if the policy is defined for the given observation memory (False otherwise).

# _load Restorable

_load(
  self,
path:
)

Restore the solver state from given path.

Load the given checkpoint directory into the openevolve database.

# Parameters

  • path: The path where the solver state was saved.

# _reset Solver

_reset(
  self
) -> None

Reset whatever is needed on this solver before running a new episode.

This function does nothing by default but can be overridden if needed (e.g. to reset the hidden state of a LSTM policy network, which carries information about past observations seen in the previous episode).

# _sample_action Policies

_sample_action(
  self,
observation: skdecide.domains.T_observation,
domain: typing.Optional[skdecide.domains.Domain] = None
) -> skdecide.domains.T_event

Sample an action for the given observation (from the solver's current policy).

# Parameters

  • observation: The observation for which an action must be sampled.
  • domain: the domain source of the observation. Typically used to get current applicable actions or action mask. NB: Be careful that the domain has not been autocast, so may not respect the T_domain specs.

# Returns

The sampled action.

# _save Restorable

_save(
  self,
path:
)

Save the solver state to given path.

Save the openevolve database to the given path (as it does for checkpoint)

# Parameters

  • path: The path to store the saved state. (Must be a directory path, potentially to be created)

# _solve FromInitialState

_solve(
  self
)

Run the solving process.

TIP

The nature of the solutions produced here depends on other solver's characteristics like policy and assessibility.

# IntegratedOpenEvolve

Wrapper around openevolve with the LLM directly using the scikit-decide domain API.

We start from an initial program that should

  • define a Planner class initialized with a domain instance
  • define a Planner.sample_action() sampling a domain action from a domain observation
  • have # EVOLVE-BLOCK-START and # EVOLVE-BLOCK-END around the class definition
  • import the scikit-decide domain

The idea here is that the initial program has access to the scikit-decide domain public API. Could potentially create a solver for all domains sharing the domain characteristics.

# Constructor IntegratedOpenEvolve

IntegratedOpenEvolve(
  domain_factory: typing.Callable[[], skdecide.domains.Domain],
initial_program_path: typing.Optional[str] = None,
initial_program_include_rollout: = True,
evaluator_path: typing.Optional[str] = None,
evaluator_domain_factories: typing.Optional[list[typing.Callable[[], skdecide.domains.Domain]]] = None,
evaluator_rollout_num_episodes: = 3,
evaluator_rollout_max_steps: typing.Union[int, typing.Callable[[skdecide.domains.Domain], int]] = 100,
evaluator_rollout_normalize: = True,
evaluator_timeout: = 60,
evaluator_enforce_using_public_api: = False,
config: typing.Union[str, pathlib.Path, openevolve.config.Config, NoneType] = None,
output_dir: typing.Optional[str] = None,
target_score: typing.Optional[float] = None,
prompt_add_blockevolve_instruction: = True,
prompt_add_public_api_instruction: = True,
prompt_include_domain_module: = False,
prompt_include_public_api: = True,
prompt_include_public_api_params: typing.Optional[skdecide.hub.solver.openevolve.api_extraction.ApiExtractionParams] = None,
prompt_update_function: typing.Optional[typing.Callable[[str], str]] = None,
nb_iterations: typing.Optional[int] = None,
**kwargs: typing.Any
)

# Parameters

  • domain_factory: domain factory on which the solver works
  • initial_program_path: path to the initial program to evolve. Default to a generated one with a random sampler of actions available in domain_factory(). If given, other initial program parameters are ignored.
  • initial_program_include_rollout: whether to add an example of rollout at the end of the initial program or not.
  • evaluator_path: path to the evaluation script used by openevolve. Default to a generated one with rollouts on evaluator_domain_factories. If given, other evaluator parameters are ignored. evaluator_domain_factories: list of domain factories on which a rollout is applied to generate the evaluator. Default to [domain_factory]. evaluator_rollout_num_episodes: number of episodes to perform on each domain evaluator_rollout_max_steps: max steps for each episode. Either an integer or a function mapping a domain to an integer, usually in relation with the domain size. evaluator_rollout_normalize: whether normalizing the cost of a rollout by the evaluator_rollout_max_steps (i.e. potentially the size of the domain) evaluator_timeout: time (in s) allowed for the evaluation of an evolved program. evaluator_enforce_using_public_api: if True, the evaluator domains will be wrapped in a proxy that allows only calling their public api (else raising an AttributeError with a message telling not using the private attributes). The proxy class still derives from the relevant characteristics found in skdecide.builder.domain so that checks isinstance() based are still working. planner_kwargs_factory: function generating the kwargs to instanciate the evolved planner from the domain planner_obs_converter: function converting domain observation into args needed by the evolved planner sample_action method (default to identity) planner_action_converter: function converting the action returned by the evolved planner into an actual action of the domain (default to identity) config: config yaml file to be used by openevolve (or openevolve.Config object). Potentially contains the prompt header used to describe the domain to work on. output_dir: output directory for openevolve evolution target_score: target score used by openevolve prompt_add_blockevolve_instruction: if True, add an instruction at the end of the system prompt found in the config to restrict changes between the # EVOLVE-BLOCK-START and # EVOLVE-BLOCK-END token. prompt_add_public_api_instruction: if True, add an instruction in prompt to use only the public api of the domain prompt_include_domain_module: if True, include domain class module code in the prompt prompt_include_public_api: if True, include the public api of the domain class in the prompt prompt_include_public_api_params: parameters for public api extraction prompt_update_function: callable to apply on the system prompt included in the config to update it nb_iterations: override number of iterations found in config kwargs:

# check_domain Solver

check_domain(
  domain: Domain
) -> bool

Check whether a domain is compliant with this solver type.

By default, Solver.check_domain() provides some boilerplate code and internally calls Solver._check_domain_additional() (which returns True by default but can be overridden to define specific checks in addition to the "domain requirements"). The boilerplate code automatically checks whether all domain requirements are met.

# Parameters

  • domain: The domain to check.

# Returns

True if the domain is compliant with the solver type (False otherwise).

# complete_with_default_hyperparameters Hyperparametrizable

complete_with_default_hyperparameters(
  kwargs: dict[str, Any],
names: Optional[list[str]] = None
)

Add missing hyperparameters to kwargs by using default values

Args: kwargs: keyword arguments to complete (e.g. for __init__, init_model, or solve) names: names of the hyperparameters to add if missing. By default, all available hyperparameters.

Returns: a new dictionary, completion of kwargs

# copy_and_update_hyperparameters Hyperparametrizable

copy_and_update_hyperparameters(
  names: Optional[list[str]] = None,
**kwargs_by_name: dict[str, Any]
) -> list[Hyperparameter]

Copy hyperparameters definition of this class and update them with specified kwargs.

This is useful to define hyperparameters for a child class for which only choices of the hyperparameter change for instance.

Args: names: names of hyperparameters to copy. Default to all. **kwargs_by_name: for each hyperparameter specified by its name, the attributes to update. If a given hyperparameter name is not specified, the hyperparameter is copied without further update.

Returns:

# evaluate_program_code _BaseOpenEvolve

evaluate_program_code(
  self,
code:
) ->

Evaluate the program code as openevolve does during evolution.

# Parameters

  • code: code of the program to evaluate

# Returns

evaluation result computed by the opensolve controller using the underlying evaluator file

# get_best_program_code _BaseOpenEvolve

get_best_program_code(
  self
) ->

Get best program code found so far.

# Returns

# get_default_hyperparameters Hyperparametrizable

get_default_hyperparameters(
  names: Optional[list[str]] = None
) -> dict[str, Any]

Get hyperparameters default values.

Args: names: names of the hyperparameters to choose. By default, all available hyperparameters will be suggested.

Returns: a mapping between hyperparameter's name_in_kwargs and its default value (None if not specified)

# get_domain_requirements Solver

get_domain_requirements(
) -> list[type]

Get domain requirements for this solver class to be applicable.

Domain requirements are classes from the skdecide.builders.domain package that the domain needs to inherit from.

# Returns

A list of classes to inherit from.

# get_hyperparameter Hyperparametrizable

get_hyperparameter(
  name: str
) -> Hyperparameter

Get hyperparameter from given name.

# get_hyperparameters_by_name Hyperparametrizable

get_hyperparameters_by_name(
) -> dict[str, Hyperparameter]

Mapping from name to corresponding hyperparameter.

# get_hyperparameters_names Hyperparametrizable

get_hyperparameters_names(
) -> list[str]

List of hyperparameters names.

# is_policy_defined_for Policies

is_policy_defined_for(
  self,
observation: StrDict[D.T_observation]
) -> bool

Check whether the solver's current policy is defined for the given observation.

# Parameters

  • observation: The observation to consider.

# Returns

True if the policy is defined for the given observation memory (False otherwise).

# load Restorable

load(
  self,
path: str
) -> None

Restore the solver state from given path.

# Parameters

  • path: The path where the solver state was saved.

# reset Solver

reset(
  self
) -> None

Reset whatever is needed on this solver before running a new episode.

This function does nothing by default but can be overridden if needed (e.g. to reset the hidden state of a LSTM policy network, which carries information about past observations seen in the previous episode).

# sample_action Policies

sample_action(
  self,
observation: StrDict[D.T_observation],
domain: Optional[Domain] = None
) -> StrDict[list[D.T_event]]

Sample an action for the given observation (from the solver's current policy).

# Parameters

  • observation: The observation for which an action must be sampled.
  • domain: the domain source of the observation. Typically used to get current applicable actions or action mask.

# Returns

The sampled action.

# sample_prompt _BaseOpenEvolve

sample_prompt(
  self
) -> dict[str, str]

Sample a prompt for LLM as done during openevolve evolution with current settings.

# Returns

a dictionary

  • system -> system prompt
  • user -> user prompt

# save Restorable

save(
  self,
path: str
) -> None

Save the solver state to given path.

# Parameters

  • path: The path to store the saved state.

# solve FromInitialState

solve(
  self
) -> None

Run the solving process.

TIP

The nature of the solutions produced here depends on other solver's characteristics like policy and assessibility.

# suggest_hyperparameter_with_optuna Hyperparametrizable

suggest_hyperparameter_with_optuna(
  trial: optuna.trial.Trial,
name: str,
prefix: str,
**kwargs
) -> Any

Suggest hyperparameter value during an Optuna trial.

This can be used during Optuna hyperparameters tuning.

Args: trial: optuna trial during hyperparameters tuning name: name of the hyperparameter to choose prefix: prefix to add to optuna corresponding parameter name (useful for disambiguating hyperparameters from subsolvers in case of meta-solvers) **kwargs: options for optuna hyperparameter suggestions

Returns:

kwargs can be used to pass relevant arguments to

  • trial.suggest_float()
  • trial.suggest_int()
  • trial.suggest_categorical()

For instance it can

  • add a low/high value if not existing for the hyperparameter or override it to narrow the search. (for float or int hyperparameters)
  • add a step or log argument (for float or int hyperparameters, see optuna.trial.Trial.suggest_float())
  • override choices for categorical or enum parameters to narrow the search

# suggest_hyperparameters_with_optuna Hyperparametrizable

suggest_hyperparameters_with_optuna(
  trial: optuna.trial.Trial,
names: Optional[list[str]] = None,
kwargs_by_name: Optional[dict[str, dict[str, Any]]] = None,
fixed_hyperparameters: Optional[dict[str, Any]] = None,
prefix: str
) -> dict[str, Any]

Suggest hyperparameters values during an Optuna trial.

Args: trial: optuna trial during hyperparameters tuning names: names of the hyperparameters to choose. By default, all available hyperparameters will be suggested. If fixed_hyperparameters is provided, the corresponding names are removed from names. kwargs_by_name: options for optuna hyperparameter suggestions, by hyperparameter name fixed_hyperparameters: values of fixed hyperparameters, useful for suggesting subbrick hyperparameters, if the subbrick class is not suggested by this method, but already fixed. Will be added to the suggested hyperparameters. prefix: prefix to add to optuna corresponding parameters (useful for disambiguating hyperparameters from subsolvers in case of meta-solvers)

Returns: mapping between the hyperparameter name and its suggested value. If the hyperparameter has an attribute name_in_kwargs, this is used as the key in the mapping instead of the actual hyperparameter name. the mapping is updated with fixed_hyperparameters.

kwargs_by_name[some_name] will be passed as **kwargs to suggest_hyperparameter_with_optuna(name=some_name)

# _build_planner_from_loaded_cls _BaseOpenEvolve

_build_planner_from_loaded_cls(
  self,
evolved_planner_cls: type[skdecide.hub.solver.openevolve.openevolve_wrapper.Planner]
) ->

Build the planner.

Use the domain as only argument (according to assumptions made on the program).

# _check_domain_additional Solver

_check_domain_additional(
  domain: Domain
) -> bool

Check whether the given domain is compliant with the specific requirements of this solver type (i.e. the ones in addition to "domain requirements").

This is a helper function called by default from Solver.check_domain(). It focuses on specific checks, as opposed to taking also into account the domain requirements for the latter.

# Parameters

  • domain: The domain to check.

# Returns

True if the domain is compliant with the specific requirements of this solver type (False otherwise).

# _cleanup Solver

_cleanup(
  self
)

Runs cleanup code here, or code to be executed at the exit of a 'with' context statement.

# _convert_action_from_planner _BaseOpenEvolve

_convert_action_from_planner(
  self,
pre_action: typing.Any
) -> skdecide.domains.T_event

Conversion of planner action.

By default, identity.

# _convert_applicable_actions_for_planner _BaseOpenEvolve

_convert_applicable_actions_for_planner(
  self,
applicable_actions: skdecide.core.Space[skdecide.domains.T_event]
) -> typing.Any

Convert into planner actions format.

By default, identity.

# _convert_obs_for_planner _BaseOpenEvolve

_convert_obs_for_planner(
  self,
observation: skdecide.domains.T_observation
) -> typing.Any

Convert into planner observation format.

By default, identity.

# _initialize Solver

_initialize(
  self
)

Runs long-lasting initialization code here.

# _is_policy_defined_for Policies

_is_policy_defined_for(
  self,
observation: skdecide.domains.T_observation
) ->

Check whether the solver's current policy is defined for the given observation.

# Parameters

  • observation: The observation to consider.

# Returns

True if the policy is defined for the given observation memory (False otherwise).

# _load Restorable

_load(
  self,
path:
)

Restore the solver state from given path.

Load the given checkpoint directory into the openevolve database.

# Parameters

  • path: The path where the solver state was saved.

# _reset Solver

_reset(
  self
) -> None

Reset whatever is needed on this solver before running a new episode.

This function does nothing by default but can be overridden if needed (e.g. to reset the hidden state of a LSTM policy network, which carries information about past observations seen in the previous episode).

# _sample_action Policies

_sample_action(
  self,
observation: skdecide.domains.T_observation,
domain: typing.Optional[skdecide.domains.Domain] = None
) -> skdecide.domains.T_event

Sample an action for the given observation (from the solver's current policy).

# Parameters

  • observation: The observation for which an action must be sampled.
  • domain: the domain source of the observation. Typically used to get current applicable actions or action mask. NB: Be careful that the domain has not been autocast, so may not respect the T_domain specs.

# Returns

The sampled action.

# _save Restorable

_save(
  self,
path:
)

Save the solver state to given path.

Save the openevolve database to the given path (as it does for checkpoint)

# Parameters

  • path: The path to store the saved state. (Must be a directory path, potentially to be created)

# _solve FromInitialState

_solve(
  self
)

Run the solving process.

TIP

The nature of the solutions produced here depends on other solver's characteristics like policy and assessibility.