コード例 #1
0
    def discrete_outcomes(self,
                          n_max: int = None,
                          astype: Type['Outcome'] = dict) -> List['Outcome']:
        """
        A discrete set of outcomes that spans the outcome space

        Args:
            n_max: The maximum number of outcomes to return. If None, all outcomes will be returned for discrete issues
            and *100* if any of the issues was continuous
            astype: A type to cast the resulting outcomes to.

        Returns:

            List[Outcome]: List of `n` or less outcomes

        """
        if self.outcomes is not None:
            return self.outcomes
        if self.__discrete_outcomes is None:
            if all(issue.is_discrete() for issue in self.issues):
                self.__discrete_outcomes = Issue.sample(
                    issues=self.issues,
                    n_outcomes=n_max,
                    astype=astype,
                    with_replacement=False,
                    fail_if_not_enough=False)
            else:
                self.__discrete_outcomes = Issue.sample(
                    issues=self.issues,
                    n_outcomes=n_max if n_max is not None else 100,
                    astype=astype,
                    with_replacement=False,
                    fail_if_not_enough=False)
        return self.__discrete_outcomes
コード例 #2
0
 def random(
     cls,
     issues: List["Issue"],
     reserved_value=(0.0, 1.0),
     normalized=True,
     max_n_outcomes: int = 10000,
 ):
     outcomes = (Issue.enumerate(issues)
                 if Issue.num_outcomes(issues) <= max_n_outcomes else
                 Issue.sample(issues,
                              max_n_outcomes,
                              with_replacement=False,
                              fail_if_not_enough=False))
     return UtilityFunction.generate_random(1, outcomes)[0]
コード例 #3
0
ファイル: mechanisms.py プロジェクト: egerson1996/negmas
    def random_outcomes(
        self, n: int = 1, astype: Type[Outcome] = None
    ) -> List["Outcome"]:
        """Returns random offers.

        Args:
              n: Number of outcomes to generate
              astype: The type to use for the generated outcomes

        Returns:
              A list of outcomes (in the type specified using `astype`) of at most n outcomes.

        Remarks:

                - If the number of outcomes `n` cannot be satisfied, a smaller number will be returned
                - Sampling is done without replacement (i.e. returned outcomes are unique).

        """
        if astype is None:
            astype = self.ami.outcome_type
        if self.ami.issues is None or len(self.ami.issues) == 0:
            raise ValueError("I do not have any issues to generate offers from")
        return Issue.sample(
            issues=self.issues,
            n_outcomes=n,
            astype=astype,
            with_replacement=False,
            fail_if_not_enough=False,
        )
コード例 #4
0
    def equiprobable_thresholds(cls,
                                n: int,
                                ufun: "UtilityFunction",
                                issues: List[Issue],
                                n_samples: int = 1000) -> List[float]:
        """
        Generates thresholds for the n given levels where levels are equally likely approximately

        Args:
            n: Number of scale levels (one side)
            ufun: The utility function to use
            issues: The issues to generate the thresholds for
            n_samples: The number of samples to use during the process

        """
        samples = list(
            Issue.sample(issues,
                         n_samples,
                         with_replacement=False,
                         fail_if_not_enough=False))
        n_samples = len(samples)
        diffs = []
        for i, first in enumerate(samples):
            n_diffs = min(10, n_samples - i - 1)
            for second in sample(samples[i + 1:], k=n_diffs):
                diffs.append(abs(ufun.compare_real(first, second)))
        diffs = np.array(diffs)
        hist, edges = np.histogram(diffs, bins=n + 1)
        return edges[1:-1].tolist()
コード例 #5
0
    def random(cls,
               issues: List["Issue"],
               reserved_value=(0.0, 1.0),
               normalized=True,
               **kwargs):
        from negmas.utilities.ops import normalize

        reserved_value = make_range(reserved_value)
        n_issues = len(issues)
        r = reserved_value if reserved_value is not None else random.random()
        s = 0.0
        weights = [2 * (random.random() - 0.5) for _ in range(n_issues)]
        biases = [2 * (random.random() - 0.5) for _ in range(n_issues)]
        ufun = cls(
            weights=weights,
            biases=biases,
            reserved_value=random.random() *
            (reserved_value[1] - reserved_value[0]) + reserved_value[0],
        )
        if normalized:
            return normalize(
                ufun,
                outcomes=Issue.discretize_and_enumerate(issues,
                                                        n_discretization=10,
                                                        max_n_outcomes=10000),
            )
        return ufun
