Source code for negmas.outcomes.categorical_issue

from __future__ import annotations
import random
from typing import Any, Generator

from negmas.helpers import unique_name
from negmas.outcomes.base_issue import DiscreteIssue

__all__ = ["CategoricalIssue"]


[docs] class CategoricalIssue(DiscreteIssue): """ An `Issue` type representing discrete values that have no ordering or difference defined. """ def __init__(self, values, name=None) -> None: super().__init__(values, name) values = list(values) self._n_values = len(values) self._value_type = ( type(values[0]) if len({type(_) for _ in values if _ is not None}) == 1 else object ) if self.is_numeric(): self.min_value, self.max_value = min(values), max(values) @property def type(self) -> str: return "categorical" def _to_xml_str(self, indx): output = f' <issue etype="discrete" index="{indx + 1}" name="{self.name}" type="discrete" vtype="discrete">\n' for i, v in enumerate(self._values): output += f' <item index="{i + 1}" value="{v}" cost="0" description="{v}">\n </item>\n' output += " </issue>\n" return output
[docs] def is_continuous(self) -> bool: return False
[docs] def is_uncountable(self) -> bool: return False
@property def all(self) -> Generator[Any, None, None]: yield from self._values
[docs] def rand_invalid(self): # type: ignore """Pick a random *invalid* value""" if self.is_float(): return random.random() * self.max_value + self.max_value * 1.1 if self.is_integer(): return random.randint(self.max_value + 1, self.max_value * 2) if issubclass(self._value_type, tuple): return (random.randint(100, 200), unique_name("")) return unique_name("") + str(random.choice(self._values)) + unique_name("")