MappingUtilityFunction

class negmas.utilities.MappingUtilityFunction(mapping: Union[Callable[[Union[negmas.outcomes.OutcomeType, Tuple[Union[int, float, str, list]], Dict[Union[int, str], Union[int, float, str, list]], int, str, float]], Union[negmas.helpers.Distribution, float]], Mapping[Union[Sequence, Mapping, int, str, float], Union[negmas.helpers.Distribution, float]]], default=None, name: Optional[str] = None, reserved_value: Union[negmas.helpers.Distribution, float] = - inf, ami: Optional[negmas.common.AgentMechanismInterface] = None, outcome_type: Optional[Type] = None, id=None, **kwargs)[source]

Bases: negmas.utilities.UtilityFunction

Outcome mapping utility function.

This is the simplest possible utility function and it just maps a set of `Outcome`s to a set of `UtilityValue`(s). It is only usable with single-issue negotiations. It can be constructed with wither a mapping (e.g. a dict) or a callable function.

Parameters
  • mapping – Either a callable or a mapping from Outcome to UtilityValue.

  • default – value returned for outcomes causing exception (e.g. invalid outcomes).

  • name – name of the utility function. If None a random name will be generated.

  • reserved_value – The reserved value (utility of not getting an agreement = utility(None) )

  • ami – an AgentMechnismInterface that is used mostly for setting the outcome-type in methods returning outcomes.

  • outcome_type – The type that should be returned from methods returning Outcome which can be tuple, dict or any OutcomeType.

Examples

Single issue outcome case:

>>> issue =Issue(values=['to be', 'not to be'], name='THE problem')
>>> print(str(issue))
THE problem: ['to be', 'not to be']
>>> f = MappingUtilityFunction({'to be':10.0, 'not to be':0.0})
>>> print(list(map(f, ['to be', 'not to be'])))
[10.0, 0.0]
>>> f = MappingUtilityFunction(mapping={'to be':-10.0, 'not to be':10.0})
>>> print(list(map(f, ['to be', 'not to be'])))
[-10.0, 10.0]
>>> f = MappingUtilityFunction(lambda x: float(len(x)))
>>> print(list(map(f, ['to be', 'not to be'])))
[5.0, 9.0]

Multi issue case:

>>> issues = [Issue((10.0, 20.0), 'price'), Issue(['delivered', 'not delivered'], 'delivery')
...           , Issue(5, 'quality')]
>>> print(list(map(str, issues)))
['price: (10.0, 20.0)', "delivery: ['delivered', 'not delivered']", 'quality: (0, 4)']
>>> f = MappingUtilityFunction(lambda x: x['price'] if x['delivery'] == 'delivered' else -1.0)
>>> g = MappingUtilityFunction(lambda x: x['price'] if x['delivery'] == 'delivered' else -1.0
...     , default=-1000 )
>>> f({'price': 16.0}) is None
True
>>> g({'price': 16.0})
-1000
>>> f({'price': 16.0, 'delivery':  'delivered'})
16.0
>>> f({'price': 16.0, 'delivery':  'not delivered'})
-1.0
Remarks:
  • If the mapping used failed on the outcome (for example because it is not a valid outcome), then the

default value given to the constructor (which defaults to None) will be returned.

Methods Summary

eval(offer)

Calculate the utility value for a given outcome.

from_dict(d)

random(issues[, reserved_value, normalized, …])

Generates a random ufun of the given type

to_dict()

xml(issues)

Examples

Methods Documentation

eval(offer: Optional[Union[negmas.outcomes.OutcomeType, Tuple[Union[int, float, str, list]], Dict[Union[int, str], Union[int, float, str, list]]]])Optional[Union[negmas.helpers.Distribution, float]][source]

Calculate the utility value for a given outcome.

Parameters

offer – The offer to be evaluated.

Returns

The utility_function value which may be a distribution.

If None it means the utility_function value cannot be calculated.

Return type

UtilityValue

Remarks:
  • You cannot return None from overriden eval() functions but raise an exception (ValueError) if it was not possible to calculate the UtilityValue.

  • Typehint the return type as a UtilityValue instead of a float for the benefit of inspection code.

  • Return the reserved value if the offer was None

  • NEVER call the baseclass using super() when overriding this method. Calling super will lead to an infinite loop.

  • The default implementation assumes that is_better is defined and uses it to do the evaluation. Note that the default implementation of is_better does assume that eval is defined and uses it. This means that failing to define both leads to an infinite loop.

classmethod from_dict(d)[source]
classmethod random(issues: List[negmas.outcomes.Issue], reserved_value=(0.0, 1.0), normalized=True, max_n_outcomes: int = 10000)[source]

Generates a random ufun of the given type

to_dict()[source]
xml(issues: List[negmas.outcomes.Issue])str[source]

Examples

>>> issue =Issue(values=['to be', 'not to be'], name='THE problem')
>>> print(str(issue))
THE problem: ['to be', 'not to be']
>>> f = MappingUtilityFunction({'to be':10.0, 'not to be':0.0})
>>> print(list(map(f, ['to be', 'not to be'])))
[10.0, 0.0]
>>> print(f.xml([issue]))
<issue index="1" etype="discrete" type="discrete" vtype="discrete" name="THE problem">
    <item index="1" value="to be"  cost="0"  evaluation="10.0" description="to be">
    </item>
    <item index="2" value="not to be"  cost="0"  evaluation="0.0" description="not to be">
    </item>
</issue>
<weight index="1" value="1.0">
</weight>