NonLinearAggregationUtilityFunction

class negmas.preferences.NonLinearAggregationUtilityFunction(values: dict[str, Callable[[Any], Any] | Mapping | Sequence] | list[Callable[[Any], Any] | Mapping | Sequence] | None, f: Callable[[tuple[float]], float], *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A nonlinear utility function.

Allows for the modeling of a single nonlinear utility function that combines the utilities of different issues.

Parameters:
  • values – A set of mappings from issue values to utility functions. These are generic mappings so Callable (s) and Mapping (s) are both accepted

  • f – A nonlinear function mapping from a dict of utility_function-per-issue to a float

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

Notes

The utility is calculated as:

\[u = f\left(u_0\left(i_0\right), u_1\left(i_1\right), ..., u_n\left(i_n\right)\right)\]

where \(u_j()\) is the utility function for issue \(j\) and \(i_j\) is value of issue \(j\) in the evaluated outcome.

Examples

>>> from negmas.outcomes import make_issue
>>> from negmas.preferences.crisp.mapping import MappingUtilityFunction
>>> issues = [
...     make_issue((10.0, 20.0), "price"),
...     make_issue(["delivered", "not delivered"], "delivery"),
...     make_issue(5, "quality"),
... ]
>>> print(list(map(str, issues)))
['price: (10.0, 20.0)', "delivery: ['delivered', 'not delivered']", 'quality: (0, 4)']
>>> g = NonLinearAggregationUtilityFunction(
...     {
...         "price": lambda x: 2.0 * x,
...         "delivery": {"delivered": 10, "not delivered": -10},
...         "quality": MappingUtilityFunction(lambda x: x - 3),
...     },
...     f=lambda u: u[0] + 2.0 * u[-1],
...     issues=issues,
... )
>>> g((14.0, "delivered", 2)) - ((2.0 * 14.0) + 2.0 * (2 - 3))
0.0

You must pass a value for each issue in the outcome. If some issues are not used for the ufun, you can pass them as any value that is acceptable to the corresponding value function

>>> g = NonLinearAggregationUtilityFunction(
...     {
...         "price": lambda x: 2.0 * x,
...         "delivery": {"delivered": 10, "not delivered": -10},
...     },
...     f=lambda u: 2.0 * u[0],
...     issues=issues[:2],
... )
>>> g((14.0, "delivered")) - (2.0 * (2.0 * 14))
0.0

Attributes Summary

base_type

Returns the utility_function base type ignoring discounting and similar wrappings.

id

The unique ID of this entity

name

A convenient name of the entity (intended primarily for printing/logging/debugging).

reserved_distribution

short_type_name

type

Returns the utility_function type.

type_name

uuid

The unique ID of this entity

Methods Summary

__call__(offer)

Calculate the utility_function value for a given outcome.

argrank(outcomes[, descending])

Ranks the given list of outcomes with weights.

argrank_with_weights(outcomes[, descending])

Ranks the given list of outcomes with weights.

best()

changes()

Returns a list of changes to the preferences (if any) since last call.

checkpoint(path[, file_name, info, ...])

Saves a checkpoint of the current object at the given path.

checkpoint_info(file_name)

Returns the information associated with a dump of the object saved in the given file

create(*args, **kwargs)

Creates an object and returns a proxy to it.

difference(first, second)

Returns a numeric difference between the utility of the two given outcomes

difference_prob(first, second)

Returns a numeric difference between the utility of the two given outcomes

eu(offer)

calculates the expected utility value of the input outcome

eval(offer)

eval_normalized(offer[, above_reserve, ...])

Evaluates the ufun normalizing the result between zero and one

extreme_outcomes([outcome_space, issues, ...])

forget_inverter()

Deletes the cached inverter.

from_checkpoint(file_name[, return_info])

Creates an object from a saved checkpoint

from_dict(d[, python_class_identifier])

from_genius(file_name, **kwargs)

Imports a utility function from a GENIUS XML file.

from_geniusweb(file_name, **kwargs)

Imports a utility function from a GeniusWeb json file.

from_geniusweb_json_str(json_str[, ...])

Imports a utility function from a GeniusWeb JSON string.

from_xml_str(xml_str, issues[, ...])

Imports a utility function from a GENIUS XML string.

generate_bilateral(outcomes[, ...])

Generates a couple of utility functions

generate_random(n, outcomes[, normalized])

Generates N mapping utility functions

generate_random_bilateral(outcomes)

Generates a couple of utility functions

invert([inverter])

Inverts the ufun, initializes it and caches the result.

is_better(first, second)

Compares two offers using the ufun returning whether the first is strictly better than the second

is_equivalent(first, second)

Compares two offers using the ufun returning whether the first is strictly equivelent than the second

is_not_better(first, second)

Compares two offers using the ufun returning whether the first is worse or equivalent than the second

is_not_worse(first, second)

Is first at least as good as second

is_session_dependent()

Does the utility of an outcome depend on the NegotiatorMechanismInterface?

is_state_dependent()

Does the utility of an outcome depend on the negotiation state?

is_stationary()

Are the preferences stationary (i.e. repeated calls return the same value for any preferences comparion or evaluaton method)?.

is_volatile()

Does the utility of an outcome depend on factors outside the negotiation?

is_worse(first, second)

Compares two offers using the ufun returning whether the first is strictly worse than the second

max()

min()

minmax([outcome_space, issues, outcomes, ...])

Finds the range of the given utility function for the given outcomes

normalize([to, normalize_weights])

normalize_for([to, outcome_space])

rank(outcomes[, descending])

Ranks the given list of outcomes with weights.

rank_with_weights(outcomes[, descending])

Ranks the given list of outcomes with weights.

reset_changes()

Will be called whenever we need to reset changes.

sample_outcome_with_utility(rng[, ...])

Samples an outcome in the given utiltity range or return None if not possible

scale_by(scale[, scale_reserved])

scale_max(to[, rng])

scale_max_for(to[, outcome_space, issues, ...])

scale_min(to[, rng])

scale_min_for(to[, outcome_space, issues, ...])

set_id(id)

Sets the unique ID of this entity

shift_by(offset[, shift_reserved])

shift_max_for(to[, outcome_space, issues, ...])

shift_min_for(to[, outcome_space, issues, ...])

spawn([spawn_as, spawn_params])

spawn_object(*args, **kwargs)

to_crisp()

to_dict([python_class_identifier])

to_genius(file_name[, issues])

Exports a utility function to a GENIUS XML file.

to_prob()

to_stationary()

to_xml_str([issues, discount_factor])

Exports a utility function to a well formatted string

worst()

xml(issues)

Attributes Documentation

base_type

Returns the utility_function base type ignoring discounting and similar wrappings.

id

The unique ID of this entity

name

A convenient name of the entity (intended primarily for printing/logging/debugging).

reserved_distribution
short_type_name
type

Returns the utility_function type.

Each class inheriting from this UtilityFunction class will have its own type. The default type is the empty string.

Examples

>>> from negmas.preferences import *
>>> from negmas.outcomes import make_issue
>>> print(
...     LinearAdditiveUtilityFunction(
...         (lambda x: x, lambda x: x), issues=[make_issue((0, 1), (0, 1))]
...     ).type
... )
linear_additive
>>> print(
...     MappingUtilityFunction(
...         [lambda x: x], issues=[make_issue((0.0, 1.0))]
...     ).type
... )
mapping
Returns:

utility_function type

Return type:

str

type_name
uuid

The unique ID of this entity

Methods Documentation

__call__(offer: tuple | None) float

Calculate the utility_function value for a given outcome.

Parameters:

offer – The offer to be evaluated.

Remarks:

  • It calls the abstract method eval after opationally adjusting the outcome type.

  • It is preferred to override eval instead of directly overriding this method

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

  • Return a float from your eval implementation.

  • Return the reserved value if the offer was None

Returns:

The utility of the given outcome

argrank(outcomes: Sequence[tuple | None], descending=True) list[list[tuple | None]]

Ranks the given list of outcomes with weights. None stands for the null outcome.

Returns:

A list of lists of integers giving the outcome index in the input. The list is sorted by utlity value

argrank_with_weights(outcomes: Sequence[tuple | None], descending=True) list[tuple[list[tuple | None], float]]

Ranks the given list of outcomes with weights. None stands for the null outcome.

Returns:

  • an list of integers giving the index in the input array (outcomes) of an outcome (at the given utility level)
    • the weight of that outcome

  • The list is sorted by weights descendingly

Return type:

  • A list of tuples each with two values

best() tuple
changes() list[PreferencesChange]

Returns a list of changes to the preferences (if any) since last call.

Remarks:
  • If the ufun is stationary, the return list will always be empty.

  • If the ufun is not stationary, the ufun itself is responsible for saving the changes in _changes whenever they happen.

checkpoint(path: PathLike, file_name: str | None = None, info: dict[str, Any] | None = None, exist_ok: bool = False, single_checkpoint: bool = True, step_attribs: tuple[str, ...] = ('current_step', '_current_step', '_Entity__current_step', '_step')) Path

Saves a checkpoint of the current object at the given path.

Parameters:
  • path – Full path to a directory to store the checkpoint

  • file_name – Name of the file to dump into. If not given, a unique name is created

  • info – Information to save with the checkpoint (must be json serializable)

  • exist_ok – If true, override existing dump

  • single_checkpoint – If true, keep a single checkpoint for the last step

  • step_attribs – Attributes to represent the time-step of the object. Any of the given attributes will be used in the file name generated if single_checkpoint is False. If single_checkpoint is True, the filename will not contain time-step information

Returns:

full path to the file used to save the checkpoint

classmethod checkpoint_info(file_name: Path | str) dict[str, Any]

Returns the information associated with a dump of the object saved in the given file

Parameters:

file_name – Name of the object

Returns:

classmethod create(*args, **kwargs)

Creates an object and returns a proxy to it.

difference(first: tuple | None, second: tuple | None) float

Returns a numeric difference between the utility of the two given outcomes

difference_prob(first: tuple | None, second: tuple | None) Distribution

Returns a numeric difference between the utility of the two given outcomes

eu(offer: tuple | None) float

calculates the expected utility value of the input outcome

eval(offer: tuple | None) float[source]
eval_normalized(offer: tuple | None, above_reserve: bool = True, expected_limits: bool = True) float

Evaluates the ufun normalizing the result between zero and one

Parameters:
  • offer (Outcome | None) – offer

  • above_reserve (bool) – If True, zero corresponds to the reserved value not the minimum

  • expected_limits (bool) – If True, the expectation of the utility limits will be used for normalization instead of the maximum range and minimum lowest limit

Remarks:
  • If the maximum and the minium are equal, finite and above reserve, will return 1.0.

  • If the maximum and the minium are equal, initinte or below reserve, will return 0.0.

  • For probabilistic ufuns, a distribution will still be returned.

  • The minimum and maximum will be evaluated freshly every time. If they are already cached in the ufun, the cache will be used.

extreme_outcomes(outcome_space: OutcomeSpace | None = None, issues: Iterable[Issue] | None = None, outcomes: Iterable[tuple] | None = None, max_cardinality=100000) tuple[tuple, tuple]
forget_inverter()

Deletes the cached inverter.

classmethod from_checkpoint(file_name: Path | str, return_info: bool = False) NamedObject | tuple[NamedObject, dict[str, Any]]

Creates an object from a saved checkpoint

Parameters:
  • file_name

  • return_info – If True, tbe information saved when the file was dumped are returned

Returns:

Either the object or the object and dump-info as a dict (if return_info was true)

Remarks:

  • If info is returned, it is guaranteed to have the following members:
    • time: Dump time

    • type: Type of the dumped object

    • id: ID

    • name: name

classmethod from_dict(d, python_class_identifier='__python_class__')[source]
classmethod from_genius(file_name: PathLike | str, **kwargs) tuple[BaseUtilityFunction | None, float | None]

Imports a utility function from a GENIUS XML file.

Parameters:

file_name (str) – File name to import from

Returns:

A utility function object (depending on the input file)

Examples

>>> from negmas.preferences import UtilityFunction
>>> import pkg_resources
>>> from negmas.inout import load_genius_domain
>>> domain = load_genius_domain(
...     pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-domain.xml"
...     )
... )
>>> u, d = UtilityFunction.from_genius(
...     file_name=pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-prof1.xml"
...     ),
...     issues=domain.issues,
... )
>>> u.__class__.__name__
'LinearAdditiveUtilityFunction'
>>> u.reserved_value
0.0
>>> d
1.0
Remarks:

