def xml(self, issues: List[Issue]) -> str: output = "" keys = list(ikeys(issues)) for i, k in enumerate(keys): issue_name = iget(issues, k).name output += f'<issue index="{i+1}" etype="discrete" type="discrete" vtype="discrete" name="{issue_name}">\n' vals = iget(issues, k).all for indx, u in enumerate(vals): output += ( f' <item index="{indx+1}" value="{u}" evaluation="{u}" />\n' ) output += "</issue>\n" for i, k in enumerate(keys): output += ( f'<weight index="{i+1}" value="{iget(self.weights, k)}">\n</weight>\n' ) return output
def __init__( self, issues: List['Issue'] = None, outcomes: Union[int, List['Outcome']] = None, n_steps: int = None, time_limit: float = None, max_n_agents: int = None, dynamic_entry=False, cache_outcomes=True, max_n_outcomes: int = 1000000, keep_issue_names=True, annotation: Optional[Dict[str, Any]] = None, state_factory=MechanismState, name=None, ): """ 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: 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 name: Name of the mechanism session. Should be unique. If not given, it will be generated. """ super().__init__(name=name) # parameters fixed for all runs if issues is None: if outcomes is None: raise ValueError( 'Not issues or outcomes are given to this mechanism. Cannot be constructed' ) 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_continuous(): break n_outcomes *= issue.cardinality() if n_outcomes > max_n_outcomes: break else: outcomes = enumerate_outcomes( __issues, keep_issue_names=keep_issue_names) except ValueError: pass elif outcomes is not None: issue_names = [_.name for _ in issues] assert (keep_issue_names and isinstance(outcomes[0], dict)) or \ (not keep_issue_names and 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) __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_index = lambda x: None self.outcome_indices = [] if __outcomes is not None and cache_outcomes: self.outcome_indices = range(len(__outcomes)) try: _outcome_index = dict(zip(__outcomes, self.outcome_indices)) self.outcome_index = lambda x: _outcome_index[x] except: self.outcome_index = lambda x: __outcomes.index(x) self.id = str(uuid.uuid4()) self.info = MechanismInfo( id=self.id, n_outcomes=None if outcomes is None else len(outcomes), issues=__issues, outcomes=__outcomes, time_limit=time_limit, n_steps=n_steps, dynamic_entry=dynamic_entry, max_n_agents=max_n_agents, annotation=annotation) self._history = [] # if self.info.issues is not None: # self.info.issues = tuple(self.info.issues) # if self.info.outcomes is not None: # self.info.outcomes = tuple(self.info.outcomes) self._state_factory = state_factory Mechanism.all[self.id] = self self._requirements = {} self._agents = [] 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.__discrete_outcomes: List[Outcome] = None 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, 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, )