Beispiel #1
0
    def eval(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]:
        if offer is None:
            return self.reserved_value
        if self.issue_utilities is None:
            raise ValueError(
                "No issue utilities were set. Call set_params() or use the constructor"
            )

        u = {}
        for k in ikeys(self.issue_utilities):
            v = iget(offer, k)
            u[k] = gmap(iget(self.issue_utilities, k), v)
        return self.f(u)
Beispiel #2
0
 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
Beispiel #3
0
    def eval(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]:
        if offer is None:
            return self.reserved_value
        u = ExactUtilityValue(0.0)
        for k in ikeys(self.issue_utilities):
            if isinstance(offer, tuple):
                v = iget(offer, self.issue_indices[k])
            else:
                v = iget(offer, k)
            current_utility = gmap(iget(self.issue_utilities, k), v)
            if current_utility is None:
                return None

            w = iget(self.weights, k)  # type: ignore
            if w is None:
                return None
            try:
                u += w * current_utility
            except FloatingPointError:
                continue
        return u
Beispiel #4
0
    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))
Beispiel #5
0
    def __init__(
        self,
        outcomes: Iterable["Outcome"],
        distributions: Iterable["UtilityDistribution"] = None,
        issue_names: Iterable[str] = None,
        name=None,
        reserved_value: UtilityValue = float("-inf"),
        ami: AgentMechanismInterface = None,
        outcome_type: Optional[Type] = None,
        id=None,
    ):
        super().__init__(
            name=name,
            outcome_type=outcome_type,
            reserved_value=reserved_value,
            ami=ami,
            id=id,
        )
        outcomes, distributions = (
            list(outcomes),
            (list(distributions) if distributions is not None else None),
        )
        if len(outcomes) < 1:
            raise ValueError(
                "IPUtilityFunction cannot be initialized with zero outcomes")
        self.tupelized = False

        self.n_issues = len(outcomes[0])
        if issue_names is None:
            self.issue_names = sorted(ikeys(outcomes[0]))
        else:
            self.issue_names = range(len(outcomes[0]))

        self.issue_keys = dict(zip(range(self.n_issues), self.issue_names))

        if not isinstance(outcomes[0], tuple):
            outcomes = [
                tuple(iget(_, key, None) for key in self.issue_names)
                for _ in outcomes
            ]
            self.tupelized = True
        if distributions is None:
            distributions = [
                UtilityDistribution(dtype="uniform", loc=0.0, scale=1.0)
                for _ in range(len(outcomes))
            ]
        self.distributions = dict(zip(outcomes, distributions))