See from_xml_str for all the parameters

classmethod from_geniusweb(file_name: PathLike | str, **kwargs) tuple[BaseUtilityFunction | None, float | None]

Imports a utility function from a GeniusWeb json file.

Parameters:

file_name (str) – File name to import from

Returns:

A utility function object (depending on the input file)

Remarks:

See from_geniusweb_json_str for all the parameters

classmethod from_geniusweb_json_str(json_str: str | dict, safe_parsing=True, issues: Iterable[Issue] | Sequence[Issue] | None = None, ignore_discount=False, ignore_reserved=False, use_reserved_outcome=False, name: str | None = None) tuple[BaseUtilityFunction | None, float | None]

Imports a utility function from a GeniusWeb JSON string.

Parameters:
  • json_str (str) – The string containing GENIUS style XML utility function definition

  • issues (Sequence[Issue] | None) – Optional issue space to confirm that the utility function is valid

  • input (product of all issues in the)

  • safe_parsing (bool) – Turn on extra checks

Returns:

A utility function object (depending on the input file)

classmethod from_xml_str(xml_str: str, issues: Iterable[Issue] | Sequence[Issue], safe_parsing=True, ignore_discount=False, ignore_reserved=False, name: str | None = None) tuple[BaseUtilityFunction | None, float | None]

