def outcome_index(self, outcome) -> Optional[int]: """Returns the index of the outcome if that was possible""" if self.__outcomes is None: return None if self.__outcome_index is not None: return self.__outcome_index[outcome_as_tuple(outcome)] return self.__outcomes.index(outcome)
def test_ufun_range_general(n_issues): issues = [Issue(values=(0.0, 1.0), name=f"i{i}") for i in range(n_issues)] rs = [(i + 1.0) * random.random() for i in range(n_issues)] ufun = MappingUtilityFunction( mapping=lambda x: sum(r * v for r, v in zip(rs, outcome_as_tuple(x))), outcome_type=tuple, ) assert ufun([0.0] * n_issues) == 0.0 assert ufun([1.0] * n_issues) == sum(rs) rng = utility_range(ufun, issues=issues) assert rng[0] >= 0.0 assert rng[1] <= sum(rs)
def eval(self, offer: Optional[Outcome]) -> Optional[UtilityValue]: # noinspection PyBroadException if offer is None: return self.reserved_value try: if isinstance(offer, dict) and isinstance(self.mapping, dict): m = gmap(self.mapping, outcome_as_tuple(offer)) else: m = gmap(self.mapping, offer) except Exception: return self.default return m
def eval(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]: if offer is None: return self.reserved_value # offer = outcome_for(offer, self.ami) if self.ami is not None else offer u = ExactUtilityValue(0.0) if isinstance(self.weights, dict): if isinstance(offer, dict): for k, w in self.weights.items(): u += w * (iget(offer, k, self.missing_value) + self.biases.get(k, 0)) return u else: if self.ami is not None: newoffer = dict() for i, v in enumerate(offer): newoffer[self.ami.issues[i].name] = v elif self.issue_names is not None: newoffer = dict() for i, v in enumerate(offer): newoffer[self.issue_names[i]] = v elif self.issues is not None: newoffer = dict() for i, v in enumerate(offer): newoffer[self.issues[i].name] = v else: raise ValueError( f"Cannot find issue names but weights are given as a dict." ) for k, w in self.weights.items(): u += w * (iget(offer, k, self.missing_value) + self.biases.get(k, 0)) return u offer = outcome_as_tuple(offer) return sum(w * (v + b) for w, b, v in zip(self.weights, self.biases, offer))
def __init__( self, issues: List["Issue"] = None, outcomes: Union[int, List["Outcome"]] = None, n_steps: int = None, time_limit: float = None, step_time_limit: float = None, max_n_agents: int = None, dynamic_entry=False, cache_outcomes=True, max_n_outcomes: int = 1000000, keep_issue_names=None, annotation: Optional[Dict[str, Any]] = None, state_factory=MechanismState, enable_callbacks=False, checkpoint_every: int = 1, checkpoint_folder: Optional[Union[str, Path]] = None, checkpoint_filename: str = None, extra_checkpoint_info: Dict[str, Any] = None, single_checkpoint: bool = True, exist_ok: bool = True, name=None, outcome_type=tuple, ): """ Args: issues: List of issues to use (optional as you can pass `outcomes`) outcomes: List of outcomes (optional as you can pass `issues`). If an int then it is the number of outcomes n_steps: Number of rounds allowed (None means infinity) time_limit: Number of real seconds allowed (None means infinity) max_n_agents: Maximum allowed number of agents dynamic_entry: Allow agents to enter/leave negotiations between rounds cache_outcomes: If true, a list of all possible outcomes will be cached max_n_outcomes: The maximum allowed number of outcomes in the cached set keep_issue_names: DEPRICATED. Use `outcome_type` instead. If True, dicts with issue names will be used for outcomes otherwise tuples annotation: Arbitrary annotation state_factory: A callable that receives an arbitrary set of key-value pairs and return a MechanismState descendant object checkpoint_every: The number of steps to checkpoint after. Set to <= 0 to disable checkpoint_folder: The folder to save checkpoints into. Set to None to disable checkpoint_filename: The base filename to use for checkpoints (multiple checkpoints will be prefixed with step number). single_checkpoint: If true, only the most recent checkpoint will be saved. extra_checkpoint_info: Any extra information to save with the checkpoint in the corresponding json file as a dictionary with string keys exist_ok: IF true, checkpoints override existing checkpoints with the same filename. name: Name of the mechanism session. Should be unique. If not given, it will be generated. outcome_type: The type used for representing outcomes. Can be tuple, dict or any `OutcomeType` """ super().__init__(name=name) CheckpointMixin.checkpoint_init( self, step_attrib="_step", every=checkpoint_every, folder=checkpoint_folder, filename=checkpoint_filename, info=extra_checkpoint_info, exist_ok=exist_ok, single=single_checkpoint, ) time_limit = time_limit if time_limit is not None else float("inf") step_time_limit = ( step_time_limit if step_time_limit is not None else float("inf") ) if keep_issue_names is not None: warnings.warn( "keep_issue_names is depricated. Use outcome_type instead.\n" "keep_issue_names=True <--> outcome_type=dict\n" "keep_issue_names=False <--> outcome_type=tuple\n", DeprecationWarning, ) outcome_type = dict if keep_issue_names else tuple keep_issue_names = not issubclass(outcome_type, tuple) # parameters fixed for all runs if issues is None: if outcomes is None: __issues = [] outcomes = [] else: if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] else: outcomes = list(outcomes) n_issues = len(outcomes[0]) issues = [] issue_names = ikeys(outcomes[0]) for issue in range(n_issues): vals = list(set([_[issue] for _ in outcomes])) issues.append(vals) __issues = [ Issue(_, name=name_) for _, name_ in zip(issues, issue_names) ] else: __issues = list(issues) if outcomes is None and cache_outcomes: try: if len(__issues) == 0: outcomes = [] else: n_outcomes = 1 for issue in __issues: if issue.is_uncountable(): break n_outcomes *= issue.cardinality if n_outcomes > max_n_outcomes: break else: outcomes = enumerate_outcomes(__issues, astype=outcome_type) except ValueError: pass elif outcomes is not None: issue_names = [_.name for _ in issues] assert (not keep_issue_names and isinstance(outcomes[0], tuple)) or ( keep_issue_names and not isinstance(outcomes[0], tuple) ), ( f"Either you request to keep issue" f" names but use tuple outcomes or " f"vice versa (names={keep_issue_names}" f", type={type(outcomes[0])})" ) if keep_issue_names: for i, outcome in enumerate(outcomes): assert list(outcome.keys()) == issue_names else: for i, outcome in enumerate(outcomes): assert len(outcome) == len(issue_names) self.__outcomes = outcomes # we have now __issues is a List[Issue] and __outcomes is Optional[List[Outcome]] # create a couple of ways to access outcomes by indices effeciently self.outcome_indices = [] self.__outcome_index = None if self.__outcomes is not None and cache_outcomes: self.outcome_indices = range(len(self.__outcomes)) self.__outcome_index = dict( zip( (outcome_as_tuple(o) for o in self.__outcomes), range(len(self.__outcomes)), ) ) self.id = str(uuid.uuid4()) self.ami = AgentMechanismInterface( id=self.id, n_outcomes=None if outcomes is None else len(outcomes), issues=__issues, outcomes=self.__outcomes, time_limit=time_limit, n_steps=n_steps, step_time_limit=step_time_limit, dynamic_entry=dynamic_entry, max_n_agents=max_n_agents, annotation=annotation, outcome_type=dict if keep_issue_names else tuple, ) self.ami._mechanism = self self._history = [] # if self.ami.issues is not None: # self.ami.issues = tuple(self.ami.issues) # if self.ami.outcomes is not None: # self.ami.outcomes = tuple(self.ami.outcomes) self._state_factory = state_factory self._requirements = {} self._negotiators = [] self._negotiator_map: Dict[str, "SAONegotiator"] = dict() self._roles = [] self._start_time = None self._started = False self._step = 0 self._n_accepting_agents = 0 self._broken = False self._agreement = None self._timedout = False self._running = False self._error = False self._error_details = "" self._waiting = False self.__discrete_outcomes: List[Outcome] = None self._enable_callbacks = enable_callbacks self.agents_of_role = defaultdict(list) self.role_of_agent = {}
def __init__( self, issues: List["Issue"] = None, outcomes: Union[int, List["Outcome"]] = None, n_steps: int = None, time_limit: float = None, step_time_limit: float = None, negotiator_time_limit: float = None, max_n_agents: int = None, dynamic_entry=False, cache_outcomes=True, max_n_outcomes: int = 1000000, keep_issue_names=None, annotation: Optional[Dict[str, Any]] = None, state_factory=MechanismState, enable_callbacks=False, checkpoint_every: int = 1, checkpoint_folder: Optional[Union[str, Path]] = None, checkpoint_filename: str = None, extra_checkpoint_info: Dict[str, Any] = None, single_checkpoint: bool = True, exist_ok: bool = True, name=None, outcome_type=tuple, genius_port: int = DEFAULT_JAVA_PORT, id: str = None, ): super().__init__(name, id=id) CheckpointMixin.checkpoint_init( self, step_attrib="_step", every=checkpoint_every, folder=checkpoint_folder, filename=checkpoint_filename, info=extra_checkpoint_info, exist_ok=exist_ok, single=single_checkpoint, ) time_limit = time_limit if time_limit is not None else float("inf") step_time_limit = (step_time_limit if step_time_limit is not None else float("inf")) negotiator_time_limit = (negotiator_time_limit if negotiator_time_limit is not None else float("inf")) if keep_issue_names is not None: warnings.warn( "keep_issue_names is depricated. Use outcome_type instead.\n" "keep_issue_names=True <--> outcome_type=dict\n" "keep_issue_names=False <--> outcome_type=tuple\n", DeprecationWarning, ) outcome_type = dict if keep_issue_names else tuple keep_issue_names = not issubclass(outcome_type, tuple) # parameters fixed for all runs if issues is None: if outcomes is None: __issues = [] outcomes = [] else: if isinstance(outcomes, int): outcomes = [(_, ) for _ in range(outcomes)] else: outcomes = list(outcomes) n_issues = len(outcomes[0]) issues = [] issue_names = ikeys(outcomes[0]) for issue in range(n_issues): vals = list(set([_[issue] for _ in outcomes])) issues.append(vals) __issues = [ Issue(_, name=name_) for _, name_ in zip(issues, issue_names) ] else: __issues = list(issues) if outcomes is None and cache_outcomes: try: if len(__issues) == 0: outcomes = [] else: n_outcomes = 1 for issue in __issues: if issue.is_uncountable(): break n_outcomes *= issue.cardinality if n_outcomes > max_n_outcomes: break else: outcomes = enumerate_outcomes(__issues, astype=outcome_type) except ValueError: pass elif outcomes is not None: issue_names = [_.name for _ in issues] assert (not keep_issue_names and isinstance(outcomes[0], tuple)) or ( keep_issue_names and not isinstance(outcomes[0], tuple)), ( f"Either you request to keep issue" f" names but use tuple outcomes or " f"vice versa (names={keep_issue_names}" f", type={type(outcomes[0])})") if keep_issue_names: for outcome in outcomes: assert list(outcome.keys()) == issue_names else: for i, outcome in enumerate(outcomes): assert len(outcome) == len(issue_names) self.__outcomes = outcomes # we have now __issues is a List[Issue] and __outcomes is Optional[List[Outcome]] # create a couple of ways to access outcomes by indices effeciently self.outcome_indices = [] self.__outcome_index = None if self.__outcomes is not None and cache_outcomes: self.outcome_indices = range(len(self.__outcomes)) self.__outcome_index = dict( zip( (outcome_as_tuple(o) for o in self.__outcomes), range(len(self.__outcomes)), )) self.id = str(uuid.uuid4()) _imap = dict(zip((_.name for _ in __issues), range(len(__issues)))) _imap.update( dict(zip(range(len(__issues)), (_.name for _ in __issues)))) self.ami = AgentMechanismInterface( id=self.id, n_outcomes=None if outcomes is None else len(outcomes), issues=__issues, outcomes=self.__outcomes, time_limit=time_limit, n_steps=n_steps, step_time_limit=step_time_limit, negotiator_time_limit=negotiator_time_limit, dynamic_entry=dynamic_entry, max_n_agents=max_n_agents, annotation=annotation, outcome_type=dict if keep_issue_names else tuple, imap=_imap, ) self.ami._mechanism = self self._history: List[MechanismState] = [] self._stats: Dict[str, Any] = dict() self._stats["round_times"] = list() self._stats["times"] = defaultdict(float) self._stats["exceptions"] = defaultdict(list) # if self.ami.issues is not None: # self.ami.issues = tuple(self.ami.issues) # if self.ami.outcomes is not None: # self.ami.outcomes = tuple(self.ami.outcomes) self._state_factory = state_factory self._requirements = {} self._negotiators = [] self._negotiator_map: Dict[str, "SAONegotiator"] = dict() self._roles = [] self._start_time = None self._started = False self._step = 0 self._n_accepting_agents = 0 self._broken = False self._agreement = None self._timedout = False self._running = False self._error = False self._error_details = "" self._waiting = False self.__discrete_outcomes: List[Outcome] = None self._enable_callbacks = enable_callbacks self.agents_of_role = defaultdict(list) self.role_of_agent = {} # mechanisms do not differentiate between RANDOM_JAVA_PORT and ANY_JAVA_PORT. # if either is given as the genius_port, it will fix a port and all negotiators # that are not explicitly assigned to a port (by passing port>0 to them) will just # use that port. self.genius_port = genius_port if genius_port > 0 else get_free_tcp_port( ) self.params = dict( dynamic_entry=dynamic_entry, genius_port=genius_port, cache_outcomes=cache_outcomes, annotation=annotation, )