Beispiel #6
0
    def xml(self, issues: List[Issue]) -> str:
        """Generates an XML string representing the utility function

        Args:
            issues:

        Examples:

            >>> from negmas.utilities.nonlinear import MappingUtilityFunction
            >>> issues = [Issue(values=10, name='i1'), Issue(values=['delivered', 'not delivered'], name='i2')
            ...     , Issue(values=4, name='i3')]
            >>> f = LinearUtilityAggregationFunction([lambda x: 2.0*x
            ...                          , {'delivered': 10, 'not delivered': -10}
            ...                          , MappingUtilityFunction(lambda x: x-3)]
            ...         , weights=[1.0, 2.0, 4.0])
            >>> print(f.xml(issues))
            <issue index="1" etype="discrete" type="discrete" vtype="discrete" name="i1">
                <item index="1" value="0" evaluation="0.0" />
                <item index="2" value="1" evaluation="2.0" />
                <item index="3" value="2" evaluation="4.0" />
                <item index="4" value="3" evaluation="6.0" />
                <item index="5" value="4" evaluation="8.0" />
                <item index="6" value="5" evaluation="10.0" />
                <item index="7" value="6" evaluation="12.0" />
                <item index="8" value="7" evaluation="14.0" />
                <item index="9" value="8" evaluation="16.0" />
                <item index="10" value="9" evaluation="18.0" />
            </issue>
            <issue index="2" etype="discrete" type="discrete" vtype="discrete" name="i2">
                <item index="1" value="delivered" evaluation="10" />
                <item index="2" value="not delivered" evaluation="-10" />
            </issue>
            <issue index="3" etype="discrete" type="discrete" vtype="discrete" name="i3">
                <item index="1" value="0" evaluation="-3" />
                <item index="2" value="1" evaluation="-2" />
                <item index="3" value="2" evaluation="-1" />
                <item index="4" value="3" evaluation="0" />
            </issue>
            <weight index="1" value="1.0">
            </weight>
            <weight index="2" value="2.0">
            </weight>
            <weight index="3" value="4.0">
            </weight>
            <BLANKLINE>
            >>> print(f.xml({i:_ for i, _ in enumerate(issues)}))
            <issue index="1" etype="discrete" type="discrete" vtype="discrete" name="i1">
                <item index="1" value="0" evaluation="0.0" />
                <item index="2" value="1" evaluation="2.0" />
                <item index="3" value="2" evaluation="4.0" />
                <item index="4" value="3" evaluation="6.0" />
                <item index="5" value="4" evaluation="8.0" />
                <item index="6" value="5" evaluation="10.0" />
                <item index="7" value="6" evaluation="12.0" />
                <item index="8" value="7" evaluation="14.0" />
                <item index="9" value="8" evaluation="16.0" />
                <item index="10" value="9" evaluation="18.0" />
            </issue>
            <issue index="2" etype="discrete" type="discrete" vtype="discrete" name="i2">
                <item index="1" value="delivered" evaluation="10" />
                <item index="2" value="not delivered" evaluation="-10" />
            </issue>
            <issue index="3" etype="discrete" type="discrete" vtype="discrete" name="i3">
                <item index="1" value="0" evaluation="-3" />
                <item index="2" value="1" evaluation="-2" />
                <item index="3" value="2" evaluation="-1" />
                <item index="4" value="3" evaluation="0" />
            </issue>
            <weight index="1" value="1.0">
            </weight>
            <weight index="2" value="2.0">
            </weight>
            <weight index="3" value="4.0">
            </weight>
            <BLANKLINE>

        """
        output = ""
        keys = list(ikeys(issues))
        for i, k in enumerate(keys):
            issue = iget(issues, k)
            issue_name = issue.name
            if issue.is_float():
                output += f'<issue index="{i + 1}" etype="real" type="real" vtype="real" name="{issue_name}">\n'
                output += f'<range lowerbound = {issue.min_value} upperbound = {issue.max_value} ></range>'
            # elif issue.is_integer():
            #     output += f'<issue index="{i + 1}" etype="integer" type="integer" vtype="integer" name="{issue_name}">\n'
            #     output += f'<range lowerbound = {issue.min_value} upperbound = {issue.max_value} ></range>'
            else:
                output += f'<issue index="{i+1}" etype="discrete" type="discrete" vtype="discrete" name="{issue_name}">\n'
                vals = iget(issues, k).all
                for indx, v in enumerate(vals):
                    try:
                        u = gmap(iget(self.issue_utilities, issue_name), v)
                    except:
                        u = gmap(iget(self.issue_utilities, k), v)
                    v_ = (v
                          if not (isinstance(v, tuple) or isinstance(v, list))
                          else "-".join([str(_) for _ in v]))
                    output += (
                        f'    <item index="{indx+1}" value="{v_}" evaluation="{u}" />\n'
                    )
            output += "</issue>\n"
        if isinstance(issues, dict):
            if isinstance(self.weights, dict):
                weights = self.weights
            else:
                weights = {k: v for k, v in zip(ikeys(issues), self.weights)}
        else:
            if isinstance(self.weights, list):
                weights = self.weights
            else:
                weights = list(self.weights.get(i.name, 1.0) for i in issues)

        for i, k in enumerate(keys):
            output += f'<weight index="{i+1}" value="{iget(weights, k)}">\n</weight>\n'
        return output
Beispiel #7
0
    def xml(self, issues: List[Issue]) -> str:
        """Generates an XML string representing the utility function

        Args:
            issues:

        Examples:

            >>> issues = [Issue(values=10, name='i1'), Issue(values=4, name='i2')]
            >>> f = LinearUtilityFunction(weights=[1.0, 4.0])
            >>> print(f.xml(issues))
            <issue index="1" etype="discrete" type="discrete" vtype="discrete" name="i1">
                <item index="1" value="0" evaluation="0" />
                <item index="2" value="1" evaluation="1" />
                <item index="3" value="2" evaluation="2" />
                <item index="4" value="3" evaluation="3" />
                <item index="5" value="4" evaluation="4" />
                <item index="6" value="5" evaluation="5" />
                <item index="7" value="6" evaluation="6" />
                <item index="8" value="7" evaluation="7" />
                <item index="9" value="8" evaluation="8" />
                <item index="10" value="9" evaluation="9" />
            </issue>
            <issue index="2" etype="discrete" type="discrete" vtype="discrete" name="i2">
                <item index="1" value="0" evaluation="0" />
                <item index="2" value="1" evaluation="1" />
                <item index="3" value="2" evaluation="2" />
                <item index="4" value="3" evaluation="3" />
            </issue>
            <weight index="1" value="1.0">
            </weight>
            <weight index="2" value="4.0">
            </weight>
            <BLANKLINE>

        """
        output = ""
        keys = list(ikeys(issues))
        for i, k in enumerate(keys):
            issue = iget(issues, k)
            issue_name = issue.name
            if issue.is_float():
                output += f'<issue index="{i + 1}" etype="real" type="real" vtype="real" name="{issue_name}">\n'
                output += f'<range lowerbound = {issue.min_value} upperbound = {issue.max_value} ></range>'
            # elif issue.is_integer():
            #     output += f'<issue index="{i + 1}" etype="integer" type="integer" vtype="integer" name="{issue_name}">\n'
            #     output += f'<range lowerbound = {issue.min_value} upperbound = {issue.max_value} ></range>'
            else:
                output += f'<issue index="{i+1}" etype="discrete" type="discrete" vtype="discrete" name="{issue_name}">\n'
            vals = iget(issues, k).all
            bias = iget(self.biases, k, 0.0)
            for indx, u in enumerate(vals):
                uu = issue.value_type(u + bias)
                output += f'    <item index="{indx+1}" value="{uu}" evaluation="{u}" />\n'

            output += "</issue>\n"
        if isinstance(issues, dict):
            if isinstance(self.weights, dict):
                weights = self.weights
            else:
                weights = {k: v for k, v in zip(ikeys(issues), self.weights)}
        else:
            if isinstance(self.weights, list) or isinstance(
                    self.weights, tuple):
                weights = list(self.weights)
            else:
                weights = list(self.weights.get(i.name, 1.0) for i in issues)

        for i, k in enumerate(keys):
            output += f'<weight index="{i+1}" value="{iget(weights, k)}">\n</weight>\n'
        return output