Imports a utility function from a GENIUS XML string.

Parameters:
  • xml_str (str) – The string containing GENIUS style XML utility function definition

  • issues (Sequence[Issue] | None) – Optional issue space to confirm that the utility function is valid

  • input (product of all issues in the)

  • safe_parsing (bool) – Turn on extra checks

Returns:

A utility function object (depending on the input file)

Examples

>>> from negmas.preferences import UtilityFunction
>>> import pkg_resources
>>> from negmas.inout import load_genius_domain
>>> domain = load_genius_domain(
...     pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-domain.xml"
...     )
... )
>>> with open(
...     pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-prof1.xml"
...     ),
...     "r",
... ) as ff:
...     u, _ = UtilityFunction.from_xml_str(ff.read(), issues=domain.issues)
>>> with open(
...     pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-prof1.xml"
...     ),
...     "r",
... ) as ff:
...     u, _ = UtilityFunction.from_xml_str(ff.read(), issues=domain.issues)
>>> assert abs(u(("Dell", "60 Gb", "19'' LCD")) - 21.987727736172488) < 0.000001
>>> assert abs(u(("HP", "80 Gb", "20'' LCD")) - 22.68559475583014) < 0.000001
classmethod generate_bilateral(outcomes: int | Sequence[tuple], conflict_level: float = 0.5, conflict_delta=0.005) tuple[UtilityFunction, UtilityFunction]