コード例 #6
0
def test_imap_issues():
    issues = [Issue(5, f"i{i}") for i in range(5)]
    m = MyMechanism(issues=issues)
    assert len(m.ami.imap) == 10
    for i in range(5):
        assert m.ami.imap[i] == f"i{i}"
        assert m.ami.imap[f"i{i}"] == i
コード例 #7
0
def test_ufun_range_linear(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 = LinearUtilityFunction(weights=rs, reserved_value=0.0)
    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)
コード例 #8
0
 def _unorm(self, u: UtilityFunction, mn, mx):
     if not isinstance(u, LinearUtilityAggregationFunction) and not isinstance(
         u, LinearUtilityFunction
     ):
         return normalize(u, outcomes=Issue.enumerate(issues, max_n_outcomes=1000))
     # _, mx = self._urange(u, issues)
     if mx < 0:
         return None
     u.weights = {k: _ / mx for k, _ in u.weights.items()}
     return u
コード例 #9
0
 def random_outcomes(self,
                     n: int = 1,
                     astype: Type[Outcome] = dict) -> List['Outcome']:
     """Returns random offers"""
     if self.info.issues is None or len(self.info.issues) == 0:
         raise ValueError(
             'I do not have any issues to generate offers from')
     return Issue.sample(issues=self.issues,
                         n_outcomes=n,
                         astype=astype,
                         with_replacement=False,
                         fail_if_not_enough=False)
コード例 #10
0
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)
コード例 #11
0
ファイル: test_inout.py プロジェクト: yasserfarouk/negmas
def test_reading_writing_linear_ufun(tmp_path):
    from negmas.utilities import LinearUtilityAggregationFunction, UtilityFunction
    from negmas.outcomes import Issue

    base_folder = pkg_resources.resource_filename(
        "negmas", resource_name="tests/data/Laptop")
    _, agent_info, issues = load_genius_domain_from_folder(
        base_folder,
        keep_issue_names=True,
        keep_value_names=True,
    )
    ufuns = [_["ufun"] for _ in agent_info]
    for ufun in ufuns:
        assert isinstance(ufun, LinearUtilityAggregationFunction)
        dst = tmp_path / "tmp.xml"
        print(dst)
        UtilityFunction.to_genius(ufun, issues=issues, file_name=dst)
        ufun2, _ = UtilityFunction.from_genius(dst)
        assert isinstance(ufun2, LinearUtilityAggregationFunction)
        for outcome in Issue.enumerate(issues):
            assert abs(ufun2(outcome) - ufun(outcome)) < 1e-3
コード例 #12
0
ファイル: ops.py プロジェクト: yasserfarouk/negmas
def pareto_frontier(
    ufuns: Iterable[UtilityFunction],
    outcomes: Iterable[Outcome] = None,
    issues: Iterable[Issue] = None,
    n_discretization: Optional[int] = 10,
    sort_by_welfare=False,
) -> Tuple[List[Tuple[float]], List[int]]:
    """Finds all pareto-optimal outcomes in the list

    Args:

        ufuns: The utility functions
        outcomes: the outcomes to be checked. If None then all possible outcomes from the issues will be checked
        issues: The set of issues (only used when outcomes is None)
        n_discretization: The number of items to discretize each real-dimension into
        sort_by_welfare: If True, the resutls are sorted descendingly by total welfare

    Returns:
        Two lists of the same length. First list gives the utilities at pareto frontier points and second list gives their indices

    """

    ufuns = list(ufuns)
    if issues:
        issues = list(issues)
    if outcomes:
        outcomes = list(outcomes)

    # calculate all candidate outcomes
    if outcomes is None:
        if issues is None:
            return [], []
        outcomes = Issue.discretize_and_enumerate(issues, n_discretization)
        # outcomes = itertools.product(
        #     *[issue.alli(n=n_discretization) for issue in issues]
        # )
    points = [[ufun(outcome) for ufun in ufuns] for outcome in outcomes]
    return _pareto_frontier(points, sort_by_welfare=sort_by_welfare)