Beispiel #8
0
    def xml(self, issues: List[Issue]) -> str:
        """Represents the function as XML

        Args:
            issues:

        Examples:

            >>> f = HyperRectangleUtilityFunction(outcome_ranges=[
            ...                                        {0: (1.0, 2.0), 1: (1.0, 2.0)},
            ...                                        {0: (1.4, 2.0), 2: (2.0, 3.0)}]
            ...                                , utilities= [2.0, 9.0 + 4.0])
            >>> print(f.xml([Issue((0.0, 4.0), name='0'), Issue((0.0, 9.0), name='1')
            ... , Issue((0.0, 9.0), name='2')]).strip())
            <issue index="1" name="0" vtype="real" type="real" etype="real">
                <range lowerbound="0.0" upperbound="4.0"></range>
            </issue><issue index="2" name="1" vtype="real" type="real" etype="real">
                <range lowerbound="0.0" upperbound="9.0"></range>
            </issue><issue index="3" name="2" vtype="real" type="real" etype="real">
                <range lowerbound="0.0" upperbound="9.0"></range>
            </issue><utility_function maxutility="-1.0">
                <ufun type="PlainUfun" weight="1" aggregation="sum">
                    <hyperRectangle utility_function="2.0">
                        <INCLUDES index="0" min="1.0" max="2.0" />
                        <INCLUDES index="1" min="1.0" max="2.0" />
                    </hyperRectangle>
                    <hyperRectangle utility_function="13.0">
                        <INCLUDES index="0" min="1.4" max="2.0" />
                        <INCLUDES index="2" min="2.0" max="3.0" />
                    </hyperRectangle>
                </ufun>
            </utility_function>

        """
        output = ""
        for i, issue in enumerate(ivalues(issues)):
            name = issue.name
            if isinstance(issue.values, tuple):
                output += (
                    f'<issue index="{i+1}" name="{name}" vtype="real" type="real" etype="real">\n'
                    f'    <range lowerbound="{issue.values[0]}" upperbound="{issue.values[1]}"></range>\n'
                    f"</issue>")
            elif isinstance(issue.values, int):
                output += (
                    f'<issue index="{i+1}" name="{name}" vtype="integer" type="integer" etype="integer" '
                    f'lowerbound="0" upperbound="{issue.values - 1}"/>\n')
            else:
                output += (
                    f'<issue index="{i+1}" name="{name}" vtype="integer" type="integer" etype="integer" '
                    f'lowerbound="{min(issue.values)}" upperbound="{max(issue.values)}"/>\n'
                )
        # todo find the real maxutility
        output += '<utility_function maxutility="-1.0">\n    <ufun type="PlainUfun" weight="1" aggregation="sum">\n'
        for rect, u, w in zip(self.outcome_ranges, self.mappings,
                              self.weights):
            output += f'        <hyperRectangle utility_function="{u * w}">\n'
            for indx in ikeys(rect):
                values = iget(rect, indx, None)
                if values is None:
                    continue
                if isinstance(values, float) or isinstance(values, int):
                    mn, mx = values, values
                elif isinstance(values, tuple):
                    mn, mx = values
                else:
                    mn, mx = min(values), max(values)
                output += (
                    f'            <INCLUDES index="{indx}" min="{mn}" max="{mx}" />\n'
                )
            output += f"        </hyperRectangle>\n"
        output += "    </ufun>\n</utility_function>"
        return output