Generates a couple of utility functions

Parameters:
  • n_outcomes (int) – number of outcomes to use

  • conflict_level – How conflicting are the two ufuns to generate. 1.0 means maximum conflict.

  • conflict_delta – How variable is the conflict at different outcomes.

Examples

>>> from negmas.preferences import conflict_level
>>> u1, u2 = UtilityFunction.generate_bilateral(
...     outcomes=10, conflict_level=0.0, conflict_delta=0.0
... )
>>> print(conflict_level(u1, u2, outcomes=10))
0.0
>>> u1, u2 = UtilityFunction.generate_bilateral(
...     outcomes=10, conflict_level=1.0, conflict_delta=0.0
... )
>>> print(conflict_level(u1, u2, outcomes=10))
1.0
>>> u1, u2 = UtilityFunction.generate_bilateral(
...     outcomes=10, conflict_level=0.5, conflict_delta=0.0
... )
>>> 0.0 < conflict_level(u1, u2, outcomes=10) < 1.0
True
classmethod generate_random(n: int, outcomes: int | Sequence[tuple] | Iterable[tuple], normalized: bool = True) list[UtilityFunction]

Generates N mapping utility functions

Parameters:
  • n – number of utility functions to generate

  • outcomes – number of outcomes to use

  • normalized – if true, the resulting ufuns will be normlized between zero and one.

