Source code for IO_Objects

from typing import Union
from abc import ABC, abstractmethod


[docs]class ReprMixin(ABC): """Adds a useful string representation to subclasses""" def __init__(self): self._to_repr = {} # TODO: replace all _to_repr[name] = attr lines with these shortcuts def _add_repr(self, name, attr=None, check=False): if attr is None: attr = name if (not check) or getattr(self, attr): self._to_repr[name] = attr def _add_reprs(self, names, check=False): for name in names: self._add_repr(name, check=check) def __repr__(self): attr_list = [f'{attr_name}={repr(getattr(self, attr))}' for attr_name, attr in self._to_repr.items()] return f'{self.__class__.__name__}({", ".join(attr_list)})'
[docs]class IOBase(ReprMixin, ABC): """IOBase(name) Base class for inputs, objectives and constraints. :param str name: For generating DataFrame column titles.""" def __init__(self, name=''): super().__init__() self._name = name if name: self._to_repr['name'] = '_name' @property def name(self): return self._name or self._default_name @name.setter def name(self, value): self._name = value @property def _default_name(self): return ''
def get_name(x: Union[str, int, IOBase]): if isinstance(x, str): return x if isinstance(x, int): return str(x) return x.name
[docs]class Descriptor(ReprMixin, ABC): def __init__(self, **kwargs): super().__init__(**kwargs) self.platypus_type = NotImplemented
[docs] @abstractmethod def validate(self, value) -> bool: """Checks if value is a valid value for this parameter. :param value: The value to check :return: True if the value is valid False otherwise """
# consider a pandas type to improve DataFrame generation
[docs] @abstractmethod def sample(self, value): """Takes a value in the range 0-1 and returns a valid value for this parameter :param value: """ pass
[docs]class AnyValue(Descriptor): """A descriptor that can take on any possible value. Intended to be used as a placeholder."""
[docs] def validate(self, value): return True
[docs] def sample(self, value): raise NotImplementedError
def __bool__(self): """Marks this as a 'missing' piece""" # ReprMixin will detect this as something to not include when checking return False
[docs]class Selector(ReprMixin, ABC): """Base Class for Selectors, which describe what attribute of the building is read or modified""" @abstractmethod def get(self, building): pass @abstractmethod def set(self, building, value): pass
[docs] def setup(self, building) -> None: """Modifies the building so that it is ready for this selector""" pass
[docs]class DummySelector(Selector): """A selector that does not modify the building. Intended to be used as a placeholder.""" def get(self, building): raise NotImplementedError def set(self, building, value): pass def __bool__(self): """Marks this as a 'missing' piece""" # ReprMixin will detect this as something to not include when checking return False
[docs]class Objective(IOBase): """Objective(name) Base class for objectives.""" def __call__(self, *args, **kwargs) -> float: """Return the objective's value on the instance represented by *args and **kwargs""" raise NotImplementedError