コード例 #13
0
def test_inverse_genius_domain(normalize):
    issues, _ = Issue.from_xml_str(
        open(
            pkg_resources.resource_filename(
                "negmas", resource_name="tests/data/Laptop/Laptop-C-domain.xml"
            ),
            "r",
        ).read(),
    )
    u, _ = UtilityFunction.from_xml_str(
        open(
            pkg_resources.resource_filename(
                "negmas", resource_name="tests/data/Laptop/Laptop-C-prof1.xml"
            ),
            "r",
        ).read(),
        force_single_issue=False,
        normalize_utility=normalize,
    )
    u.init_inverse(issues=issues)
    for i in range(100):
        v = u(u.inverse(i / 100.0, eps=(0.001, 0.1), assume_normalized=normalize))
        assert v-1e-3 <= v <= v+0.1
コード例 #14
0
    def random(cls,
               issues: List["Issue"],
               reserved_value=(0.0, 1.0),
               normalized=True,
               **kwargs):
        from negmas.utilities.ops import normalize

        reserved_value = make_range(reserved_value)

        n_issues = len(issues)
        # r = reserved_value if reserved_value is not None else random.random()
        s = 0.0
        weights = dict(
            zip([_.name for _ in issues],
                [random.random() for _ in range(n_issues)]))
        s = sum(_ for _ in weights.values())
        if s:
            for k, v in weights.items():
                weights[k] = v / s
        issue_utilities = dict(
            zip([_.name for _ in issues],
                [random_mapping(issue) for issue in issues]))

        ufun = cls(
            weights=weights,
            issue_utilities=issue_utilities,
            reserved_value=random.random() *
            (reserved_value[1] - reserved_value[0]) + reserved_value[0],
            **kwargs,
        )
        if normalized:
            return normalize(
                ufun,
                outcomes=Issue.discretize_and_enumerate(issues,
                                                        max_n_outcomes=5000),
            )
コード例 #15
0
    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 = {}
コード例 #16
0
ファイル: mechanisms.py プロジェクト: yasserfarouk/negmas
    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,
        )
コード例 #17
0
ファイル: fixtures.py プロジェクト: eareyan/negmas
def hamlet():
    return Issue(['val {}'.format(_) for _ in range(5)], name='THE problem')
コード例 #18
0
ファイル: fixtures.py プロジェクト: eareyan/negmas
def uissue():
    return Issue(['val {}'.format(_) for _ in range(5)])
コード例 #19
0
ファイル: fixtures.py プロジェクト: eareyan/negmas
def dissue():
    return Issue(10, name='d')
コード例 #20
0
def uissue():
    return Issue(["val {}".format(_) for _ in range(5)])
コード例 #21
0
ファイル: fixtures.py プロジェクト: eareyan/negmas
def sissue():
    return Issue(['val {}'.format(_) for _ in range(5)], name='s')
コード例 #22
0
ファイル: fixtures.py プロジェクト: eareyan/negmas
def bissue():
    return Issue(['be', 'not b'], name='binary')
コード例 #23
0
def bissue():
    return Issue(["be", "not b"], name="binary")
コード例 #24
0
def int_issues():
    return Issue.generate([5], [10])
コード例 #25
0
def sissue():
    return Issue(["val {}".format(_) for _ in range(5)], name="s")
コード例 #26
0
def cissue():
    return Issue((0.0, 1.0), name="c")
コード例 #27
0
ファイル: mechanisms.py プロジェクト: egerson1996/negmas
    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 = {}
コード例 #28
0
def dissue():
    return Issue(10, name="d")
コード例 #29
0
def hamlet():
    return Issue(["val {}".format(_) for _ in range(5)], name="THE problem")