classmethod generate_random_bilateral(outcomes: int | Sequence[tuple]) tuple[UtilityFunction, UtilityFunction]

Generates a couple of utility functions

Parameters:
  • n_outcomes (int) – number of outcomes to use

  • conflict_level – How conflicting are the two ufuns to generate. 1.0 means maximum conflict.

  • conflict_delta – How variable is the conflict at different outcomes.

  • zero_summness – How zero-sum like are the two ufuns.

invert(inverter: type[InverseUFun] | None = None, **kwargs) InverseUFun

Inverts the ufun, initializes it and caches the result.

is_better(first: tuple | None, second: tuple | None) bool

Compares two offers using the ufun returning whether the first is strictly better than the second

Parameters:
  • first – First outcome to be compared

  • second – Second outcome to be compared

Remarks:

  • Should raise ValueError if the comparison cannot be done

is_equivalent(first: tuple | None, second: tuple | None) bool

Compares two offers using the ufun returning whether the first is strictly equivelent than the second

Parameters:
  • first – First outcome to be compared

  • second – Second outcome to be compared

Remarks:

  • Should raise ValueError if the comparison cannot be done

is_not_better(first: tuple | None, second: tuple | None) bool

Compares two offers using the ufun returning whether the first is worse or equivalent than the second

Parameters:
  • first – First outcome to be compared

  • second – Second outcome to be compared

Remarks:

  • Should raise ValueError if the comparison cannot be done

is_not_worse(first: tuple | None, second: tuple | None) bool

Is first at least as good as second

is_session_dependent() bool

Does the utility of an outcome depend on the NegotiatorMechanismInterface?

is_state_dependent() bool

Does the utility of an outcome depend on the negotiation state?

is_stationary() bool

Are the preferences stationary (i.e. repeated calls return the same value for any preferences comparion or evaluaton method)?

is_volatile() bool

Does the utility of an outcome depend on factors outside the negotiation?

Remarks:
  • A volatile preferences is one that can change even for the same mechanism state due to outside influence

is_worse(first: tuple | None, second: tuple | None) bool

Compares two offers using the ufun returning whether the first is strictly worse than the second

Parameters:
  • first – First outcome to be compared

  • second – Second outcome to be compared

Remarks:

  • Should raise ValueError if the comparison cannot be done

max() Distribution | float
min() Distribution | float
minmax(outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[tuple] | None = None, max_cardinality=1000, above_reserve=False) tuple[float, float]

Finds the range of the given utility function for the given outcomes

Parameters:
  • self – The utility function

  • issues – List of issues (optional)

  • outcomes – A collection of outcomes (optional)

  • max_cardinality – the maximum number of outcomes to try sampling (if sampling is used and outcomes are not given)

  • above_reserve – If given, the minimum and maximum will be set to reserved value if they were less than it.

