Source code for rtac.ac_functionalities.config_gens

"""This module contains functions for configuration generation."""

from abc import ABC, abstractmethod
import argparse
import sys
import uuid
import random
import math
import numpy as np
from rtac.ac_functionalities.rtac_data import (
    Configuration,
    ParamType,
    ValType,
    Distribution,
    DiscreteParameter,
    ContinuousParameter,
    CategoricalParameter,
    BinaryParameter,
    Generator
)


[docs]class AbstractConfigGen(ABC): """ Abstract class for generation of configurations. Parameters ---------- scenario : argparse.Namespace Namespace containing all settings for the RTAC. """ @abstractmethod def __init__(self, scenario: argparse.Namespace): """Initialize configuration generation class."""
[docs] @abstractmethod def generate(self) -> Configuration: """ Generates and returns configuration. Returns ------- Configuration Newly generated Configuration. """
[docs]class DefaultConfigGen(AbstractConfigGen): """ Generates default Configurationa. Parameters ---------- scenario : argparse.Namespace Namespace containing all settings for the RTAC. """ def __init__(self, scenario: argparse.Namespace): """Initialize default configuration class.""" self.scenario = scenario self.config_space = scenario.config_space self.default_config = {}
[docs] def generate(self, tourn) -> Configuration: """ Generates and stores default Configuration. Parameters ---------- tourn : int Number of tournament since RTAC initialization. Returns ------- Configuration Default Configuration. """ if not self.default_config: if '.json' in f'{self.scenario.param_file}': default_config = {} for param, definition in self.config_space.items(): if definition.default is not None: default_config[param] = definition.default else: # If default not defined, define naively if definition.paramtype in \ (ParamType.discrete, ParamType.continuous): default_config[param] = \ (definition.maxval - definition.minval) / 2 else: default_config[param] = definition.values[0] elif '.pcs' in f'{self.scenario.param_file}': default_config = \ dict( self.scenario.config_space.get_default_configuration()) self.default_config = \ Configuration( uuid.uuid4().hex, default_config, [], Generator.default, tourn ) return self.default_config
[docs]class RandomConfigGen(AbstractConfigGen): """ Generates random Configuration. Parameters ---------- scenario : argparse.Namespace Namespace containing all settings for the RTAC. """ def __init__(self, scenario: argparse.Namespace): """Initialize random configuration class.""" self.scenario = scenario self.config_space = scenario.config_space
[docs] def generate(self, tourn) -> Configuration: """ Generates random Configuration. Parameters ---------- tourn : int Number of tournament since RTAC initialization. Returns ------- Configuration Randomly generated Configuration. """ if '.json' in f'{self.scenario.param_file}': random_config = {} for param_name, parameter in self.config_space.items(): if isinstance(parameter, BinaryParameter): if isinstance(parameter.valtype, ValType.int): random_config[param_name] = \ random.choice([0, 1]) elif isinstance(parameter.valtype, ValType.str): random_config[param_name] = \ random.choice(parameter.values) elif isinstance(parameter, CategoricalParameter): if parameter.valtype is ValType.int: if parameter.values: random_config[param_name] = \ random.choice(parameter.values) else: random_config[param_name] = \ random.choice(list(range( parameter.minval, parameter.maxval))) elif parameter.valtype is ValType.str: if not parameter.flag: random_config[param_name] = \ random.choice(parameter.values) else: random_config[random.choice(parameter.values)] = '' elif isinstance(parameter, (ContinuousParameter, DiscreteParameter)): minval = parameter.minval maxval = parameter.maxval if parameter.distribution is Distribution.uniform: random_config[param_name] = \ random.uniform(minval, maxval) elif parameter.distribution is Distribution.log: tiny_float = sys.float_info.min probabpos = np.float64(round(parameter.probabpos, 3)) if parameter.includezero: probabzero = \ np.float64( round(parameter.probabilityzero, 3)) probabneg = \ np.float64( round(1 - probabpos - probabzero, 3)) else: probabneg = np.float64(round(1 - probabpos, 3)) values = [] weights = [] if parameter.splitbydefault and parameter.default != 0: split_high = math.log(parameter.default) split_low = \ math.log(parameter.default - tiny_float) else: if parameter.logonpos: split_high = tiny_float else: split_high = minval if parameter.logonneg: split_low = -tiny_float else: split_low = maxval if parameter.logonpos: logmaxval = math.log(maxval) values.append( math.exp(np.random.uniform( split_high, logmaxval, size=1))) else: values.append(random.uniform(split_high, maxval)) weights.append(probabpos) if parameter.logonneg: if minval > 0: logminval = math.log(minval) values.append( math.exp(np.random.uniform( split_low, logminval, size=1))) elif minval == 0: logminval = math.log(tiny_float) values.append( math.exp(np.random.uniform( split_low, logminval, size=1))) elif minval < 0: logminval = math.log(-minval) values.append( -math.exp(np.random.uniform( split_low, -logminval, size=1)) - minval) else: values.append(random.uniform(minval, split_low)) weights.append(probabneg) if parameter.includezero: values.append(0) weights.append(probabzero) random_config[param_name] = \ np.random.choice(values, 1, p=weights)[0] if isinstance(parameter, DiscreteParameter): random_config[param_name] = \ int(round(random_config[param_name])) elif '.pcs' in f'{self.scenario.param_file}': random_config = \ dict(self.scenario.config_space.sample_configuration(1)) return Configuration( uuid.uuid4().hex, random_config, [], Generator.random, tourn )