Returns:

(lowest, highest) utilities in that order

normalize(to: tuple[float, float] = (0.0, 1.0), normalize_weights: bool = False) T | ConstUtilityFunction
normalize_for(to: tuple[float, float] = (0.0, 1.0), outcome_space: OutcomeSpace | None = None) T | ConstUtilityFunction
rank(outcomes: Sequence[tuple | None], descending=True) list[list[tuple | None]]

Ranks the given list of outcomes with weights. None stands for the null outcome.

Returns:

A list of lists of integers giving the outcome index in the input. The list is sorted by utlity value

rank_with_weights(outcomes: Sequence[tuple | None], descending=True) list[tuple[list[tuple | None], float]]

Ranks the given list of outcomes with weights. None stands for the null outcome.

Returns:

  • an list of integers giving the index in the input array (outcomes) of an outcome (at the given utility level)
    • the weight of that outcome

  • The list is sorted by weights descendingly

Return type:

  • A list of tuples each with two values

reset_changes() None

Will be called whenever we need to reset changes.

sample_outcome_with_utility(rng: tuple[float, float], outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[tuple] | None = None, n_trials: int = 100) tuple | None

Samples an outcome in the given utiltity range or return None if not possible

Parameters:
  • rng (Tuple[float, float]) – rng

  • outcome_space (OutcomeSpace | None) – outcome_space

  • issues (Sequence[Issue] | None) – issues

  • outcomes (Sequence[Outcome] | None) – outcomes

  • n_trials (int) – n_trials

Return type:

Optional[“Outcome”]

scale_by(scale: float, scale_reserved=True) WeightedUtilityFunction | T
scale_max(to: float, rng: tuple[float, float] | None = None) T
scale_max_for(to: float, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[tuple] | None = None, rng: tuple[float, float] | None = None) T
scale_min(to: float, rng: tuple[float, float] | None = None) T
scale_min_for(to: float, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[tuple] | None = None, rng: tuple[float, float] | None = None) T
set_id(id: str)

Sets the unique ID of this entity

shift_by(offset: float, shift_reserved=True) WeightedUtilityFunction | T
shift_max_for(to: float, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[tuple] | None = None, rng: tuple[float, float] | None = None) T
shift_min_for(to: float, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[tuple] | None = None, rng: tuple[float, float] | None = None) T
classmethod spawn(spawn_as='object', spawn_params: dict[str, Any] | None = None, *args, **kwargs)
classmethod spawn_object(*args, **kwargs)
to_crisp() UtilityFunction
to_dict(python_class_identifier='__python_class__')[source]
to_genius(file_name: PathLike | str, issues: Iterable[Issue] | None = None, **kwargs)

Exports a utility function to a GENIUS XML file.

Parameters:
  • file_name (str) – File name to export to

  • u – utility function

  • issues – The issues being considered as defined in the domain

Returns:

None

Examples

>>> from negmas.preferences import UtilityFunction
>>> from negmas.inout import load_genius_domain
>>> import pkg_resources
>>> domain = load_genius_domain(
...     domain_file_name=pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-domain.xml"
...     )
... )
>>> u, d = UtilityFunction.from_genius(
...     file_name=pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/Laptop/Laptop-C-prof1.xml"
...     ),
...     issues=domain.issues,
... )
>>> u.to_genius(
...     discount_factor=d,
...     file_name=pkg_resources.resource_filename(
...         "negmas", resource_name="tests/data/LaptopConv/Laptop-C-prof1.xml"
...     ),
...     issues=domain.issues,
... )
Remarks:

See to_xml_str for all the parameters

to_prob() ProbUtilityFunction
to_stationary() UtilityFunction
to_xml_str(issues: Iterable[Issue] | None = None, discount_factor=None) str

Exports a utility function to a well formatted string

worst() tuple
xml(issues: list[Issue]) str[source]