negmas.preferences

Models basic types of utility functions.

Utility functions are at the core of negotiation. Agents engage in negotiations with the goal of maximizing some utility function. In most cases, these utility functions are assumed to be known a-periori and static for the duration of a single negotiations.

Notes

We try to allow for applications that do not necessary have these two assumptions in the following ways:

  • A utility_function value (Value) can always represent represent a utility_function distribution over all possible utility_function values (Distribution) or a KnownValue which is a real number.

  • The base class of all utility_function functions is UtilityFunction and is assumed to map outcomes (Outcome objects) to the aforementioned generic utility values (Value objects).

  • Utility functions can be constructed using any Callable which makes it possible to construct them so that they change depending on the context or the progression of the negotiation.

class negmas.preferences.AffineFun(slope: float, bias: float = 0)[source]

Bases: BaseFun

Affine value function: f(x) = slope * x + bias.

Maps numeric issue values to utilities using an affine (linear + constant) transformation. This is one of the most commonly used value functions.

Mathematical definition:

\[f(x) = a \cdot x + b\]

where \(a\) is the slope and \(b\) is the bias.

Parameters:
  • slope – The coefficient \(a\) multiplying the input value.

  • bias – The constant offset \(b\) (default: 0).

Example

>>> f = AffineFun(slope=2.0, bias=1.0)
>>> f(5)  # 2*5 + 1 = 11
11.0
>>> f(0)  # 2*0 + 1 = 1
1.0

Note

  • For slope > 0: higher input values yield higher utilities

  • For slope < 0: higher input values yield lower utilities

  • AffineFun(slope=m, bias=0) is equivalent to LinearFun(slope=m)

bias: float[source]
minmax(input: Issue) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) AffineFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

AffineFun

shift_by(offset: float) AffineFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

AffineFun

slope: float[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.AffineMultiFun(slope: tuple[float, ...], bias: float = 0)[source]

Bases: BaseMultiFun

Affine multi-issue value function: f(x) = sum(slope[i] * x[i]) + bias.

Maps tuples of numeric issue values to utilities using an affine combination (weighted sum plus constant). This models additive interactions between issues.

Mathematical definition:

\[f(\mathbf{x}) = \sum_{i=1}^{n} a_i x_i + b\]

where \(a_i\) are the slopes (weights) for each issue, \(x_i\) are the issue values, and \(b\) is the bias.

Parameters:
  • slope – Tuple of coefficients \((a_1, a_2, ..., a_n)\) for each issue.

  • bias – Constant offset \(b\) (default: 0).

Example

>>> f = AffineMultiFun(slope=(0.5, 0.3), bias=0.1)
>>> f((10, 20))  # 0.5*10 + 0.3*20 + 0.1 = 11.1
11.1

Note

This is equivalent to LinearMultiFun when bias=0.

bias: float[source]
property dim: int[source]

Dim.

Returns:

The result.

Return type:

int

minmax(input: Iterable[Issue]) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) AffineMultiFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

AffineMultiFun

shift_by(offset: float) AffineMultiFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

AffineMultiFun

slope: tuple[float, ...][source]
xml(indx, issues, bias: float = 0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issues – Issues.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.AffineUtilityFunction(weights: dict[str, float] | list[float] | tuple[float, ...] | None = None, bias: float = 0, *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

An affine utility function for multi-issue negotiations.

Models a linear utility function using predefined weights.

Parameters:
  • weights – weights for combining values

  • bias – The offset added

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

Notes

The utility value is calculated as:

\[u = \alpha + \sum_{i=0}^{n_{outcomes}-1} {\alpha_i * \omega_i}\]

where $alpha$ is the bias term and $alpha_i$ is the weight of issue $i$, and $omega_i$ is the value of issue $i$ in the input outcome $omega$.

Examples

>>> from negmas.outcomes import make_issue
>>> issues = [make_issue((10.0, 20.0), "price"), make_issue(5, "quality")]
>>> print(list(map(str, issues)))
['price: (10.0, 20.0)', 'quality: (0, 4)']
>>> f = AffineUtilityFunction({"price": 1.0, "quality": 4.0}, issues=issues)
>>> f((2, 14.0)) - (2 * 1.0 + 14.0 * 4)
0.0
>>> f = LinearUtilityFunction([1.0, 2.0])
>>> f((2, 14)) - (2 * 1.0 + 14 * 2.0)
0.0

Remarks:

  • If an outcome contains combinations of strings and numeric values that have corresponding weights, an exception will be raised when its utility is calculated

  • If you pass weights as a dictionary (mapping issue names to wieght values), you must pass the issues as well ( using outcome_space or issues ) and issue names must match the keys of the weights dict exactly (i.e. all issues are represented and all keys in the dict are in the issues).

  • If you pass the weights as a tuple, you need not pass the issues (but you still should to help with things like scaling and shifting ufun values)

property bias: float[source]

The constant offset term added to the weighted sum.

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Computes u = bias + sum(weights[i] * offer[i]) for all issues i.

Parameters:

offer – The outcome to evaluate. If None, returns the reserved value.

Returns:

The utility value for the given outcome.

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

Find the outcomes with minimum and maximum utility values.

For affine utility functions, exploits the linear structure to efficiently find extremes without enumerating all outcomes.

Parameters:
  • outcome_space – The outcome space to search within.

  • issues – Alternative way to specify the search space via issues.

  • outcomes – Explicit set of outcomes to search (slower).

  • max_cardinality – Maximum samples per issue when enumerating values.

Returns:

Tuple of (worst_outcome, best_outcome).

classmethod from_dict(d: dict, python_class_identifier='__python_class__')[source]

Create an instance from a dictionary.

Parameters:
  • d – Dictionary containing the serialized utility function.

  • python_class_identifier – Key used to identify the class type.

Returns:

A new AffineUtilityFunction instance.

normalize(to: tuple[float, float] = (0.0, 1.0), normalize_weights: bool = False) ConstUtilityFunction | AffineUtilityFunction | LinearUtilityFunction[source]

Normalize utility values to a specified range using the current outcome space.

Parameters:
  • to – Target range (min, max) for the normalized utility values.

  • normalize_weights – Unused parameter (kept for API compatibility).

Returns:

A new utility function with values normalized to the target range.

normalize_for(to: tuple[float, float] = (0.0, 1.0), outcome_space: OutcomeSpace | None = None) ConstUtilityFunction | AffineUtilityFunction[source]

Creates a new utility function that is normalized based on input conditions.

Parameters:

to

The minimum and maximum value to normalize to. If either is None, it is ignored.

This means that passing (None, 1.0) will normalize the ufun so that the maximum is 1 but will not guarantee any limit for the minimum and so on.

outcome_space: the outcome space to normalize within

classmethod random(issues: list[Issue] | tuple[Issue, ...], reserved_value=(0.0, 1.0), normalized=True)[source]

Generate a random affine utility function.

Parameters:
  • issues – The issues to generate the utility function for. Must be numeric.

  • reserved_value – Range (min, max) for random reserved value selection.

  • normalized – If True, normalize weights to sum to 1 and scale by issue ranges.

Returns:

A random AffineUtilityFunction instance.

Raises:

ValueError – If any issue is not numeric.

scale_by(scale: float, scale_reserved: bool = True) AffineUtilityFunction[source]

Create a new utility function scaled by a constant factor.

Computes u’(x) = scale * u(x).

Parameters:
  • scale – The non-negative factor to multiply all utility values by.

  • scale_reserved – If True, also scale the reserved value.

Returns:

A new AffineUtilityFunction with the scaled utility values.

Raises:

ValueError – If scale is negative.

shift_by(offset: float, shift_reserved: bool = True) AffineUtilityFunction[source]

Create a new utility function shifted by a constant offset.

Computes u’(x) = u(x) + offset.

Parameters:
  • offset – The amount to add to all utility values.

  • shift_reserved – If True, also shift the reserved value.

Returns:

A new AffineUtilityFunction with the shifted utility values.

to_dict(python_class_identifier='__python_class__')[source]

Convert to a dictionary for serialization.

Parameters:

python_class_identifier – Key used to store the class type identifier.

Returns:

Dictionary representation suitable for JSON serialization.

property values: list[source]

The value functions for each issue (identity functions for affine/linear).

property weights: list[float][source]

The weights for each issue in the linear combination.

xml(issues: list[Issue] | None = None) str[source]

Generates an XML string representing the utility function

Parameters:

issues

Examples

>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(values=10, name="i1"), make_issue(values=4, name="i2")]
>>> f = LinearUtilityFunction(weights=[1.0, 4.0], issues=issues)
>>> print(f.xml(issues))
<issue index="1" etype="discrete" type="discrete" vtype="integer" name="i1">
    <item index="1" value="0" evaluation="0.0" />
    <item index="2" value="1" evaluation="1.0" />
    <item index="3" value="2" evaluation="2.0" />
    <item index="4" value="3" evaluation="3.0" />
    <item index="5" value="4" evaluation="4.0" />
    <item index="6" value="5" evaluation="5.0" />
    <item index="7" value="6" evaluation="6.0" />
    <item index="8" value="7" evaluation="7.0" />
    <item index="9" value="8" evaluation="8.0" />
    <item index="10" value="9" evaluation="9.0" />
</issue>
<issue index="2" etype="discrete" type="discrete" vtype="integer" name="i2">
    <item index="1" value="0" evaluation="0.0" />
    <item index="2" value="1" evaluation="1.0" />
    <item index="3" value="2" evaluation="2.0" />
    <item index="4" value="3" evaluation="3.0" />
</issue>
<weight index="1" value="1.0">
</weight>
<weight index="2" value="4.0">
</weight>
class negmas.preferences.BaseFun[source]

Bases: ABC

Abstract base class for single-issue value functions.

A value function maps values from a single issue to real numbers. These are used as building blocks in utility functions like LinearAdditiveUtilityFunction.

All subclasses must implement:
  • __call__(x): Evaluate the function at value x

  • minmax(issue): Find min/max values over an issue’s domain

Subclasses should also implement:
  • shift_by(offset): Return a shifted version of the function

  • scale_by(scale): Return a scaled version of the function

  • xml(indx, issue, bias): Export to GENIUS XML format

Example

>>> from negmas.outcomes import make_issue
>>> from negmas.preferences.value_fun import AffineFun
>>> # Create an affine function f(x) = 2x + 1
>>> f = AffineFun(slope=2.0, bias=1.0)
>>> f(5)
11.0
>>> # Find min/max over an issue
>>> issue = make_issue(10, "quantity")  # 0-9
>>> f.minmax(issue)
(1.0, 19.0)
property dim: int[source]

Return the dimensionality of this function (always 1 for single-issue).

Returns:

Always returns 1.

Return type:

int

classmethod from_dict(d: dict, python_class_identifier='__python_class__')[source]

Deserialize a value function from a dictionary.

Parameters:
  • d – Dictionary representation of the function.

  • python_class_identifier – Key used for class type identification.

Returns:

The deserialized value function.

Return type:

BaseFun

max(input: Issue) float[source]

Find the maximum value over an issue’s domain.

Parameters:

input – The issue whose domain to evaluate over.

Returns:

The maximum value.

Return type:

float

min(input: Issue) float[source]

Find the minimum value over an issue’s domain.

Parameters:

input – The issue whose domain to evaluate over.

Returns:

The minimum value.

Return type:

float

abstractmethod minmax(input: Issue) tuple[float, float][source]

Find the minimum and maximum values over an issue’s domain.

Parameters:

input – The issue whose domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

Return type:

tuple[float, float]

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

Serialize the value function to a dictionary.

Parameters:

python_class_identifier – Key to use for class type identification.

Returns:

Dictionary representation of the function.

Return type:

dict[str, Any]

to_table(issue: Issue) TableFun[source]

Convert this function to a table lookup function.

Useful for exporting functions to formats that only support discrete value mappings.

Parameters:

issue – The issue to enumerate values from.

Returns:

A table function with the same values.

Return type:

TableFun

Note

For continuous issues, the issue will be discretized first.

class negmas.preferences.BaseMultiFun[source]

Bases: ABC

Abstract base class for multi-issue value functions.

A multi-issue value function maps a tuple of values from multiple issues to a single real number. These are used in utility functions like GLAUtilityFunction to model interactions between issues.

All subclasses must implement:
  • __call__(x): Evaluate the function at value tuple x

  • minmax(issues): Find min/max values over the issues’ domains

  • dim: Property returning the number of issues

Subclasses should also implement:
  • shift_by(offset): Return a shifted version of the function

  • scale_by(scale): Return a scaled version of the function

  • xml(indx, issues, bias): Export to GENIUS XML format (if possible)

Example

>>> from negmas.outcomes import make_issue
>>> from negmas.preferences.value_fun import AffineMultiFun
>>> # Create a multi-issue function f(x,y) = 0.5*x + 0.3*y + 0.1
>>> f = AffineMultiFun(slope=(0.5, 0.3), bias=0.1)
>>> f((10, 20))
11.1
>>> # Find min/max over issues
>>> issues = [make_issue(10, "x"), make_issue(5, "y")]
>>> f.minmax(tuple(issues))
(0.1, 5.8)
abstract property dim: int[source]

Return the number of issues this function operates on.

Returns:

The dimensionality (number of issues).

Return type:

int

classmethod from_dict(d: dict, python_class_identifier='__python_class__')[source]

Deserialize a value function from a dictionary.

Parameters:
  • d – Dictionary representation of the function.

  • python_class_identifier – Key used for class type identification.

Returns:

The deserialized value function.

Return type:

BaseMultiFun

abstractmethod minmax(input: Iterable[Issue]) tuple[float, float][source]

Find the minimum and maximum values over the issues’ domains.

Parameters:

input – The issues whose combined domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

Return type:

tuple[float, float]

abstractmethod scale_by(scale: float) BaseMultiFun[source]

Create a new function scaled by a constant factor.

Parameters:

scale – The factor to multiply all output values by.

Returns:

A new function where f’(x) = scale * f(x).

Return type:

BaseMultiFun

abstractmethod shift_by(offset: float) BaseMultiFun[source]

Create a new function shifted by a constant offset.

Parameters:

offset – The amount to add to all output values.

Returns:

A new function where f’(x) = f(x) + offset.

Return type:

BaseMultiFun

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

Serialize the value function to a dictionary.

Parameters:

python_class_identifier – Key to use for class type identification.

Returns:

Dictionary representation of the function.

Return type:

dict[str, Any]

xml(indx: int, issues: list[Issue] | tuple[Issue, ...], bias: float = 0) str[source]

Export this function to GENIUS XML format.

Parameters:
  • indx – The index of this function in the utility function.

  • issues – The issues this function operates on.

  • bias – Additional bias to add to values.

Returns:

XML string representation.

Return type:

str

Raises:

NotImplementedError – Multi-issue functions generally cannot be exported to GENIUS XML format.

class negmas.preferences.BasePref(*args, **kwargs)[source]

Bases: Protocol

Base Protcol for all preferences in NegMAS. All Preferences objects implement this interface

abstract property base_type: str[source]

Returns the utility_function base type ignoring discounting and similar wrappings.

abstractmethod is_session_dependent() bool[source]

Does the utiltiy of an outcome depend on the NegotiatorMechanismInterface?

abstractmethod is_state_dependent() bool[source]

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

abstractmethod is_stationary() bool[source]

Is the ufun stationary (i.e. utility value of an outcome is a constant)?

abstractmethod is_volatile() bool[source]

Does the utiltiy 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

abstract property type: str[source]

Returns the preferences type.

class negmas.preferences.BaseUtilityFunction(*args, reserved_value: float = -inf, invalid_value: float | None = None, **kwargs)[source]

Bases: Preferences, ABC

Base class for all utility functions in negmas

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

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]][source]

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[source]

Best.

Returns:

The result.

Return type:

Outcome

difference(first: tuple | None, second: tuple | None) float[source]

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

difference_prob(first: tuple | None, second: tuple | None) Distribution[source]

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

eu(offer: tuple | None) float[source]

calculates the expected utility value of the input outcome

abstractmethod eval(offer: tuple) Distribution | float[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Value

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

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 caached 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][source]

Extreme outcomes.

Parameters:
  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • max_cardinality – Max cardinality.

Returns:

The result.

Return type:

tuple[Outcome, Outcome]

forget_inverter()[source]

Deletes the cached inverter.

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

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

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][source]

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][source]

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][source]

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
invert(inverter: type[InverseUFun] | None = None, **kwargs) InverseUFun[source]

Inverts the ufun, initializes it and caches the result.

is_not_worse(first: tuple | None, second: tuple | None) bool[source]

Check if not worse.

Parameters:
  • first – First.

  • second – Second.

Returns:

The result.

Return type:

bool

is_session_dependent() bool[source]

Check if session dependent.

Returns:

The result.

Return type:

bool

is_state_dependent() bool[source]

Check if state dependent.

Returns:

The result.

Return type:

bool

is_volatile() bool[source]

Check if volatile.

Returns:

The result.

Return type:

bool

max() Distribution | float[source]

Max.

Returns:

The result.

Return type:

Value

min() Distribution | float[source]

Min.

Returns:

The result.

Return type:

Value

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][source]

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[source]

Normalize.

Parameters:
  • to – To.

  • normalize_weights – Normalize weights.

Returns:

The result.

Return type:

T | ConstUtilityFunction

normalize_for(to: tuple[float, float] = (0.0, 1.0), outcome_space: OutcomeSpace | None = None) T | ConstUtilityFunction[source]

Normalize for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

Returns:

The result.

Return type:

T | ConstUtilityFunction

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

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]][source]

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

property reserved_distribution: Distribution[source]

Reserved distribution.

Returns:

The result.

Return type:

Distribution

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[source]

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[source]

Scale by.

Parameters:
  • scale – Scale.

  • scale_reserved – Scale reserved.

Returns:

The result.

Return type:

WeightedUtilityFunction | T

scale_max(to: float, rng: tuple[float, float] | None = None) T[source]

Scale max.

Parameters:
  • to – To.

  • rng – Rng.

Returns:

The result.

Return type:

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[source]

Scale max for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

T

scale_min(to: float, rng: tuple[float, float] | None = None) T[source]

Scale min.

Parameters:
  • to – To.

  • rng – Rng.

Returns:

The result.

Return type:

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[source]

Scale min for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

T

shift_by(offset: float, shift_reserved=True) WeightedUtilityFunction | T[source]

Shift by.

Parameters:
  • offset – Offset.

  • shift_reserved – Shift reserved.

Returns:

The result.

Return type:

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[source]

Shift max for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

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[source]

Shift min for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

T

to_crisp() UtilityFunction[source]

To crisp.

Returns:

The result.

Return type:

UtilityFunction

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

Returns:

The result.

Return type:

dict[str, Any]

to_genius(file_name: PathLike | str, issues: Iterable[Issue] | None = None, **kwargs)[source]

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[source]

To prob.

Returns:

The result.

Return type:

ProbUtilityFunction

to_stationary() T[source]

To stationary.

Returns:

The result.

Return type:

T

to_xml_str(issues: Iterable[Issue] | None = None, discount_factor=None) str[source]

Exports a utility function to a well formatted string

worst() tuple[source]

Worst.

Returns:

The result.

Return type:

Outcome

class negmas.preferences.BilinearMultiFun(a: float, b: float, c: float, bias: float = 0)[source]

Bases: BaseMultiFun

Bilinear two-issue value function: f(x, y) = a*x + b*y + c*x*y + d.

A specialized function for exactly two issues with a bilinear interaction term. This is simpler than QuadraticMultiFun when you only need linear terms and their product (no squared terms).

Mathematical definition:

\[f(x, y) = a x + b y + c x y + d\]

where \(a\) and \(b\) are linear coefficients, \(c\) is the interaction coefficient, and \(d\) is the bias.

Parameters:
  • a – Coefficient for the first issue \(x\).

  • b – Coefficient for the second issue \(y\).

  • c – Interaction coefficient for \(xy\).

  • bias – Constant offset \(d\) (default: 0).

Example

>>> f = BilinearMultiFun(a=2.0, b=3.0, c=1.0, bias=0.0)
>>> f((1, 1))  # 2*1 + 3*1 + 1*1*1 = 6
6.0
>>> f((2, 3))  # 2*2 + 3*3 + 1*2*3 = 4 + 9 + 6 = 19
19.0

Note

This is a special case of QuadraticMultiFun with quadratic=(0,0). Use QuadraticMultiFun if you need squared terms.

a: float[source]
b: float[source]
bias: float[source]
c: float[source]
property dim: int[source]

Return the number of issues (always 2).

Returns:

Always returns 2.

Return type:

int

minmax(input: Iterable[Issue]) tuple[float, float][source]

Find the minimum and maximum values over the issues’ domains.

Parameters:

input – The issues whose combined domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

Return type:

tuple[float, float]

scale_by(scale: float) BilinearMultiFun[source]

Create a new function scaled by a constant factor.

Parameters:

scale – The factor to multiply all output values by.

Returns:

A new function where f’(x) = scale * f(x).

Return type:

BilinearMultiFun

shift_by(offset: float) BilinearMultiFun[source]

Create a new function shifted by a constant offset.

Parameters:

offset – The amount to add to all output values.

Returns:

A new function where f’(x) = f(x) + offset.

Return type:

BilinearMultiFun

class negmas.preferences.CardinalCrisp(*args, **kwargs)[source]

Bases: CardinalProb, Protocol

Differences between outcomes are meaningfull and crisp (i.e. real numbers)

abstractmethod difference(first: tuple, second: tuple) float[source]

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

class negmas.preferences.CardinalProb(*args, **kwargs)[source]

Bases: Ordinal, Protocol

Differences between outcomes are meaningfull but probabilistic.

Remarks:

Inheriting from this class adds is_not_worse implementation that is extremely conservative. It declares that first is not worse than second only if any sample form first is ALWAYS not worse than any sample from second.

abstractmethod difference_prob(first: tuple, second: tuple) Distribution[source]

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

class negmas.preferences.CardinalRanking(*args, **kwargs)[source]

Bases: Protocol

Implements ranking of outcomes with meaningful differences (i.e. each rank is given a value and nearer values are more similar)

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

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

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

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

class negmas.preferences.ComplexNonlinearUtilityFunction(ufuns: Iterable[BaseUtilityFunction], combination_function: Callable[[Iterable[Distribution | float]], Distribution | float], **kwargs)[source]

Bases: _DependenceMixin, BaseUtilityFunction

A utility function composed of nonlinear aggregation of other utility functions

Parameters:
  • ufuns – An iterable of utility functions

  • combination_function – The function used to combine results of ufuns

  • name – Utility function name

eval(offer: tuple) Distribution | float[source]

Calculate the utility_function value for a given outcome.

Parameters:

offer – The offer to be evaluated.

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

  • Return A Value not a float for real-valued utilities for the benefit of inspection code.

Returns:

The utility_function value which may be a distribution. If None it means the utility_function value cannot be calculated.

Return type:

Value

classmethod from_dict(d: dict[str, Any], python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

classmethod random(outcome_space, reserved_value, normalized=True, n_ufuns=(1, 4), ufun_types=(<class 'negmas.preferences.crisp.linear.LinearAdditiveUtilityFunction'>, ), **kwargs) ComplexNonlinearUtilityFunction[source]

Generates a random ufun of the given type

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

Returns:

The result.

Return type:

dict[str, Any]

to_stationary()[source]

Returns a stationary version with all component utility functions converted to stationary.

class negmas.preferences.ConstFun(bias: float)[source]

Bases: BaseFun

Constant value function: f(x) = bias.

Returns the same value regardless of input. Useful for issues that don’t affect utility, or as a building block for more complex functions.

Mathematical definition:

\[f(x) = c\]

where \(c\) is a constant (the bias parameter).

Parameters:

bias – The constant value \(c\) to return.

Example

>>> f = ConstFun(bias=5.0)
>>> f(0)
5.0
>>> f(100)
5.0
>>> f("anything")
5.0
bias: float[source]
minmax(input: Issue) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) AffineFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

AffineFun

shift_by(offset: float) ConstFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

ConstFun

xml(indx: int, issue: Issue, bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.ConstUtilityFunction(value: Distribution | float, *, reserved_value: float = -inf, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A utility function that returns the same value for all outcomes.

This type of ufun can be considered a special type of LinearUtilityFunction with zero slop but it is applicable to any type of issue not only numeric ones.

eval(offer: tuple) float[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

float

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

classmethod random(issues, reserved_value=(0.0, 1.0), normalized=True, value_range=(0.0, 1.0), **kwargs) ConstUtilityFunction[source]

Generates a random ufun of the given type

to_dict(python_class_identifier='__python_class__')[source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

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

Xml.

Parameters:

issues – Issues.

Returns:

The result.

Return type:

str

class negmas.preferences.CosFun(multiplier: float = 1.0, bias: float = 0.0, phase: float = 0.0, amplitude: float = 1.0)[source]

Bases: BaseFun

Cosine value function.

Maps numeric issue values to utilities using a cosine function.

Mathematical definition:

\[f(x) = A \cos(\omega x + \phi) + b\]

where \(A\) is the amplitude, \(\omega\) is the angular frequency (multiplier), \(\phi\) is the phase shift, and \(b\) is the bias.

Parameters:
  • multiplier – Angular frequency \(\omega\) (default: 1.0).

  • bias – Vertical offset \(b\) (default: 0.0).

  • phase – Phase shift \(\phi\) in radians (default: 0.0).

  • amplitude – Amplitude \(A\) (default: 1.0).

Example

>>> import math
>>> f = CosFun()  # f(x) = cos(x)
>>> abs(f(0) - 1.0) < 1e-10  # cos(0) = 1
True
>>> abs(f(math.pi) - (-1.0)) < 1e-10  # cos(pi) = -1
True

Note

The function oscillates between bias - amplitude and bias + amplitude with period \(2\pi / \omega\).

amplitude: float[source]
bias: float[source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

multiplier: float[source]
phase: float[source]
scale_by(scale: float) CosFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

CosFun

shift_by(offset: float) CosFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

CosFun

xml(indx: int, issue: Issue, bias) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.DiscountedUtilityFunction(ufun: BaseUtilityFunction, **kwargs)[source]

Bases: StateDependentUFunMixin, BaseUtilityFunction

Base class for all discounted ufuns

is_state_dependent()[source]

Check if state dependent.

to_stationary()[source]

Returns the underlying stationary (non-discounted) utility function.

class negmas.preferences.Distribution(*args, **kwargs)[source]

Bases: Protocol

A protocol representing a probability distribution

cum_prob(mn: float, mx: float) float[source]

Returns the probability for the given range

is_crisp() bool[source]

Returns true if this is a distribution with all probability at one point (delta(v))

is_gaussian() bool[source]

Returns true if this is a gaussian distribution

is_uniform() bool[source]

Returns true if this is a uniform distribution

property loc: float[source]

Returns the location of the distributon (usually mean)

property max: float[source]

Returns the maximum

mean() float[source]

Finds the mean

property min: float[source]

Returns the minimum

prob(val: float) float[source]

Returns the probability for the given value

sample(size: int = 1) Iterable[float][source]

Samples size elements from the distribution

property scale: float[source]

Returns the scale of the distribution (may be std. dev.)

type() str[source]

Returns the distribution type (e.g. uniform, normal, …)

class negmas.preferences.ExpDiscountedUFun(ufun: BaseUtilityFunction, discount: float | None = None, factor: str | Callable[[MechanismState], float] = 'step', name=None, reserved_value: Distribution | float = -inf, dynamic_reservation=True, id=None, **kwargs)[source]

Bases: DiscountedUtilityFunction

A discounted utility function based on some factor of the negotiation

Parameters:
  • ufun – The utility function that is being discounted

  • discount – discount factor

  • factor (callable -> must receive a mechanism info object and returns a float representing the) – str -> The name of the AgentMechanismInterface variable based on which discounting operate

  • factor

property base_type[source]

Returns the type name of the underlying utility function.

eval_on_state(offer: tuple, nmi: NegotiatorMechanismInterface | None = None, state: MechanismState | None = None)[source]

Evaluates discounted utility for an offer given the current negotiation state.

Parameters:
  • offer – The outcome to evaluate.

  • nmi – Negotiator-mechanism interface (optional).

  • state – Current mechanism state used to compute the discount factor.

classmethod from_dict(d: dict[str, Any], python_class_identifier='__python_class__')[source]

Creates an instance from a dictionary representation.

Parameters:
  • d – Dictionary containing serialized utility function data.

  • python_class_identifier – Key used to identify the class type.

minmax(outcome_space=None, issues=None, outcomes=None, max_cardinality=10000, above_reserve=False) tuple[float, float][source]

Finds minimum and maximum utility values over the outcome space.

Parameters:
  • outcome_space – The outcome space to search. Uses self.outcome_space if None.

  • issues – Alternative way to specify outcomes via issues.

  • outcomes – Explicit list of outcomes to evaluate.

  • max_cardinality – Maximum outcomes to sample for large spaces.

  • above_reserve – If True, only consider outcomes above reserved value.

Returns:

Tuple of (minimum utility, maximum utility).

classmethod random(issues, reserved_value=(0.0, 1.0), normalized=True, discount_range=(0.8, 1.0), base_preferences_type: str | type[BaseUtilityFunction] = 'negmas.LinearAdditiveUtilityFunction', **kwargs) ExpDiscountedUFun[source]

Generates a random ufun of the given type

scale_by(scale: float, scale_reserved: bool = True) ExpDiscountedUFun[source]

Returns a new utility function with all values scaled by a factor.

Parameters:
  • scale – Multiplier for all utility values.

  • scale_reserved – If True, also scale the reserved value.

Returns:

New ExpDiscountedUFun with scaled values.

shift_by(offset: float, shift_reserved: bool = True) ExpDiscountedUFun[source]

Returns a new utility function with all values shifted by offset.

Parameters:
  • offset – Amount to add to all utility values.

  • shift_reserved – If True, also shift the reserved value.

Returns:

New ExpDiscountedUFun with shifted values.

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

Serializes this utility function to a dictionary.

Parameters:

python_class_identifier – Key used to store the class type.

Returns:

Dictionary representation suitable for JSON serialization.

property type[source]

Type.

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

Serializes this utility function to XML format (Genius compatibility).

Parameters:

issues – List of issues defining the negotiation domain.

Returns:

XML string representation.

class negmas.preferences.ExponentialFun(tau: float, bias: float = 0, base: float = 2.718281828459045)[source]

Bases: BaseFun

Exponential value function: f(x) = base^(tau*x) + bias.

Maps numeric issue values to utilities using an exponential function.

Mathematical definition:

\[f(x) = a^{\tau x} + b\]

where \(a\) is the base, \(\tau\) is the rate parameter, and \(b\) is the bias.

Parameters:
  • tau – Rate parameter \(\tau\) controlling growth/decay speed.

  • bias – Constant offset \(b\) (default: 0).

  • base – Exponential base \(a\) (default: e ≈ 2.718).

Example

>>> import math
>>> f = ExponentialFun(tau=1.0)  # f(x) = e^x
>>> abs(f(0) - 1.0) < 1e-10  # e^0 = 1
True
>>> abs(f(1) - math.e) < 1e-10  # e^1 = e
True

Note

  • For \(\tau > 0\): function grows with increasing x

  • For \(\tau < 0\): function decays with increasing x

  • Common bases: e (natural), 2 (binary), 10 (decimal)

base: float[source]
bias: float[source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) ExponentialFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

ExponentialFun

shift_by(offset: float) ExponentialFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

ExponentialFun

tau: float[source]
xml(indx: int, issue: Issue, bias) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.GLAUtilityFunction(factors: Sequence[tuple[tuple[int | str, ...], BaseFun | BaseMultiFun | Callable[[Any], float] | Mapping[Any, float] | float] | tuple[tuple[int | str, ...], BaseFun | BaseMultiFun | Callable[[Any], float] | Mapping[Any, float] | float, float]], weights: Sequence[float] | None = None, bias: float = 0.0, *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A Generalized Linear Aggregation Utility Function.

Unlike LinearAdditiveUtilityFunction which has one function per issue, this class allows each factor to operate on any subset of issues.

Parameters:
  • factors

    A list of tuples, where each tuple contains: - issue_indices: A tuple of issue indices (or names) that the factor operates on - function: The factor function (can be BaseFun subclass,

    Callable, Mapping/dict, or a constant float)

  • weights – Optional weights for combining factors (defaults to 1.0 for each)

  • bias – A constant bias term added to the final utility

  • name – Name of the utility function

Notes

The utility value is calculated as:

\[u = b + \sum_{k=0}^{n_{factors}-1} {w_k * f_k(\omega_{I_k})}\]

where $b$ is the bias, $w_k$ is the weight for factor $k$, $f_k$ is the factor function, and $omega_{I_k}$ represents the values of issues in the index set $I_k$ for outcome $omega$.

Examples

>>> from negmas.outcomes import make_issue
>>> from negmas.preferences.value_fun import LinearMultiFun
>>> issues = [
...     make_issue(10, "A"),
...     make_issue(5, "B"),
...     make_issue(["x", "y", "z"], "C"),
...     make_issue((0.0, 1.0), "D"),
...     make_issue(4, "E"),
... ]

Create a GLA utility function with various factor types:

>>> f = GLAUtilityFunction(
...     factors=[
...         # Factor on issue A (affine function)
...         (("A",), AffineFun(slope=2.0, bias=1.0)),
...         # Factor on issues A and B (dict mapping)
...         (("A", "B"), {(0, 0): 1.0, (0, 1): 2.0, (1, 0): 3.0, (1, 1): 4.0}),
...         # Factor on issues A, C, E (lambda function)
...         (("A", "C", "E"), lambda x: x[0] + (1 if x[1] == "x" else 0) + x[2]),
...         # Factor on issue D only
...         (("D",), lambda x: x * 10),
...         # Factor on issues B and C (multivariate polynomial-like)
...         (("B", "C"), AffineMultiFun(slope=(1.0, 0.0), bias=0.5)),
...         # Constant factor (interaction term for D and A)
...         (("D", "A"), LinearMultiFun(slope=(1.0, 0.5))),
...     ],
...     weights=[1.0, 0.5, 2.0, 1.0, 0.3, 0.2],
...     issues=issues,
... )

Evaluate the utility of an outcome:

>>> outcome = (2, 1, "x", 0.5, 3)  # A=2, B=1, C="x", D=0.5, E=3
>>> u = f(outcome)
>>> isinstance(u, float)
True
Remarks:
  • Factor functions can be:
    • Single-issue functions: AffineFun, LinearFun, TableFun, LambdaFun, etc.

    • Multi-issue functions: TableMultiFun, AffineMultiFun, LambdaMultiFun, etc.

    • Callable: Any callable taking a value (single issue) or tuple (multi-issue)

    • Mapping/dict: A mapping from values/tuples to utilities

    • float: A constant value (useful for bias terms on specific issue combinations)

  • Issue indices can be integers or issue names (strings)

  • The outcome space must have independent issues (CartesianOutcomeSpace)

property bias: float[source]

Return the bias term.

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Parameters:

offer – The outcome to evaluate.

Returns:

The utility value.

property factors: list[tuple[tuple[int, ...], BaseFun | BaseMultiFun]][source]

Return the list of factors.

classmethod from_dict(d: dict, python_class_identifier='__python_class__') GLAUtilityFunction[source]

Create from dictionary.

Parameters:
  • d – Dictionary representation.

  • python_class_identifier – The key used for the Python class name.

Returns:

GLAUtilityFunction instance.

classmethod random(outcome_space: CartesianOutcomeSpace | None = None, issues: list[Issue] | tuple[Issue, ...] | None = None, reserved_value: tuple[float, float] = (0.0, 1.0), normalized: bool = True, n_factors: int | tuple[int, int] = (1, 5), max_factor_issues: int = 3, **kwargs) GLAUtilityFunction[source]

Generate a random GLA utility function.

Parameters:
  • outcome_space – The outcome space.

  • issues – The issues (used if outcome_space is not provided).

  • reserved_value – Range for random reserved value.

  • normalized – Whether to normalize weights.

  • n_factors – Number of factors or range (min, max).

  • max_factor_issues – Maximum number of issues per factor.

  • **kwargs – Additional arguments passed to the constructor.

Returns:

A random GLAUtilityFunction.

scale_by(scale: float, scale_reserved: bool = True) GLAUtilityFunction[source]

Create a scaled version of this utility function.

Parameters:
  • scale – The scaling factor.

  • scale_reserved – Whether to also scale the reserved value.

Returns:

A new scaled GLAUtilityFunction.

shift_by(offset: float, shift_reserved: bool = True) GLAUtilityFunction[source]

Create a shifted version of this utility function.

Parameters:
  • offset – The amount to shift by.

  • shift_reserved – Whether to also shift the reserved value.

Returns:

A new shifted GLAUtilityFunction.

to_dict(python_class_identifier='__python_class__') dict[source]

Convert to dictionary for serialization.

Parameters:

python_class_identifier – The key to use for the Python class name.

Returns:

Dictionary representation.

property weights: list[float][source]

Return the weights.

xml(issues: list[Issue] | None = None) str[source]

Generate an XML string representing the utility function.

Parameters:

issues – The issues (uses self.issues if not provided).

Returns:

XML string representation.

Raises:

NotImplementedError – GLA utility functions cannot be fully represented in GENIUS XML format.

class negmas.preferences.GPAUtilityFunction(factors: Sequence[tuple[tuple[int | str, ...], BaseFun | BaseMultiFun | Callable[[Any], float] | Mapping[Any, float] | float]], terms: Sequence[tuple[float, tuple[int, ...]]], bias: float = 0.0, *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A Generalized Polynomial Aggregation Utility Function.

Like GLAUtilityFunction, each factor can operate on any subset of issues. However, instead of linearly aggregating factor results, this class uses polynomial expansion where each term is a product of factor values raised to specified powers.

Mathematical definition:

\[u(\omega) = b + \sum_{k} c_k \prod_{j} f_j(\omega_{I_j})^{p_{kj}}\]
where:
  • \(b\) is the bias

  • \(c_k\) is the coefficient for term \(k\)

  • \(f_j\) is the factor function for factor \(j\)

  • \(\omega_{I_j}\) are the issue values for factor \(j\)

  • \(p_{kj}\) is the power of factor \(j\) in term \(k\)

Parameters:
  • factors – A list of tuples, where each tuple contains: - issue_indices: A tuple of issue indices (or names) that the factor operates on - function: The factor function (can be BaseFun, Callable, Mapping, or float)

  • terms – A list of polynomial terms, where each term is a tuple of: - coefficient: The coefficient for this term - powers: A tuple of powers for each factor (length must match number of factors)

  • bias – A constant bias term added to the final utility

  • name – Name of the utility function

Examples

>>> from negmas.outcomes import make_issue
>>> from negmas.preferences.value_fun import AffineFun
>>> issues = [make_issue(10, "A"), make_issue(10, "B"), make_issue(10, "C")]

Create factors a, b, c based on issues:

>>> factors = [
...     (("A",), AffineFun(slope=1.0, bias=0.0)),  # a = A
...     (("B",), AffineFun(slope=1.0, bias=0.0)),  # b = B
...     (("C",), AffineFun(slope=1.0, bias=0.0)),  # c = C
... ]

Define polynomial: u = a^3 + b^2*c + a*b*c^2

>>> terms = [
...     (1.0, (3, 0, 0)),  # a^3
...     (1.0, (0, 2, 1)),  # b^2 * c
...     (1.0, (1, 1, 2)),  # a * b * c^2
... ]
>>> f = GPAUtilityFunction(factors=factors, terms=terms, issues=issues)

Evaluate: for outcome (2, 3, 4): a=2, b=3, c=4 u = 2^3 + 3^2*4 + 2*3*4^2 = 8 + 36 + 96 = 140

>>> f((2, 3, 4))
140.0
Remarks:
  • Factor functions can be any of the types supported by GLAUtilityFunction

  • Powers of 0 exclude a factor from a term (factor^0 = 1)

  • For linear aggregation (like GLAUtilityFunction), use powers of (1, 0, 0, …), (0, 1, 0, …), etc. with appropriate coefficients as weights

property bias: float[source]

Return the bias term.

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Parameters:

offer – The outcome to evaluate.

Returns:

The utility value.

property factors: list[tuple[tuple[int, ...], BaseFun | BaseMultiFun]][source]

Return the list of factors.

classmethod from_dict(d: dict, python_class_identifier='__python_class__') GPAUtilityFunction[source]

Create from dictionary.

classmethod random(outcome_space: CartesianOutcomeSpace | None = None, issues: list[Issue] | tuple[Issue, ...] | None = None, reserved_value: tuple[float, float] = (0.0, 1.0), normalized: bool = True, n_factors: int | tuple[int, int] = (2, 4), n_terms: int | tuple[int, int] = (2, 5), max_factor_issues: int = 2, max_power: int = 3, **kwargs) GPAUtilityFunction[source]

Generate a random GPA utility function.

Parameters:
  • outcome_space – The outcome space.

  • issues – The issues (used if outcome_space is not provided).

  • reserved_value – Range for random reserved value.

  • normalized – Whether to normalize coefficients.

  • n_factors – Number of factors or range (min, max).

  • n_terms – Number of polynomial terms or range (min, max).

  • max_factor_issues – Maximum number of issues per factor.

  • max_power – Maximum power for any factor in a term.

  • **kwargs – Additional arguments passed to the constructor.

Returns:

A random GPAUtilityFunction.

scale_by(scale: float, scale_reserved: bool = True) GPAUtilityFunction[source]

Create a scaled version of this utility function.

shift_by(offset: float, shift_reserved: bool = True) GPAUtilityFunction[source]

Create a shifted version of this utility function.

property terms: list[tuple[float, tuple[int, ...]]][source]

Return the polynomial terms.

to_dict(python_class_identifier='__python_class__') dict[source]

Convert to dictionary for serialization.

xml(issues: list[Issue] | None = None) str[source]

Generate an XML string representing the utility function.

Raises:

NotImplementedError – GPA utility functions cannot be represented in GENIUS XML format.

class negmas.preferences.HasRange(*args, **kwargs)[source]

Bases: HasMinMax, UFun, Protocol

Has a defined range of utility values (a minimum and a maximum) and defined best and worst outcomes

best() tuple[source]

Returns best outcome

extreme_outcomes(outcome_space: OutcomeSpace | None = None, issues: list[Issue] | None = None, outcomes: list[Outcome] | int | None = None, max_cardinality=1000) tuple[Outcome, Outcome][source]

Finds the best and worst outcomes

Parameters:
  • ufun – 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)

Returns:

(worst, best) outcomes

max() Distribution | float[source]

Returns maximum utility

min() Distribution | float[source]

Returns minimum utility

minmax(outcome_space: OutcomeSpace | None = None, issues: list[Issue] | None = None, outcomes: list[Outcome] | int | None = None, max_cardinality=1000, above_reserve=False) tuple[float, float][source]

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

worst() tuple[source]

Returns worst outcome

class negmas.preferences.HasReservedDistribution(*args, **kwargs)[source]

Bases: Protocol

In case of disagreement, a value sampled from reserved_distribution will be received by the entity

reserved_distribution: Distribution[source]
class negmas.preferences.HasReservedOutcome(*args, **kwargs)[source]

Bases: Protocol

In case of disagreement, the value of reserved_outcome will be received by the entity

reserved_outcome: tuple[source]
class negmas.preferences.HasReservedValue(*args, **kwargs)[source]

Bases: Protocol

In case of disagreement, reserved_value will be received by the entity

property reserved_distribution: Distribution[source]

Reserved distribution.

Returns:

The result.

Return type:

Distribution

reserved_value: float[source]
class negmas.preferences.HyperRectangleUtilityFunction(outcome_ranges: Iterable[Mapping[int, Any] | None], utilities: list[float] | list[Callable[[tuple | None], Distribution | float] | Mapping[tuple | None, Distribution | float]], weights: list[float] | None = None, ignore_issues_not_in_input=False, ignore_failing_range_utilities=False, bias: float = 0.0, *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A utility function defined as a set of hyper-volumes.

The utility function that is calulated by combining linearly a set of probably nonlinear functions applied in predefined hyper-volumes of the outcome space.

Parameters:
  • outcome_ranges – The outcome_ranges for which the mappings are defined

  • weights – The optional weights to use for combining the outputs of the mappings

  • ignore_issues_not_in_input – If a hyper-volumne local function is defined for some issue

  • it. (that is not in the outcome being evaluated ignore)

  • ignore_failing_range_utilities – If a hyper-volume local function fails, just assume it

  • outcome. (did not exist for this)

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

Notes

The utility value is calculated as:

\[u(\omega) = b + \sum_{k: \omega \in R_k} w_k \cdot f_k(\omega)\]

where \(b\) is the bias term, \(R_k\) are hyper-rectangular regions of the outcome space, \(w_k\) are the weights for each region, and \(f_k\) is either a constant or a function that maps outcomes to utility values within region \(R_k\).

Examples:

We will use the following issue space of cardinality \(10 \times 5 \times 4\):

>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(10), make_issue(5), make_issue(4)]

Now create the utility function with

>>> 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, lambda x: 2 * x[2] + x[0]],
... )
>>> g = 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, lambda x: 2 * x[2] + x[0]],
...     ignore_issues_not_in_input=True,
... )
>>> h = 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, lambda x: 2 * x[2] + x[0]],
...     ignore_failing_range_utilities=True,
... )

We can now calcualte the utility_function of some outcomes:

An outcome that belongs to the both outcome_ranges:

>>> [
...     f({0: 1.5, 1: 1.5, 2: 2.5}),
...     g({0: 1.5, 1: 1.5, 2: 2.5}),
...     h({0: 1.5, 1: 1.5, 2: 2.5}),
... ]
[8.5, 8.5, 8.5]

An outcome that belongs to the first hypervolume only:

>>> [
...     f({0: 1.5, 1: 1.5, 2: 1.0}),
...     g({0: 1.5, 1: 1.5, 2: 1.0}),
...     h({0: 1.5, 1: 1.5, 2: 1.0}),
... ]
[2.0, 2.0, 2.0]

An outcome that belongs to and has the first hypervolume only:

>>> [f({0: 1.5}), g({0: 1.5}), h({0: 1.5})]
[nan, 0.0, nan]

An outcome that belongs to the second hypervolume only:

>>> [f({0: 1.5, 2: 2.5}), g({0: 1.5, 2: 2.5}), h({0: 1.5, 2: 2.5})]
[nan, 6.5, nan]

An outcome that has and belongs to the second hypervolume only:

>>> [f({2: 2.5}), g({2: 2.5}), h({2: 2.5})]
[nan, 0.0, nan]

An outcome that belongs to no outcome_ranges:

>>> [
...     f({0: 11.5, 1: 11.5, 2: 12.5}),
...     g({0: 11.5, 1: 11.5, 2: 12.5}),
...     h({0: 11.5, 1: 11.5, 2: 12.5}),
... ]
[0.0, 0.0, 0.0]
Remarks:
  • The number of outcome_ranges, mappings, and weights must be the same

  • if no weights are given they are all assumed to equal unity

  • mappings can either by an OutcomeUtilityMapping or a constant.

adjust_params()[source]

Initialize default weights if not provided.

Sets all weights to 1.0 if no weights were specified.

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Computes u = bias + sum(w_k * f_k(omega)) for all regions k containing omega.

Parameters:

offer – The outcome to evaluate. If None, returns the reserved value.

Returns:

The utility value for the given outcome. Returns NaN if the outcome contains issues not covered by hyper-rectangles and ignore_issues_not_in_input is False.

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

Create an instance from a dictionary.

Parameters:
  • d – Dictionary containing the serialized utility function.

  • python_class_identifier – Key used to identify the class type.

Returns:

A new HyperRectangleUtilityFunction instance.

classmethod random(outcome_space, reserved_value, normalized=True, rectangles=(1, 4), **kwargs) HyperRectangleUtilityFunction[source]

Generate a random hyper-rectangle utility function.

Parameters:
  • outcome_space – The outcome space to generate the utility function for.

  • reserved_value – The reserved value (utility of disagreement).

  • normalized – Whether to normalize the utility values.

  • rectangles – Range (min, max) for the number of rectangles.

  • **kwargs – Additional arguments.

Raises:

NotImplementedError – Random generation is not yet implemented.

to_dict(python_class_identifier='__python_class__')[source]

Convert to a dictionary for serialization.

Parameters:

python_class_identifier – Key used to store the class type identifier.

Returns:

Dictionary representation suitable for JSON serialization.

to_stationary()[source]

Return a stationary version of this utility function.

Returns:

Self, as HyperRectangleUtilityFunction is already stationary.

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

Represents the function as XML

Parameters:

issues

Examples

>>> from negmas.outcomes import make_issue
>>> 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(
...         [
...             make_issue((0.0, 4.0), name="0"),
...             make_issue((0.0, 9.0), name="1"),
...             make_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="1" min="1.0" max="2.0" />
            <INCLUDES index="2" min="1.0" max="2.0" />
        </hyperRectangle>
        <hyperRectangle utility_function="13.0">
            <INCLUDES index="1" min="1.4" max="2.0" />
            <INCLUDES index="3" min="2.0" max="3.0" />
        </hyperRectangle>
    </ufun>
</utility_function>
class negmas.preferences.ILSUtilityFunction(type: str, loc: UtilityFunction, scale: UtilityFunction, *args, **kwargs)[source]

Bases: StationaryMixin, ProbUtilityFunction

A utility function which represents the loc and scale deviations as any crisp ufun

eval(offer: tuple) ScipyDistribution[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

ScipyDistribution

class negmas.preferences.IPUtilityFunction(outcomes: Iterable[tuple], distributions: Iterable[Distribution] | None = None, issue_names: Iterable[str] | None = None, **kwargs)[source]

Bases: StationaryMixin, ProbUtilityFunction

Independent Probabilistic Utility Function.

Parameters:
  • outcomes – Iterable of outcomes

  • distributions – the distributions. One for each outcome

  • name – ufun name

Examples

>>> outcomes = [("o1",), ("o2",)]
>>> f = IPUtilityFunction(
...     outcomes=outcomes,
...     distributions=[
...         ScipyDistribution(type="uniform", loc=0.0, scale=0.5),
...         ScipyDistribution(type="uniform", loc=0.1, scale=0.5),
...     ],
... )
>>> str(f(("o1",)))
'U(0.0, 0.5)'
distribution(outcome: tuple) Distribution[source]

Returns the distributon associated with a specific outcome :param outcome:

Returns:

eval(offer: tuple) Distribution[source]

Calculate the utility_function value for a given outcome.

Parameters:

offer – The offer to be evaluated.

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

  • Return A Distribution not a float for real-valued utilities for the benefit of inspection code.

classmethod from_mapping(mapping: dict[Outcome, Value], range: tuple[float, float] = (0.0, 1.0), uncertainty: float = 0.5, variability: float = 0.0, reserved_value: float = -inf) IPUtilityFunction[source]

Generates a distribution from which u may have been sampled :param mapping: mapping from outcomes to float values :param range: range of the utility_function values :param uncertainty: uncertainty level :param variability: The variability within the ufun :param reserved_value: The reserved value

Examples

  • No uncertainty

>>> mapping = dict(zip([("o1",), ("o2",)], [0.3, 0.7]))
>>> p = IPUtilityFunction.from_mapping(mapping, uncertainty=0.0)
>>> print(p)
{('o1',): 0.3, ('o2',): 0.7}
  • Full uncertainty

>>> mapping = dict(zip([("o1",), ("o2",)], [0.3, 0.7]))
>>> p = IPUtilityFunction.from_mapping(mapping, uncertainty=1.0)
>>> print(p)
{('o1',): U(0.0, 1.0), ('o2',): U(0.0, 1.0)}
  • some uncertainty

>>> mapping = dict(zip([("o1",), ("o2",)], [0.3, 0.7]))
>>> p = IPUtilityFunction.from_mapping(mapping, uncertainty=0.1)
>>> print([_.scale for _ in p.distributions.values()])
[0.1, 0.1]
>>> for k, v in p.distributions.items():
...     assert v.loc <= mapping[k]
Returns:

a new IPUtilityFunction

classmethod from_preferences(u: ProbMappingUtilityFunction, range: tuple[float, float] = (0.0, 1.0), uncertainty: float = 0.5, variability: float = 0.0) IPUtilityFunction[source]

Generates a distribution from which u may have been sampled :param u: :param range: range of the utility_function values :param uncertainty: uncertainty level

Examples

  • No uncertainty

>>> u = MappingUtilityFunction(
...     mapping=dict(zip([("o1",), ("o2",)], [0.3, 0.7]))
... )
>>> p = IPUtilityFunction.from_preferences(u, uncertainty=0.0)
>>> print(p)
{('o1',): 0.3, ('o2',): 0.7}
  • Full uncertainty

>>> u = MappingUtilityFunction(
...     mapping=dict(zip([("o1",), ("o2",)], [0.3, 0.7]))
... )
>>> p = IPUtilityFunction.from_preferences(u, uncertainty=1.0)
>>> print(p)
{('o1',): U(0.0, 1.0), ('o2',): U(0.0, 1.0)}
  • some uncertainty

>>> u = MappingUtilityFunction(
...     mapping=dict(zip([("o1",), ("o2",)], [0.3, 0.7]))
... )
>>> p = IPUtilityFunction.from_preferences(u, uncertainty=0.1)
>>> print([_.scale for _ in p.distributions.values()])
[0.1, 0.1]
>>> for k, v in p.distributions.items():
...     assert v.loc <= u(k)
Returns:

a new IPUtilityFunction

is_state_dependent()[source]

Check if state dependent.

key(outcome: tuple)[source]

Returns the key of the given outcome in self.distributions.

Parameters:

outcome

Returns:

tuple

classmethod random(outcome_space, reserved_value, normalized=True, dist_limits=(0.0, 1.0), **kwargs) IPUtilityFunction[source]

Generates a random ufun of the given type

sample() MappingUtilityFunction[source]

Samples the utility_function distribution to create a mapping utility function

Examples

>>> import random
>>> f = IPUtilityFunction(
...     outcomes=[("o1",), ("o2",)],
...     distributions=[
...         ScipyDistribution(type="uniform", loc=0.0, scale=0.2),
...         ScipyDistribution(type="uniform", loc=0.4, scale=0.5),
...     ],
... )
>>> u = f.sample()
>>> assert u(("o1",)) <= 0.2
>>> assert 0.4 <= u(("o2",)) <= 0.9
Returns:

MappingUtilityFunction

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

Xml.

Parameters:

issues – Issues.

Returns:

The result.

Return type:

str

class negmas.preferences.IdentityFun[source]

Bases: BaseFun

Identity value function: f(x) = x.

Returns the input value unchanged. Useful when the issue value directly represents the utility.

Mathematical definition:

\[f(x) = x\]

Example

>>> f = IdentityFun()
>>> f(5)
5
>>> f(3.14)
3.14
minmax(input: Issue) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) LinearFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

LinearFun

shift_by(offset: float) ConstFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

ConstFun

xml(indx: int, issue: Issue, bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.IndIssues(*args, **kwargs)[source]

Bases: BasePref, Protocol

The utility value depends on each Issue value through a value function that does not depend on any other issue. (i.e. can be modeled as a LinearAdditiveUtilityFunction

issues: list[Issue][source]
values: list[Callable[[Any], float]][source]
weights: list[float][source]
class negmas.preferences.InverseUFun(ufun: UFun)[source]

Bases: Protocol

Can be used to get one or more outcomes at a given range

abstractmethod best() tuple[source]

Finds the best outcome

abstractmethod best_in(rng: float | tuple[float, float], normalized: bool) tuple | None[source]

Finds an outcome with highest utility within the given range

Parameters:
  • rng – The range (or single value) of utility values to search for outcomes

  • normalized – if True, the input rng will be understood as ranging from 0-1 (1=max, 0=min) independent of the ufun actual range

abstractmethod extreme_outcomes() tuple[tuple, tuple][source]

Finds the worst and best outcomes that can be returned.

Remarks:

These may be different from the results of ufun.extreme_outcomes() as they can be approximate.

init()[source]

Used to intialize the inverse ufun. Any computationally expensive initialization should be done here not in the constructor.

initialized: bool[source]
abstractmethod max() float[source]

Finds the maximum utility value that can be returned.

Remarks:
  • May be different from the maximum of the whole ufun if there is approximation

abstractmethod min() float[source]

Finds the minimum utility value that can be returned.

Remarks:
  • May be different from the minimum of the whole ufun if there is approximation

abstractmethod minmax() tuple[float, float][source]

Finds the minimum and maximum utility values that can be returned.

Remarks:

These may be different from the results of ufun.minmax() as they can be approximate.

next_better() tuple | None[source]

Returns the rational outcome with utility just below the last one returned from this function

next_worse() tuple | None[source]

Returns the rational outcome with utility just below the last one returned from this function

abstractmethod one_in(rng: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]

Finds an outcmoe with the given utility value.

Parameters:
  • rng – The range (or single value) of utility values to search for outcomes

  • normalized – if True, the input rng will be understood as ranging from 0-1 (1=max, 0=min) independent of the ufun actual range

  • fall_back_to_higher – if True, any outcome above the minimum in the range will be returned if nothing can be found in the range

  • fall_back_to_best – if True, the best outcome will always be offered if no outcome in the given range is found.

abstractmethod some(rng: float | tuple[float, float], normalized: bool, n: int | None = None) list[tuple][source]

Finds a list of outcomes with utilities in the given range.

Parameters:
  • rng – The range (or single value) of utility values to search for outcomes

  • normalized – if True, the input rng will be understood as ranging from 0-1 (1=max, 0=min) independent of the ufun actual range

  • n – The maximum number of outcomes to return

Remarks:
  • If the ufun outcome space is continuous a sample of outcomes is returned

  • If the ufun outcome space is discrete all outcomes in the range are returned

ufun: UFun[source]
abstractmethod within_fractions(rng: tuple[float, float]) list[tuple][source]

Finds outocmes within the given fractions of utility values. rng is always assumed to be normalized between 0-1

abstractmethod within_indices(rng: tuple[int, int]) list[tuple][source]

Finds outocmes within the given indices with the best at index 0 and the worst at largest index.

Remarks:
  • Works only for discrete outcome spaces

abstractmethod worst() tuple[source]

Finds the worst outcome

abstractmethod worst_in(rng: float | tuple[float, float], normalized: bool) tuple | None[source]

Finds an outcome with lowest utility within the given range

Parameters:
  • rng – The range (or single value) of utility values to search for outcomes

  • normalized – if True, the input rng will be understood as ranging from 0-1 (1=max, 0=min) independent of the ufun actual range

class negmas.preferences.LambdaFun(f: Callable[[Any], float], bias: float = 0, min_value: float | None = None, max_value: float | None = None)[source]

Bases: BaseFun

Lambda-based value function using an arbitrary callable.

Wraps any callable (function, lambda, etc.) as a value function. This provides maximum flexibility when predefined functions don’t suffice.

Mathematical definition:

\[f(x) = g(x) + b\]

where \(g\) is the user-provided callable and \(b\) is an optional bias.

Parameters:
  • f – A callable that takes an issue value and returns a float.

  • bias – Constant offset added to the callable’s output (default: 0).

  • min_value – Known minimum value (optional, for optimization).

  • max_value – Known maximum value (optional, for optimization).

Example

>>> f = LambdaFun(f=lambda x: x**2)
>>> f(3)  # 3^2 = 9
9
>>> f = LambdaFun(f=lambda x: x**2, bias=1.0)
>>> f(3)  # 3^2 + 1 = 10
10.0

Warning

Lambda functions can be serialized, but complex callables (e.g., closures with external state) may not serialize correctly.

bias: float[source]
f: Callable[[Any], float][source]
max_value: float | None[source]
min_value: float | None[source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) LambdaFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

LambdaFun

shift_by(offset: float, change_bias: bool = False) LambdaFun[source]

Shift by.

Parameters:
  • offset – Offset.

  • change_bias – Change bias.

Returns:

The result.

Return type:

LambdaFun

xml(indx: int, issue: Issue, bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.LambdaMultiFun(f: Callable[[Any], float], bias: float = 0, min_value: float | None = None, max_value: float | None = None)[source]

Bases: BaseMultiFun

Lambda-based multi-issue value function using an arbitrary callable.

Wraps any callable (function, lambda, etc.) as a multi-issue value function. This provides maximum flexibility for modeling complex interactions between issues.

Mathematical definition:

\[f(\mathbf{x}) = g(\mathbf{x}) + b\]

where \(g\) is the user-provided callable and \(b\) is an optional bias.

Parameters:
  • f – A callable that takes a tuple of issue values and returns a float.

  • bias – Constant offset added to the callable’s output (default: 0).

  • min_value – Known minimum value (optional, for optimization).

  • max_value – Known maximum value (optional, for optimization).

Example

>>> # Model interaction: value is product of issue values
>>> f = LambdaMultiFun(f=lambda x: x[0] * x[1])
>>> f((3, 4))  # 3 * 4 = 12
12
>>> # With bias
>>> f = LambdaMultiFun(f=lambda x: x[0] * x[1], bias=1.0)
>>> f((3, 4))  # 3 * 4 + 1 = 13
13.0

Warning

Lambda functions can be serialized, but complex callables (e.g., closures with external state) may not serialize correctly.

bias: float[source]
property dim: int[source]

Dim.

Returns:

The result.

Return type:

int

f: Callable[[Any], float][source]
max_value: float | None[source]
min_value: float | None[source]
minmax(input: Iterable[Issue]) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) LinearMultiFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

LinearMultiFun

shift_by(offset: float) AffineMultiFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

AffineMultiFun

xml(indx, issues, bias: float = 0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issues – Issues.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.LinDiscountedUFun(ufun: BaseUtilityFunction, cost: float | None = None, factor: str | Callable[[MechanismState], float] = 'current_step', power: float | None = 1.0, name=None, reserved_value: Distribution | float = -inf, dynamic_reservation=True, id=None, **kwargs)[source]

Bases: DiscountedUtilityFunction

A utility function with linear discounting based on some factor of the negotiation

Parameters:
  • ufun – The utility function that is being discounted

  • cost – discount factor

  • factor (callable -> must receive a mechanism info object and returns a float representing the) – str -> The name of the AgentMechanismInterface variable based on which discounting operate

  • factor

  • power – A power to raise the total cost to before discounting it from the utility_function value

property base_type[source]

Returns the type name of the underlying utility function.

eval_on_state(offer: tuple, nmi: NegotiatorMechanismInterface | None = None, state: MechanismState | None = None)[source]

Evaluates discounted utility for an offer given the current negotiation state.

Parameters:
  • offer – The outcome to evaluate.

  • nmi – Negotiator-mechanism interface (optional).

  • state – Current mechanism state used to compute the discount factor.

classmethod from_dict(d: dict[str, Any], python_class_identifier='__python_class__')[source]

Creates an instance from a dictionary representation.

Parameters:
  • d – Dictionary containing serialized utility function data.

  • python_class_identifier – Key used to identify the class type.

minmax(outcome_space=None, issues=None, outcomes=None, max_cardinality=10000, above_reserve=False) tuple[float, float][source]

Finds minimum and maximum utility values over the outcome space.

Parameters:
  • outcome_space – The outcome space to search. Uses self.outcome_space if None.

  • issues – Alternative way to specify outcomes via issues.

  • outcomes – Explicit list of outcomes to evaluate.

  • max_cardinality – Maximum outcomes to sample for large spaces.

  • above_reserve – If True, only consider outcomes above reserved value.

Returns:

Tuple of (minimum utility, maximum utility).

classmethod random(issues, reserved_value=(0.0, 1.0), normalized=True, cost_range=(0.8, 1.0), power_range=(0.0, 1.0), base_preferences_type: type[BaseUtilityFunction] | str = 'negmas.LinearAdditiveUtilityFunction', **kwargs) LinDiscountedUFun[source]

Generates a random ufun of the given type

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

Serializes this utility function to a dictionary.

Parameters:

python_class_identifier – Key used to store the class type.

Returns:

Dictionary representation suitable for JSON serialization.

property type[source]

Type.

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

Serializes this utility function to XML format (Genius compatibility).

Parameters:

issues – List of issues defining the negotiation domain.

Returns:

XML string representation.

class negmas.preferences.LinearAdditiveUtilityFunction(values: dict[str, SingleIssueFun] | tuple[SingleIssueFun, ...] | list[SingleIssueFun], weights: Mapping[Any, float] | list[float] | tuple[float, ...] | None = None, bias: float = 0.0, *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A linear aggregation utility function for multi-issue negotiations.

Models a linear utility function using predefined weights:.

Parameters:
  • values – utility functions for individual issues

  • weights – weights for combining values

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

Notes

The utility value is calculated as:

\[u = \sum_{i=0}^{n_{outcomes}-1} {w_i * u_i(\omega_i)}\]

Examples

>>> from negmas.outcomes import dict2outcome, make_issue
>>> 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)']
>>> f = LinearAdditiveUtilityFunction(
...     {
...         "price": lambda x: 2.0 * x,
...         "delivery": {"delivered": 10, "not delivered": -10},
...         "quality": lambda x: x - 3,
...     },
...     weights={"price": 1.0, "delivery": 2.0, "quality": 4.0},
...     issues=issues,
... )
>>> float(f((2, "delivered", 14.0)))
68.0

You can confirm this yourself by calculating the ufun manually:

>>> 68.0 == (1.0 * 2.0 * 2 + 2.0 * 10 + 4.0 * (14.0 - 3))
True

Yout can use a dictionary to represent the outcome for more readability:

>>> float(
...     f(
...         dict2outcome(
...             dict(price=2, quality=14, delivery="delivered"), issues=issues
...         )
...     )
... )
68.0

You can use lists instead of dictionaries for defining outcomes, weights but that is less readable. The advantage here is that you do not need to pass the issues

>>> f = LinearAdditiveUtilityFunction(
...     [
...         lambda x: 2.0 * x,
...         {"delivered": 10, "not delivered": -10},
...         LambdaFun(lambda x: x - 3),
...     ],
...     weights=[1.0, 2.0, 4.0],
...     issues=issues,
... )
>>> float(f((14.0, "delivered", 2)))
44.0
Remarks:

The mapping need not use all the issues in the output as the last example show.

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Computes u = bias + sum(weights[i] * values[i](offer[i])) for all issues i.

Parameters:

offer – The outcome to evaluate. If None, returns the reserved value.

Returns:

The utility value for the given outcome, or NaN if evaluation fails.

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

Find the outcomes with minimum and maximum utility values.

For linear additive utility functions, exploits the additive structure to efficiently find extremes by optimizing each issue independently.

Parameters:
  • outcome_space – The outcome space to search within.

  • issues – Alternative way to specify the search space via issues.

  • outcomes – Explicit set of outcomes to search (slower).

  • max_cardinality – Maximum samples per issue when enumerating values.

Returns:

Tuple of (worst_outcome, best_outcome).

classmethod from_dict(d: dict, python_class_identifier='__python_class__')[source]

Create an instance from a dictionary.

Parameters:
  • d – Dictionary containing the serialized utility function.

  • python_class_identifier – Key used to identify the class type.

Returns:

A new LinearAdditiveUtilityFunction instance.

classmethod random(outcome_space: CartesianOutcomeSpace | None = None, issues: list[Issue] | tuple[Issue, ...] | None = None, reserved_value=(0.0, 1.0), normalized=True, **kwargs)[source]

Generate a random linear additive utility function.

Parameters:
  • outcome_space – The outcome space to generate the utility function for.

  • issues – Alternative way to specify the issues (extracted from outcome_space if not provided).

  • reserved_value – Range (min, max) for random reserved value selection.

  • normalized – If True, normalize weights to sum to 1.

  • **kwargs – Additional arguments passed to the constructor.

Returns:

A random LinearAdditiveUtilityFunction instance.

Raises:

ValueError – If neither issues nor outcome_space is provided.

scale_by(scale: float, scale_reserved: bool = True, change_weights_only: bool = False, normalize_weights: bool = True) LinearAdditiveUtilityFunction[source]

Create a new utility function scaled by a constant factor.

Computes u’(x) = scale * u(x).

Parameters:
  • scale – The non-negative factor to multiply all utility values by.

  • scale_reserved – If True, also scale the reserved value.

  • change_weights_only – If True, only modify weights; otherwise scale individual value functions.

  • normalize_weights – If True, normalize weights to sum to 1 before scaling.

Returns:

A new LinearAdditiveUtilityFunction with scaled utility values.

Raises:

ValueError – If scale is negative or if both change_weights_only and normalize_weights are True.

shift_by(offset: float, shift_reserved: bool = True, change_bias_only: bool = False) LinearAdditiveUtilityFunction[source]

Create a new utility function shifted by a constant offset.

Computes u’(x) = u(x) + offset.

Parameters:
  • offset – The amount to add to all utility values.

  • shift_reserved – If True, also shift the reserved value.

  • change_bias_only – If True, only modify the bias term; otherwise shift each value function independently.

Returns:

A new LinearAdditiveUtilityFunction with shifted utility values.

to_dict(python_class_identifier='__python_class__')[source]

Convert to a dictionary for serialization.

Parameters:

python_class_identifier – Key used to store the class type identifier.

Returns:

Dictionary representation suitable for JSON serialization.

property weights[source]

The weights for each issue in the linear combination.

xml(issues: list[Issue] | None = None) str[source]

Generates an XML string representing the utility function

Parameters:

issues

Examples

>>> from negmas.outcomes import make_issue
>>> issues = [
...     make_issue(values=10, name="i1"),
...     make_issue(values=["delivered", "not delivered"], name="i2"),
...     make_issue(values=4, name="i3"),
... ]
>>> f = LinearAdditiveUtilityFunction(
...     [
...         lambda x: 2.0 * x,
...         {"delivered": 10, "not delivered": -10},
...         LambdaFun(lambda x: x - 3),
...     ],
...     weights=[1.0, 2.0, 4.0],
...     issues=issues,
... )
>>> print(f.xml(issues))
<issue index="1" etype="discrete" type="discrete" vtype="integer" 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.0" />
    <item index="2" value="not delivered" evaluation="-10.0" />
</issue>
<issue index="3" etype="discrete" type="discrete" vtype="integer" name="i3">
    <item index="1" value="0" evaluation="-3.0" />
    <item index="2" value="1" evaluation="-2.0" />
    <item index="3" value="2" evaluation="-1.0" />
    <item index="4" value="3" evaluation="0.0" />
</issue>
<weight index="1" value="1.0">
</weight>
<weight index="2" value="2.0">
</weight>
<weight index="3" value="4.0">
</weight>
class negmas.preferences.LinearFun(slope: float)[source]

Bases: BaseFun

Linear value function: f(x) = slope * x.

Maps numeric issue values to utilities using a linear transformation through the origin (no constant offset).

Mathematical definition:

\[f(x) = a \cdot x\]

where \(a\) is the slope.

Parameters:

slope – The coefficient \(a\) multiplying the input value.

Example

>>> f = LinearFun(slope=0.5)
>>> f(10)  # 0.5 * 10 = 5
5.0
>>> f(0)  # 0.5 * 0 = 0
0.0

Note

This is equivalent to AffineFun(slope=a, bias=0). Use AffineFun if you need a non-zero intercept.

property bias[source]

Bias.

Parameters:

sef – Sef.

minmax(input: Issue) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) LinearFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

LinearFun

shift_by(offset: float) AffineFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

AffineFun

slope: float[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.LinearMultiFun(slope: tuple[float, ...])[source]

Bases: BaseMultiFun

Linear multi-issue value function: f(x) = sum(slope[i] * x[i]).

Maps tuples of numeric issue values to utilities using a weighted sum (no constant offset).

Mathematical definition:

\[f(\mathbf{x}) = \sum_{i=1}^{n} a_i x_i\]

where \(a_i\) are the slopes (weights) for each issue and \(x_i\) are the issue values.

Parameters:

slope – Tuple of coefficients \((a_1, a_2, ..., a_n)\) for each issue.

Example

>>> f = LinearMultiFun(slope=(0.5, 0.3))
>>> f((10, 20))  # 0.5*10 + 0.3*20 = 11
11.0

Note

This is equivalent to AffineMultiFun(slope=slope, bias=0). Use AffineMultiFun if you need a non-zero constant term.

property bias[source]

Bias.

property dim: int[source]

Dim.

Returns:

The result.

Return type:

int

minmax(input: Iterable[Issue]) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) LinearMultiFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

LinearMultiFun

shift_by(offset: float) AffineMultiFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

AffineMultiFun

slope: tuple[float, ...][source]
xml(indx, issues, bias: float = 0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issues – Issues.

  • bias – Bias.

Returns:

The result.

Return type:

str

negmas.preferences.LinearUtilityAggregationFunction[source]

alias of LinearAdditiveUtilityFunction

class negmas.preferences.LinearUtilityFunction(weights: dict[str, float] | list[float] | tuple[float, ...] | None = None, *args, **kwargs)[source]

Bases: AffineUtilityFunction

A special case of the AffineUtilityFunciton for which the bias is zero.

Parameters:
  • weights – weights for combining values

  • bias – The offset added

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

Notes

The utility value is calculated as:

\[u = \sum_{i=0}^{n_{outcomes}-1} {\alpha_i * \omega_i}\]

where $alpha_i$ is the weight of issue $i$, and $omega_i$ is the value of issue $i$ in the input outcome $omega$.

class negmas.preferences.LogFun(tau: float, bias: float = 0, base: float = 2.718281828459045, scale: float = 1.0)[source]

Bases: BaseFun

Logarithmic value function: f(x) = scale * log_base(tau*x) + bias.

Maps numeric issue values to utilities using a logarithmic function.

Mathematical definition:

\[f(x) = s \cdot \log_a(\tau x) + b\]

where \(s\) is the scale, \(a\) is the base, \(\tau\) is the rate parameter, and \(b\) is the bias.

Parameters:
  • tau – Rate parameter \(\tau\) that scales the input.

  • bias – Constant offset \(b\) (default: 0).

  • base – Logarithm base \(a\) (default: e ≈ 2.718).

  • scale – Output scale \(s\) (default: 1.0).

Example

>>> import math
>>> f = LogFun(tau=1.0)  # f(x) = ln(x)
>>> abs(f(1) - 0.0) < 1e-10  # ln(1) = 0
True
>>> abs(f(math.e) - 1.0) < 1e-10  # ln(e) = 1
True

Warning

The input tau * x must be positive, as logarithm is undefined for non-positive values.

Note

  • For \(\tau > 0\) and \(s > 0\): function grows with increasing x

  • For \(\tau > 0\) and \(s < 0\): function decreases with increasing x

  • Common bases: e (natural log), 2 (binary log), 10 (common log)

base: float[source]
bias: float[source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale: float[source]
scale_by(scale: float) LogFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

LogFun

shift_by(offset: float) LogFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

LogFun

tau: float[source]
xml(indx: int, issue: Issue, bias) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.MappingUtilityFunction(mapping: Callable[[tuple | None], Distribution | float] | Mapping[tuple | None, Distribution | float], default: float = -inf, *args, **kwargs)[source]

Bases: StationaryMixin, 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 ``Value``s. It is only usable with single-issue negotiations. It can be constructed with either a mapping (e.g. a dict) or a callable function.

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

  • 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) )

Examples

Single issue outcome case:

>>> from negmas.outcomes import make_issue
>>> issue = make_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 = [
...     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)']
>>> 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}) == float("-inf")
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 0.0) will be returned.

eval(offer: tuple | None) float[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

float

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

classmethod random(outcome_space: OutcomeSpace, reserved_value=(0.0, 1.0), normalized=True, max_cardinality: int = 10000)[source]

Random.

Parameters:
  • outcome_space – Outcome space.

  • reserved_value – Reserved value.

  • normalized – Normalized.

  • max_cardinality – Max cardinality.

to_dict(python_class_identifier='__python_class__')[source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

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

Examples

>>> from negmas.outcomes import make_issue
>>> issue = make_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>
class negmas.preferences.MultiIssueFun(*args, **kwargs)[source]

Bases: Fun, Protocol

A value function mapping values from multiple issues to a real number

property dim: int[source]

Dim.

Returns:

The result.

Return type:

int

minmax(input: tuple[Issue, ...]) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) MultiIssueFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

MultiIssueFun

shift_by(offset: float) MultiIssueFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

MultiIssueFun

xml(indx: int, issues: list[Issue] | tuple[Issue, ...], bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issues – Issues.

  • bias – Bias.

Returns:

The result.

Return type:

str

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
eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Computes u = f(u_0(omega_0), u_1(omega_1), …, u_n(omega_n)).

Parameters:

offer – The outcome to evaluate. If None, returns the reserved value.

Returns:

The utility value for the given outcome.

Raises:

ValueError – If no issue utilities (values) have been set.

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

Create an instance from a dictionary.

Parameters:
  • d – Dictionary containing the serialized utility function.

  • python_class_identifier – Key used to identify the class type.

Returns:

A new NonLinearAggregationUtilityFunction instance.

to_dict(python_class_identifier='__python_class__')[source]

Convert to a dictionary for serialization.

Parameters:

python_class_identifier – Key used to store the class type identifier.

Returns:

Dictionary representation suitable for JSON serialization.

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

Generate an XML representation of the utility function.

Parameters:

issues – The issues defining the outcome space.

Returns:

XML string representation of the utility function.

Raises:

NotImplementedError – This function cannot be converted to XML.

class negmas.preferences.NonlinearHyperRectangleUtilityFunction(hypervolumes: Iterable[Mapping[int, Any]], mappings: list[Callable[[tuple | None], Distribution | float] | Mapping[tuple | None, Distribution | float]], f: Callable[[list[float]], float], name: str | None = None, reserved_value: float = -inf, id=None)[source]

Bases: StationaryMixin, UtilityFunction

A utility function combining hyper-rectangles with nonlinear aggregation.

Similar to HyperRectangleUtilityFunction, but uses a nonlinear function to combine the utilities from each active hyper-rectangle region.

Parameters:
  • hypervolumes – The hyper-rectangular regions defining the outcome space partitions.

  • mappings – Functions mapping outcomes to utility values within each region.

  • f – A nonlinear function to aggregate the utilities from active regions.

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

  • reserved_value – The utility value for disagreement (None offer).

Notes

The utility value is calculated as:

\[u(\omega) = f\left(\left[g_k(\omega) : \omega \in H_k\right]\right)\]

where \(H_k\) are hypervolumes (regions), \(g_k\) is the mapping for region \(k\), and \(f\) is the nonlinear aggregation function that receives the list of utilities from all regions containing \(\omega\).

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Computes u = f([g_k(omega) for all k where omega in H_k]).

Parameters:

offer – The outcome to evaluate. If None, returns the reserved value.

Returns:

The utility value for the given outcome.

Raises:

ValueError – If hypervolumes have not been set.

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

Create an instance from a dictionary.

Parameters:
  • d – Dictionary containing the serialized utility function.

  • python_class_identifier – Key used to identify the class type.

Returns:

A new NonlinearHyperRectangleUtilityFunction instance.

to_dict(python_class_identifier='__python_class__')[source]

Convert to a dictionary for serialization.

Parameters:

python_class_identifier – Key used to store the class type identifier.

Returns:

Dictionary representation suitable for JSON serialization.

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

Generate an XML representation of the utility function.

Parameters:

issues – The issues defining the outcome space.

Returns:

XML string representation of the utility function.

Raises:

NotImplementedError – This function cannot be converted to XML.

class negmas.preferences.Normalizable(*args, **kwargs)[source]

Bases: Shiftable, Scalable, Protocol

Can be normalized to a given range of values (default is 0-1)

abstractmethod normalize(to: tuple[float, float] = (0.0, 1.0)) N[source]

Normalize.

Parameters:

to – To.

Returns:

The result.

Return type:

N

class negmas.preferences.Ordinal(*args, **kwargs)[source]

Bases: BasePref, Protocol

Can be ordered (at least partially)

abstractmethod is_better(first: tuple | None, second: tuple | None) bool[source]

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

abstractmethod is_equivalent(first: tuple | None, second: tuple | None) bool[source]

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

abstractmethod is_not_better(first: tuple, second: tuple | None) bool[source]

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

abstractmethod is_not_worse(first: tuple | None, second: tuple | None) bool[source]

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

Parameters:
  • first – First outcome to be compared

  • second – Second outcome to be compared

  • state – The negotiation state at which the comparison is done

Remarks:

  • Should raise ValueError if the comparison cannot be done

abstractmethod is_worse(first: tuple | None, second: tuple | None) bool[source]

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

class negmas.preferences.OrdinalRanking(*args, **kwargs)[source]

Bases: Protocol

Outcomes can be ranked. Supports equality

abstractmethod argrank(outcomes: list[tuple | None], descending=True) list[list[int | None]][source]

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

abstractmethod rank(outcomes: list[tuple | None], descending=True) list[list[tuple | None]][source]

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

class negmas.preferences.OutcomeDistances(pareto_dist: float, nash_dist: float, kalai_dist: float, modified_kalai_dist: float, max_welfare: float, ks_dist: float = nan, modified_ks_dist: float = nan)[source]

Bases: object

OutcomeDistances implementation.

kalai_dist: float[source]
ks_dist: float[source]
max_welfare: float[source]
modified_kalai_dist: float[source]
modified_ks_dist: float[source]
nash_dist: float[source]
pareto_dist: float[source]
class negmas.preferences.OutcomeOptimality(pareto_optimality: float, nash_optimality: float, kalai_optimality: float, modified_kalai_optimality: float, max_welfare_optimality: float, ks_optimality: float = nan, modified_ks_optimality: float = nan)[source]

Bases: object

OutcomeOptimality implementation.

kalai_optimality: float[source]
ks_optimality: float[source]
max_welfare_optimality: float[source]
modified_kalai_optimality: float[source]
modified_ks_optimality: float[source]
nash_optimality: float[source]
pareto_optimality: float[source]
class negmas.preferences.PAUtilityFunction(values: dict[str, SingleIssueFun] | tuple[SingleIssueFun, ...] | list[SingleIssueFun], terms: Sequence[tuple[float, tuple[int, ...]]], bias: float = 0.0, *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A Polynomial Aggregation Utility Function.

Like LinearAdditiveUtilityFunction, this has one value function per issue. However, instead of linearly aggregating the value function outputs, this class uses polynomial expansion where each term is a product of value function outputs raised to specified powers.

Mathematical definition:

\[u(\omega) = b + \sum_{k} c_k \prod_{i=1}^{n} v_i(\omega_i)^{p_{ki}}\]
where:
  • \(b\) is the bias

  • \(c_k\) is the coefficient for term \(k\)

  • \(v_i\) is the value function for issue \(i\)

  • \(\omega_i\) is the value of issue \(i\) in outcome \(\omega\)

  • \(p_{ki}\) is the power of issue \(i\)’s value in term \(k\)

Parameters:
  • values – Value functions for individual issues (one per issue).

  • terms – A list of polynomial terms, where each term is a tuple of: - coefficient: The coefficient for this term - powers: A tuple of powers for each value function (length must match number of issues)

  • bias – A constant bias term added to the final utility

  • name – Name of the utility function

Examples

>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(10, "A"), make_issue(10, "B"), make_issue(10, "C")]

Define value functions (one per issue):

>>> values = [
...     lambda x: float(x),  # v_A = A
...     lambda x: float(x),  # v_B = B
...     lambda x: float(x),  # v_C = C
... ]

Define polynomial: u = v_A^3 + v_B^2 * v_C + v_A * v_B * v_C^2

>>> terms = [
...     (1.0, (3, 0, 0)),  # v_A^3
...     (1.0, (0, 2, 1)),  # v_B^2 * v_C
...     (1.0, (1, 1, 2)),  # v_A * v_B * v_C^2
... ]
>>> f = PAUtilityFunction(values=values, terms=terms, issues=issues)

Evaluate: for outcome (2, 3, 4): v_A=2, v_B=3, v_C=4 u = 2^3 + 3^2*4 + 2*3*4^2 = 8 + 36 + 96 = 140

>>> f((2, 3, 4))
140.0

Note

  • This is a generalization of LinearAdditiveUtilityFunction where linear aggregation corresponds to terms with single non-zero powers of 1.

  • For linear behavior, use terms like [(w1, (1,0,0)), (w2, (0,1,0)), …]

property bias: float[source]

Return the bias term.

eval(offer: tuple | None) float[source]

Evaluate the utility of an outcome.

Parameters:

offer – The outcome to evaluate.

Returns:

The utility value.

classmethod from_dict(d: dict, python_class_identifier='__python_class__') PAUtilityFunction[source]

Create from dictionary.

classmethod random(outcome_space: CartesianOutcomeSpace | None = None, issues: list[Issue] | tuple[Issue, ...] | None = None, reserved_value: tuple[float, float] = (0.0, 1.0), normalized: bool = True, n_terms: int | tuple[int, int] = (2, 5), max_power: int = 3, **kwargs) PAUtilityFunction[source]

Generate a random PA utility function.

Parameters:
  • outcome_space – The outcome space.

  • issues – The issues (used if outcome_space is not provided).

  • reserved_value – Range for random reserved value.

  • normalized – Whether to normalize coefficients.

  • n_terms – Number of polynomial terms or range (min, max).

  • max_power – Maximum power for any value in a term.

  • **kwargs – Additional arguments passed to the constructor.

Returns:

A random PAUtilityFunction.

scale_by(scale: float, scale_reserved: bool = True) PAUtilityFunction[source]

Create a scaled version of this utility function.

shift_by(offset: float, shift_reserved: bool = True) PAUtilityFunction[source]

Create a shifted version of this utility function.

property terms: list[tuple[float, tuple[int, ...]]][source]

Return the polynomial terms.

to_dict(python_class_identifier='__python_class__') dict[source]

Convert to dictionary for serialization.

property values: list[BaseFun][source]

Return the value functions.

xml(issues: list[Issue] | None = None) str[source]

Generate an XML string representing the utility function.

Raises:

NotImplementedError – PA utility functions cannot be represented in GENIUS XML format.

class negmas.preferences.PartiallyScalable(*args, **kwargs)[source]

Bases: Scalable, BasePref, Protocol

Can be scaled by a constant amount for a specific part of the outcome space

abstractmethod scale_max_for(to: float, outcome_space: OutcomeSpace | None = None, issues: list[Issue] | None = None, outcomes: list[Outcome] | None = None, rng: tuple[float, float] | None = None) PartiallyScalable[source]

Scale max for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

PartiallyScalable

abstractmethod scale_min_for(to: float, outcome_space: OutcomeSpace | None = None, issues: list[Issue] | None = None, outcomes: list[Outcome] | None = None, rng: tuple[float, float] | None = None) PartiallyScalable[source]

Scale min for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

PartiallyScalable

class negmas.preferences.PartiallyShiftable(*args, **kwargs)[source]

Bases: Scalable, Protocol

Can be shifted by a constant amount for a specific part of the outcome space

abstractmethod shift_max_for(to: float, outcome_space: OutcomeSpace | None = None, issues: list[Issue] | None = None, outcomes: list[Outcome] | None = None, rng: tuple[float, float] | None = None) PartiallyScalable[source]

Shift max for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

PartiallyScalable

abstractmethod shift_min_for(to, outcome_space: OutcomeSpace | None = None, issues: list[Issue] | None = None, outcomes: list[Outcome] | None = None, rng: tuple[float, float] | None = None) PartiallyScalable[source]

Shift min for.

Parameters:
  • to – To.

  • outcome_space – Outcome space.

  • issues – Issues.

  • outcomes – Outcomes.

  • rng – Rng.

Returns:

The result.

Return type:

PartiallyScalable

class negmas.preferences.PolynomialFun(coefficients: tuple[float, ...], bias: float = 0)[source]

Bases: BaseFun

General polynomial value function.

Maps numeric issue values to utilities using a polynomial of arbitrary degree.

Mathematical definition:

\[f(x) = b + \sum_{k=1}^{n} c_k x^k\]

where \(b\) is the bias (constant term) and \(c_k\) are the coefficients for powers 1 through n.

Parameters:
  • coefficients – Tuple of coefficients \((c_1, c_2, ..., c_n)\) for powers 1, 2, …, n respectively.

  • bias – Constant term \(b\) (default: 0).

Example

>>> # f(x) = 1 + 2x + 3x^2
>>> f = PolynomialFun(coefficients=(2.0, 3.0), bias=1.0)
>>> f(0)  # 1 + 0 + 0 = 1
1.0
>>> f(1)  # 1 + 2 + 3 = 6
6.0
>>> f(2)  # 1 + 4 + 12 = 17
17.0

Note

The coefficients tuple is indexed from power 1, not power 0. Use the bias parameter for the constant (power 0) term.

bias: float[source]
coefficients: tuple[float, ...][source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) PolynomialFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

PolynomialFun

shift_by(offset: float) PolynomialFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

PolynomialFun

xml(indx: int, issue: Issue, bias) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.PolynomialMultiFun(terms: tuple[tuple[float, tuple[int, ...]], ...], bias: float = 0)[source]

Bases: BaseMultiFun

General polynomial multi-issue value function.

Maps tuples of numeric issue values to utilities using a multivariate polynomial. Each term is specified by its coefficient and the powers to apply to each issue.

Mathematical definition:

\[f(\mathbf{x}) = \sum_{k} c_k \prod_{i=1}^{n} x_i^{p_{ki}} + d\]

where \(c_k\) are the term coefficients, \(p_{ki}\) are the powers for each issue in term k, and \(d\) is the bias.

Parameters:
  • terms – Tuple of (coefficient, powers) pairs, where powers is a tuple of exponents for each issue. For example, ((2.0, (1, 0)), (3.0, (0, 1))) represents 2*x + 3*y.

  • bias – Constant offset \(d\) (default: 0).

Example

>>> # f(x, y) = 2*x + 3*y + x^2*y + 1
>>> f = PolynomialMultiFun(
...     terms=((2.0, (1, 0)), (3.0, (0, 1)), (1.0, (2, 1))), bias=1.0
... )
>>> f((1, 1))  # 2*1 + 3*1 + 1*1*1 + 1 = 7
7.0
>>> f((2, 3))  # 2*2 + 3*3 + 4*3 + 1 = 4 + 9 + 12 + 1 = 26
26.0
>>> # Three-issue polynomial: f(x, y, z) = x*y + y*z + x*z
>>> f = PolynomialMultiFun(
...     terms=((1.0, (1, 1, 0)), (1.0, (0, 1, 1)), (1.0, (1, 0, 1))), bias=0.0
... )
>>> f((2, 3, 4))  # 2*3 + 3*4 + 2*4 = 6 + 12 + 8 = 26
26.0

Note

  • Use powers of 0 to exclude an issue from a term

  • This is the most general polynomial form but may be slower than specialized classes like QuadraticMultiFun or BilinearMultiFun

bias: float[source]
property dim: int[source]

Return the number of issues this function operates on.

Returns:

The dimensionality (number of issues).

Return type:

int

Raises:

ValueError – If there are no terms to infer dimensionality from.

minmax(input: Iterable[Issue]) tuple[float, float][source]

Find the minimum and maximum values over the issues’ domains.

Parameters:

input – The issues whose combined domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

Return type:

tuple[float, float]

scale_by(scale: float) PolynomialMultiFun[source]

Create a new function scaled by a constant factor.

Parameters:

scale – The factor to multiply all output values by.

Returns:

A new function where f’(x) = scale * f(x).

Return type:

PolynomialMultiFun

shift_by(offset: float) PolynomialMultiFun[source]

Create a new function shifted by a constant offset.

Parameters:

offset – The amount to add to all output values.

Returns:

A new function where f’(x) = f(x) + offset.

Return type:

PolynomialMultiFun

terms: tuple[tuple[float, tuple[int, ...]], ...][source]
class negmas.preferences.Preferences(*args, outcome_space: OutcomeSpace | None = None, issues: tuple[Issue] | None = None, outcomes: tuple[Outcome] | int | None = None, reserved_outcome: Outcome | None = None, owner: Rational | None = None, path: Path | None = None, **kwargs)[source]

Bases: NamedObject, ABC

Base class for all preferences.

Parameters:

outcome_space – The outcome-space over which the preferences are defined

property base_type: str[source]

Returns the utility_function base type ignoring discounting and similar wrappings.

changes() list[PreferencesChange][source]

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.

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

is_better(first: tuple | None, second: tuple | None) bool[source]

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[source]

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[source]

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

abstractmethod is_not_worse(first: tuple | None, second: tuple | None) bool[source]

Is first at least as good as second

abstractmethod is_session_dependent() bool[source]

Does the utility of an outcome depend on the NegotiatorMechanismInterface?

abstractmethod is_state_dependent() bool[source]

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

is_stationary() bool[source]

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

abstractmethod is_volatile() bool[source]

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[source]

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

reset_changes() None[source]

Will be called whenever we need to reset changes.

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

Returns:

The result.

Return type:

dict[str, Any]

property type: str[source]

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

class negmas.preferences.PresortingInverseUtilityFunction(ufun: BaseUtilityFunction, levels: int = 10, max_cache_size: int = 10000000000, rational_only: bool = False, n_waypints: int = 10, eps: float = 1e-12, rel_eps: float = 1e-06)[source]

Bases: InverseUFun

A utility function inverter that uses pre-sorting.

The outcome-space is sampled if it is continuous and enumerated if it is discrete during the call to init() and an ordered list of outcomes with their utility values is then cached.

Parameters:
  • ufun – The utility function to be inverted

  • levels – discretization levels per issue

  • max_cache_size – maximum allowed number of outcomes in the resulting inverse

  • rational_only – If true, rational outcomes will be sorted but irrational outcomes will not be sorted (should be faster if the reserved value is high)

  • n_waypoints – Used to speedup sampling outcomes at given utilities. The larger, the slower init() will be but the faster worst_in() and best_in()

  • eps – Absolute difference between utility values to consider them equal (zero or negative to disable).

  • rel_eps – Relative difference between utility values to consider them equal (zero or negative to disable).

Remarks:
  • The actual limit used to judge ufun equality is max(eps, rel_eps * range) where range is the difference between max and min utilities for rational outcomes. Set both eps, rel_eps to zero or a negative number to disable cycling through outcomes with equal utilities (or set cycle=False when calling the appropriate function).

all(rng: float | tuple[float, float], normalized: bool) list[tuple][source]

Finds all outcomes with in the given utility value range

Parameters:

rng – The range. If a value, outcome utilities must match it exactly

Remarks:
  • If issues or outcomes are not None, then init_inverse will be called first

  • If the outcome-space is discrete, this method will return all outcomes in the given range

best() tuple | None[source]

Finds the best outcome (of the rational outcomes if constructed with sort_rational_only)

best_in(rng: float | tuple[float, float], normalized: bool, cycle: bool = True, eps: float = 1e-12) tuple | None[source]

Finds an outcome with the highest possible utility within the given range (if any)

Parameters:
  • rng – Range of utilities to find the outcome within

  • normalized – If true, the range will be interpreted as on a scaled ufun with range (0-1)

  • cycle – If given, the system will cycle between outcomes with the same utility value (up to eps)

Remarks:
  • Returns None if no such outcome exists

  • This is an O(log(n)) operation (where n is the number of outcomes)

extreme_outcomes() tuple[tuple | None, tuple | None][source]

Finds the worst and best outcomes that can be returned.

Remarks:

These may be different from the results of ufun.extreme_outcomes() as they can be approximate.

init()[source]

Init.

property initialized[source]

Initialized.

max() float[source]

Finds the maximum rational utility value (of the rational outcomes if constructed with sort_rational_only)

min() float[source]

Finds the minimum utility value (of the rational outcomes if constructed with sort_rational_only)

minmax() tuple[float, float][source]

Finds the minimum and maximum utility values that can be returned.

Remarks:

  • These may be different from the results of ufun.minmax() as they can be approximate.

  • Will only consider rational outcomes if constructed with sort_rational_only

next_better() tuple | None[source]

Returns the rational outcome with utility just above the last one returned from this function

next_worse() tuple | None[source]

Returns the rational outcome with utility just below the last one returned from this function

one_in(rng: tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]

Finds an outcome within the given range of utilities.

Remarks:
  • This is an O(log(n)) operation (where n is the number of outcomes)

  • We only search rational outcomes

outcome_at(indx: int) tuple | None[source]

Outcome at.

Parameters:

indx – Indx.

Returns:

The result.

Return type:

Outcome | None

reset() None[source]

Reset.

some(rng: float | tuple[float, float], normalized: bool, n: int | None = None) list[tuple][source]

Finds some outcomes with the given utility value (if discrete, all)

Parameters:
  • rng – The range. If a value, outcome utilities must match it exactly

  • normalized – if given, consider the range as a normalized range betwwen 0 and 1 representing lowest and highest utilities.

  • n – The maximum number of outcomes to return

Remarks:
  • If issues or outcomes are not None, then init_inverse will be called first

  • If the outcome-space is discrete, this method will return all outcomes in the given range

property ufun[source]

Ufun.

utility_at(indx: int) float[source]

Utility at.

Parameters:

indx – Indx.

Returns:

The result.

Return type:

float

within_fractions(rng: tuple[float, float]) list[tuple][source]

Finds outcomes within the given fractions of utility values (the fractions must be between zero and one).

Remarks:
  • This is an O(n) operation (where n is the number of outcomes)

within_indices(rng: tuple[int, int]) list[tuple][source]

Finds outcomes within the given indices with the best at index 0 and the worst at largest index.

Remarks:
  • Works only for discrete outcome spaces

worst() tuple | None[source]

Finds the worst outcome (of the rational outcomes if constructed with sort_rational_only)

worst_in(rng: float | tuple[float, float], normalized: bool, cycle: bool = True, eps: float = 1e-12) tuple | None[source]

Finds an outcome with the lowest possible utility within the given range (if any)

Parameters:
  • rng – Range of utilities to find the outcome within

  • normalized – If true, the range will be interpreted as on a scaled ufun with range (0-1)

  • cycle – If given, the system will cycle between outcomes with the same utility value (up to eps)

Remarks:
  • Returns None if no such outcome exists, or the worst outcome in the given range is irrational

  • This is an O(log(n)) operation (where n is the number of outcomes)

class negmas.preferences.ProbMappingUtilityFunction(mapping: Callable[[tuple | None], Distribution | float] | Mapping[tuple | None, Distribution | float], default=None, *args, **kwargs)[source]

Bases: StationaryMixin, ProbUtilityFunction

Outcome mapping utility function.

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

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

  • 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) )

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.

eval(offer: tuple | None) Distribution | float | None[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Distribution | float | None

classmethod from_dict(d, python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

classmethod random(outcome_space: OutcomeSpace, reserved_value=(0.0, 1.0), normalized=True, max_cardinality: int = 10000, type: str = 'uniform')[source]

Random.

Parameters:
  • outcome_space – Outcome space.

  • reserved_value – Reserved value.

  • normalized – Normalized.

  • max_cardinality – Max cardinality.

  • type – Type.

to_dict(python_class_identifier='__python_class__')[source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

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

Xml.

Parameters:

issues – Issues.

Returns:

The result.

Return type:

str

class negmas.preferences.ProbRandomUtilityFunction(locs: tuple[float, float] = (0.0, 1.0), scales: tuple[float, float] = (0.0, 1.0), types: tuple[str, ...] = ('uniform',), *args, **kwargs)[source]

Bases: StationaryMixin, ProbUtilityFunction

A random utility function for a discrete outcome space

eval(offer: Outcome | None) Distribution[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Distribution

class negmas.preferences.ProbUtilityFunction(*args, reserved_value: float = -inf, invalid_value: float | None = None, **kwargs)[source]

Bases: _ExtremelyDynamic, BaseUtilityFunction

A probablistic utility function. One that returns a probability distribution when called

abstractmethod eval(offer: tuple) Distribution[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Distribution

classmethod generate_bilateral(outcomes: int | list[tuple], conflict_level: float = 0.5, conflict_delta=0.005, scale: float | tuple[float, float] = 0.5) tuple[ProbUtilityFunction, ProbUtilityFunction][source]

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 UtilityFunction
>>> 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 | list[tuple], normalized: bool = True, scale: float | tuple[float, float] = 0.5) list[ProbUtilityFunction][source]

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 | list[tuple], scale: float = 0.5) tuple[ProbUtilityFunction, ProbUtilityFunction][source]

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.

to_prob() ProbUtilityFunction[source]

To prob.

Returns:

The result.

Return type:

ProbUtilityFunction

class negmas.preferences.ProductMultiFun(powers: tuple[float, ...], scale: float = 1.0, bias: float = 0)[source]

Bases: BaseMultiFun

Product multi-issue value function: f(x) = scale * prod(x[i]^powers[i]) + bias.

Maps tuples of numeric issue values to utilities using a scaled product with optional powers for each issue.

Mathematical definition:

\[f(\mathbf{x}) = s \cdot \prod_{i=1}^{n} x_i^{p_i} + b\]

where \(s\) is the scale, \(p_i\) are the powers for each issue, and \(b\) is the bias.

Parameters:
  • powers – Tuple of exponents \((p_1, ..., p_n)\) for each issue. Default power of 1.0 for all issues if not specified.

  • scale – Multiplicative scale \(s\) (default: 1.0).

  • bias – Constant offset \(b\) (default: 0).

Example

>>> # Simple product: f(x, y) = x * y
>>> f = ProductMultiFun(powers=(1.0, 1.0))
>>> f((3, 4))  # 3 * 4 = 12
12.0
>>> # Cobb-Douglas style: f(x, y) = x^0.5 * y^0.5
>>> f = ProductMultiFun(powers=(0.5, 0.5))
>>> abs(f((4, 9)) - 6.0) < 1e-10  # 4^0.5 * 9^0.5 = 2 * 3 = 6
True
>>> # With scale and bias: f(x, y) = 2 * x * y + 1
>>> f = ProductMultiFun(powers=(1.0, 1.0), scale=2.0, bias=1.0)
>>> f((3, 4))  # 2 * 3 * 4 + 1 = 25
25.0

Note

This is useful for Cobb-Douglas utility functions commonly used in economics: \(U(x, y) = x^a y^{1-a}\).

bias: float[source]
property dim: int[source]

Return the number of issues this function operates on.

Returns:

The dimensionality (number of issues).

Return type:

int

minmax(input: Iterable[Issue]) tuple[float, float][source]

Find the minimum and maximum values over the issues’ domains.

Parameters:

input – The issues whose combined domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

Return type:

tuple[float, float]

powers: tuple[float, ...][source]
scale: float[source]
scale_by(scale: float) ProductMultiFun[source]

Create a new function scaled by a constant factor.

Parameters:

scale – The factor to multiply all output values by.

Returns:

A new function where f’(x) = scale * f(x).

Return type:

ProductMultiFun

shift_by(offset: float) ProductMultiFun[source]

Create a new function shifted by a constant offset.

Parameters:

offset – The amount to add to all output values.

Returns:

A new function where f’(x) = f(x) + offset.

Return type:

ProductMultiFun

class negmas.preferences.QuadraticFun(a2: float, a1: float, bias: float = 0)[source]

Bases: BaseFun

Quadratic value function: f(x) = a2*x^2 + a1*x + bias.

Maps numeric issue values to utilities using a quadratic polynomial.

Mathematical definition:

\[f(x) = a_2 x^2 + a_1 x + b\]

where \(a_2\) is the quadratic coefficient, \(a_1\) is the linear coefficient, and \(b\) is the bias (constant term).

Parameters:
  • a2 – Quadratic coefficient \(a_2\).

  • a1 – Linear coefficient \(a_1\).

  • bias – Constant term \(b\) (default: 0).

Example

>>> f = QuadraticFun(a2=1.0, a1=-2.0, bias=1.0)  # (x-1)^2
>>> f(1)  # Minimum at x=1
0.0
>>> f(0)  # 0 - 0 + 1 = 1
1.0
>>> f(3)  # 9 - 6 + 1 = 4
4.0

Note

  • If \(a_2 > 0\): parabola opens upward (has a minimum)

  • If \(a_2 < 0\): parabola opens downward (has a maximum)

  • Extremum occurs at \(x = -a_1 / (2 a_2)\)

a1: float[source]
a2: float[source]
bias: float[source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) QuadraticFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

QuadraticFun

shift_by(offset: float) QuadraticFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

QuadraticFun

xml(indx: int, issue: Issue, bias) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.QuadraticMultiFun(linear: tuple[float, ...], quadratic: tuple[float, ...], interactions: tuple[float, ...], bias: float = 0)[source]

Bases: BaseMultiFun

Quadratic multi-issue value function with cross-terms.

Maps tuples of numeric issue values to utilities using a full quadratic form including linear terms, squared terms, and all pairwise interaction terms.

Mathematical definition:

\[f(\mathbf{x}) = \sum_{i=1}^{n} a_i x_i + \sum_{i=1}^{n} b_i x_i^2 + \sum_{i=1}^{n} \sum_{j=i+1}^{n} c_{ij} x_i x_j + d\]
where:
  • \(a_i\) are the linear coefficients

  • \(b_i\) are the quadratic (squared) coefficients

  • \(c_{ij}\) are the interaction coefficients for pairs (i, j)

  • \(d\) is the bias (constant term)

Parameters:
  • linear – Tuple of linear coefficients \((a_1, ..., a_n)\).

  • quadratic – Tuple of quadratic coefficients \((b_1, ..., b_n)\) for squared terms.

  • interactions – Tuple of interaction coefficients for pairs (0,1), (0,2), …, (n-2,n-1). Length should be n*(n-1)/2 for n issues.

  • bias – Constant offset \(d\) (default: 0).

Example

>>> # f(x,y) = 2x + 3y + x^2 + 2y^2 + 4xy + 1
>>> f = QuadraticMultiFun(
...     linear=(2.0, 3.0), quadratic=(1.0, 2.0), interactions=(4.0,), bias=1.0
... )
>>> f((1, 1))  # 2*1 + 3*1 + 1*1 + 2*1 + 4*1*1 + 1 = 13
13.0
>>> f((2, 3))  # 2*2 + 3*3 + 1*4 + 2*9 + 4*2*3 + 1 = 4+9+4+18+24+1 = 60
60.0

Note

For two issues, this is equivalent to the full bivariate quadratic: \(f(x, y) = a_1 x + a_2 y + b_1 x^2 + b_2 y^2 + c_{12} xy + d\)

bias: float[source]
property dim: int[source]

Return the number of issues this function operates on.

Returns:

The dimensionality (number of issues).

Return type:

int

interactions: tuple[float, ...][source]
linear: tuple[float, ...][source]
minmax(input: Iterable[Issue]) tuple[float, float][source]

Find the minimum and maximum values over the issues’ domains.

Parameters:

input – The issues whose combined domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

Return type:

tuple[float, float]

quadratic: tuple[float, ...][source]
scale_by(scale: float) QuadraticMultiFun[source]

Create a new function scaled by a constant factor.

Parameters:

scale – The factor to multiply all output values by.

Returns:

A new function where f’(x) = scale * f(x).

Return type:

QuadraticMultiFun

shift_by(offset: float) QuadraticMultiFun[source]

Create a new function shifted by a constant offset.

Parameters:

offset – The amount to add to all output values.

Returns:

A new function where f’(x) = f(x) + offset.

Return type:

QuadraticMultiFun

class negmas.preferences.RandomUtilityFunction(rng: tuple[float, float] = (0.0, 1.0), *args, **kwargs)[source]

Bases: StationaryMixin, UtilityFunction

A random utility function for a discrete outcome space

eval(offer: Outcome | None) float[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

float

class negmas.preferences.Randomizable(*args, **kwargs)[source]

Bases: Protocol

Random Preferences of this type can be created using a random method

abstractmethod classmethod random(outcome_space, reserved_value, normalized=True, **kwargs) Randomizable[source]

Generates a random ufun of the given type

class negmas.preferences.RankOnlyUtilityFunction(ufun: BaseUtilityFunction, randomize_equal: bool = False, eps=1e-07, name: str | None = None, id: str | None = None, type_name: str | None = None)[source]

Bases: StationaryMixin, UtilityFunction

A utility function that keeps trak of outcome order onlyself.

Remarks:
  • This type of utility function can only be generated for discrete outcome spaces.

  • It can be constructed from any utility function.

  • Given an outcome space of $K$ outcomes, the outcome with maximum utility will have a value $le K$ when evaluated and the worst outcome will have value $0$.

  • Outcomes with equal utility value will be ordered randomly if randomize_eqial is True, otherwise outcomes that are eps apart will have the same rank.

  • The reserved value will also be mapped to an integer giving its rank

eval(outcome: Outcome) int | None[source]

Eval.

Parameters:

outcome – Outcome to evaluate.

Returns:

The result.

Return type:

int | None

to_mapping_ufun() MappingUtilityFunction[source]

To mapping ufun.

Returns:

The result.

Return type:

MappingUtilityFunction

class negmas.preferences.SamplingInverseUtilityFunction(ufun: BaseUtilityFunction, max_samples_per_call: int = 10000)[source]

Bases: InverseUFun

A utility function inverter that uses sampling.

Nothing is done during initialization so the fixed cost of this inverter is minimal. Nevertheless, each time the system is asked to find an outcome within some range, it uses random sampling which is very inefficient and suffers from the curse of dimensionality.

all(rng: float | tuple[float, float]) list[tuple][source]

Finds all outcomes with in the given utility value range

Parameters:

rng – The range. If a value, outcome utilities must match it exactly

Remarks:
  • If issues or outcomes are not None, then init_inverse will be called first

  • If the outcome-space is discrete, this method will return all outcomes in the given range

best_in(rng: float | tuple[float, float], normalized: bool) tuple | None[source]

Best in.

Parameters:
  • rng – Rng.

  • normalized – Normalized.

Returns:

The result.

Return type:

Outcome | None

extreme_outcomes() tuple[tuple | None, tuple | None][source]

Finds the worst and best outcomes that can be returned.

Remarks:

These may be different from the results of ufun.extreme_outcomes() as they can be approximate.

init()[source]

Init.

property initialized[source]

Initialized.

minmax() tuple[float, float][source]

Finds the minimum and maximum utility values that can be returned.

Remarks:

These may be different from the results of ufun.minmax() as they can be approximate.

one_in(rng: float | tuple[float, float], normalized: float, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]

One in.

Parameters:
  • rng – Rng.

  • normalized – Normalized.

  • fallback_to_higher – Fallback to higher.

  • fallback_to_best – Fallback to best.

Returns:

The result.

Return type:

Outcome | None

some(rng: float | tuple[float, float], normalized: bool, n: int | None = None) list[tuple][source]

Finds some outcomes with the given utility value (if discrete, all)

Parameters:
  • rng – The range. If a value, outcome utilities must match it exactly

  • n – The maximum number of outcomes to return

Remarks:
  • If issues or outcomes are not None, then init_inverse will be called first

  • If the outcome-space is discrete, this method will return all outcomes in the given range

property ufun[source]

Ufun.

worst_in(rng: float | tuple[float, float], normalized: bool) tuple | None[source]

Worst in.

Parameters:
  • rng – Rng.

  • normalized – Normalized.

Returns:

The result.

Return type:

Outcome | None

class negmas.preferences.Scalable(*args, **kwargs)[source]

Bases: UFun, Protocol

Can be scaled by a constant amount (i.e. utility values are all multiplied by this amount)

abstractmethod scale_by(scale: float, scale_reserved=True) Scalable[source]

Scale by.

Parameters:
  • scale – Scale.

  • scale_reserved – Scale reserved.

Returns:

The result.

Return type:

Scalable

abstractmethod scale_max(to: float, rng: tuple[float, float] | None = None) Scalable[source]

Scale max.

Parameters:
  • to – To.

  • rng – Rng.

Returns:

The result.

Return type:

Scalable

abstractmethod scale_min(to: float, rng: tuple[float, float] | None = None) Scalable[source]

Scale min.

Parameters:
  • to – To.

  • rng – Rng.

Returns:

The result.

Return type:

Scalable

class negmas.preferences.ScenarioStats(opposition: float, utility_ranges: list[tuple[float, float]], pareto_utils: tuple[tuple[float, ...], ...] = NOTHING, pareto_outcomes: list[tuple] = NOTHING, nash_utils: list[tuple[float, ...]] = NOTHING, nash_outcomes: list[tuple] = NOTHING, kalai_utils: list[tuple[float, ...]] = NOTHING, kalai_outcomes: list[tuple] = NOTHING, modified_kalai_utils: list[tuple[float, ...]] = NOTHING, modified_kalai_outcomes: list[tuple] = NOTHING, max_welfare_utils: list[tuple[float, ...]] = NOTHING, max_welfare_outcomes: list[tuple] = NOTHING, max_relative_welfare_utils: list[tuple[float, ...]] = NOTHING, max_relative_welfare_outcomes: list[tuple] = NOTHING, ks_utils: list[tuple[float, ...]] = NOTHING, ks_outcomes: list[tuple] = NOTHING, modified_ks_utils: list[tuple[float, ...]] = NOTHING, modified_ks_outcomes: list[tuple] = NOTHING)[source]

Bases: object

ScenarioStats implementation.

opposition[source]

Opposition level between negotiators.

Type:

float

utility_ranges[source]

List of (min, max) utility ranges for each negotiator.

Type:

list[tuple[float, float]]

pareto_utils[source]

Tuple of utility tuples on the Pareto frontier. Can be empty if not computed or excluded for space optimization.

Type:

tuple[tuple[float, …], …]

pareto_outcomes[source]

List of outcomes on the Pareto frontier. Can be empty if not computed or excluded for space optimization.

Type:

list[tuple]

nash_utils[source]

List of utility tuples at Nash bargaining solutions.

Type:

list[tuple[float, …]]

nash_outcomes[source]

List of outcomes at Nash bargaining solutions.

Type:

list[tuple]

kalai_utils[source]

List of utility tuples at Kalai-Smorodinsky solutions.

Type:

list[tuple[float, …]]

kalai_outcomes[source]

List of outcomes at Kalai-Smorodinsky solutions.

Type:

list[tuple]

modified_kalai_utils[source]

List of utility tuples at modified Kalai solutions.

Type:

list[tuple[float, …]]

modified_kalai_outcomes[source]

List of outcomes at modified Kalai solutions.

Type:

list[tuple]

max_welfare_utils[source]

List of utility tuples at maximum welfare points.

Type:

list[tuple[float, …]]

max_welfare_outcomes[source]

List of outcomes at maximum welfare points.

Type:

list[tuple]

max_relative_welfare_utils[source]

List of utility tuples at max relative welfare points.

Type:

list[tuple[float, …]]

max_relative_welfare_outcomes[source]

List of outcomes at max relative welfare points.

Type:

list[tuple]

ks_utils[source]

List of utility tuples at KS solutions.

Type:

list[tuple[float, …]]

ks_outcomes[source]

List of outcomes at KS solutions.

Type:

list[tuple]

modified_ks_utils[source]

List of utility tuples at modified KS solutions.

Type:

list[tuple[float, …]]

modified_ks_outcomes[source]

List of outcomes at modified KS solutions.

Type:

list[tuple]

Notes

The pareto_utils and pareto_outcomes fields can be empty when: - Stats were saved with include_pareto_frontier=False for space optimization - Stats were loaded from a file that excluded pareto data

Functions that need the pareto frontier should handle empty values gracefully by either skipping pareto-related calculations or computing the frontier on demand.

classmethod from_dict(d: dict, ufuns: list[UtilityFunction] | tuple[UtilityFunction, ...] | None = None, outcomes: Sequence[Outcome] | None = None, calc_pareto_if_missing: bool = False) ScenarioStats[source]

Create ScenarioStats from a dictionary.

Parameters:
  • d – Dictionary with ScenarioStats fields. Missing pareto fields will be set to empty collections unless calc_pareto_if_missing is True.

  • ufuns – Utility functions to use for calculating pareto frontier if missing. Required if calc_pareto_if_missing is True.

  • outcomes – Outcomes to consider for pareto frontier calculation. If None, outcomes will be enumerated from the ufuns’ outcome space.

  • calc_pareto_if_missing – If True and pareto frontier data is missing or empty, calculate it using the provided ufuns.

Returns:

ScenarioStats instance.

Raises:

ValueError – If calc_pareto_if_missing is True but ufuns is not provided.

Notes

When calc_pareto_if_missing is True and pareto data is missing, this method will compute the pareto frontier which may be slow for large outcome spaces.

classmethod from_ufuns(ufuns: list[UtilityFunction] | tuple[UtilityFunction, ...], outcomes: Sequence[Outcome] | None = None, eps=1e-12) ScenarioStats[source]

From ufuns.

Parameters:
  • ufuns – Ufuns.

  • outcomes – Outcomes.

  • eps – Eps.

Returns:

The result.

Return type:

ScenarioStats

property has_pareto_frontier: bool[source]

Check if the pareto frontier data is available.

kalai_outcomes: list[tuple][source]
kalai_utils: list[tuple[float, ...]][source]
ks_outcomes: list[tuple][source]
ks_utils: list[tuple[float, ...]][source]
max_relative_welfare_outcomes: list[tuple][source]
max_relative_welfare_utils: list[tuple[float, ...]][source]
max_welfare_outcomes: list[tuple][source]
max_welfare_utils: list[tuple[float, ...]][source]
modified_kalai_outcomes: list[tuple][source]
modified_kalai_utils: list[tuple[float, ...]][source]
modified_ks_outcomes: list[tuple][source]
modified_ks_utils: list[tuple[float, ...]][source]
nash_outcomes: list[tuple][source]
nash_utils: list[tuple[float, ...]][source]
opposition: float[source]
pareto_outcomes: list[tuple][source]
pareto_utils: tuple[tuple[float, ...], ...][source]
restrict(ufuns: tuple[UtilityFunction], reserved_values: tuple[float, ...]) ScenarioStats[source]

Restrict.

Parameters:
  • ufuns – Ufuns.

  • reserved_values – Reserved values.

Returns:

The result.

Return type:

ScenarioStats

to_dict(include_pareto_frontier: bool = True) dict[source]

Convert to dictionary with optional exclusion of pareto frontier data.

Parameters:

include_pareto_frontier – If True, include pareto_utils and pareto_outcomes. If False, exclude them to save space. Default is True.

Returns:

Dictionary representation of the ScenarioStats.

Notes

When include_pareto_frontier=False, the pareto_utils and pareto_outcomes fields are set to empty collections. This is useful for saving disk space when the full pareto frontier is not needed.

utility_ranges: list[tuple[float, float]][source]
class negmas.preferences.SessionDependentUFunMixin[source]

Bases: object

Indicates that the ufun is session-dependent (i.e. utility value of outcomes depend on the NMI)

eval(offer: Outcome) Distribution[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Distribution

abstractmethod eval_on_session(offer: Outcome, nmi: NegotiatorMechanismInterface | None = None) Distribution[source]

Evaluates the offer given a session

is_session_dependent()[source]

Does the utiltiy of an outcome depend on the NegotiatorMechanismInterface?

is_state_dependent()[source]

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

class negmas.preferences.Shiftable(*args, **kwargs)[source]

Bases: CardinalProb, Protocol

Can be shifted by a constant amount (i.e. utility values are all shifted by this amount)

abstractmethod shift_by(offset: float, shift_reserved=True) Shiftable[source]

Shift by.

Parameters:
  • offset – Offset.

  • shift_reserved – Shift reserved.

Returns:

The result.

Return type:

Shiftable

abstractmethod shift_max(to: float, rng: tuple[float, float] | None = None) Shiftable[source]

Shift max.

Parameters:
  • to – To.

  • rng – Rng.

Returns:

The result.

Return type:

Shiftable

abstractmethod shift_min(to: float, rng: tuple[float, float] | None = None) Shiftable[source]

Shift min.

Parameters:
  • to – To.

  • rng – Rng.

Returns:

The result.

Return type:

Shiftable

class negmas.preferences.SinFun(multiplier: float = 1.0, bias: float = 0.0, phase: float = 0.0, amplitude: float = 1.0)[source]

Bases: BaseFun

Sine value function.

Maps numeric issue values to utilities using a sine function.

Mathematical definition:

\[f(x) = A \sin(\omega x + \phi) + b\]

where \(A\) is the amplitude, \(\omega\) is the angular frequency (multiplier), \(\phi\) is the phase shift, and \(b\) is the bias.

Parameters:
  • multiplier – Angular frequency \(\omega\) (default: 1.0).

  • bias – Vertical offset \(b\) (default: 0.0).

  • phase – Phase shift \(\phi\) in radians (default: 0.0).

  • amplitude – Amplitude \(A\) (default: 1.0).

Example

>>> import math
>>> f = SinFun()  # f(x) = sin(x)
>>> abs(f(0) - 0.0) < 1e-10  # sin(0) = 0
True
>>> abs(f(math.pi / 2) - 1.0) < 1e-10  # sin(pi/2) = 1
True

Note

The function oscillates between bias - amplitude and bias + amplitude with period \(2\pi / \omega\).

amplitude: float[source]
bias: float[source]
minmax(input) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

multiplier: float[source]
phase: float[source]
scale_by(scale: float) SinFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

SinFun

shift_by(offset: float) SinFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

SinFun

xml(indx: int, issue: Issue, bias) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.SingleIssueFun(*args, **kwargs)[source]

Bases: Fun, Protocol

A value function mapping values from a single issue to a real number

max(input: Issue) float[source]

Max.

Parameters:

input – Input.

Returns:

The result.

Return type:

float

min(input: Issue) float[source]

Min.

Parameters:

input – Input.

Returns:

The result.

Return type:

float

xml(indx: int, issue: Issue, bias=0.0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issue – Issue.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.StateDependentUFunMixin[source]

Bases: object

Indicates that the ufun is state-dependent (i.e. utility value of outcomes depend on the mechanism state)

eval(offer: Outcome) Distribution[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Distribution

abstractmethod eval_on_state(offer: Outcome, nmi: NegotiatorMechanismInterface | None = None, state: MechanismState | None = None) Distribution[source]

Evaluates the offer given a session and state

is_session_dependent()[source]

Does the utiltiy of an outcome depend on the NegotiatorMechanismInterface?

is_state_dependent()[source]

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

class negmas.preferences.StationaryMixin[source]

Bases: object

Indicates that the ufun is stationary which means that it is not session or state dependent and not volatile.

Negotiators using this type of ufuns can assume that if they call it twice with the same outcome, it will always return the same value.

is_session_dependent() bool[source]

Check if session dependent.

Returns:

The result.

Return type:

bool

is_state_dependent() bool[source]

Check if state dependent.

Returns:

The result.

Return type:

bool

is_stationary() bool[source]

Check if stationary.

Returns:

The result.

Return type:

bool

is_volatile() bool[source]

Check if volatile.

Returns:

The result.

Return type:

bool

to_stationary() UtilityFunction[source]

To stationary.

Returns:

The result.

Return type:

UtilityFunction

class negmas.preferences.TableFun(mapping: dict)[source]

Bases: BaseFun

Table-based value function using dictionary lookup.

Maps discrete issue values to real numbers using a dictionary. This is the most flexible single-issue function, suitable for categorical issues or when values don’t follow a mathematical pattern.

Parameters:

mapping – Dictionary mapping issue values to utility values.

Example

>>> f = TableFun(mapping={"red": 1.0, "blue": 0.8, "green": 0.6})
>>> f("red")
1.0
>>> f("green")
0.6
>>> # Can also map numeric values
>>> f = TableFun(mapping={0: 0.0, 1: 0.5, 2: 1.0})
>>> f(1)
0.5

Note

Raises KeyError if called with a value not in the mapping.

mapping: dict[source]
minmax(input: Issue) tuple[float, float][source]

Find the minimum and maximum values over an issue’s domain.

Parameters:

input – The issue whose domain to evaluate over.

Returns:

A tuple of (minimum, maximum) values.

scale_by(scale: float) TableFun[source]

Create a new TableFun with all values scaled by a constant.

Parameters:

scale – The factor to multiply each mapped value by.

Returns:

A new TableFun where each value is multiplied by scale.

shift_by(offset: float) TableFun[source]

Create a new TableFun with all values shifted by a constant.

Parameters:

offset – The amount to add to each mapped value.

Returns:

A new TableFun where each value is increased by offset.

xml(indx: int, issue: Issue, bias=0.0) str[source]

Export this function to GENIUS XML format.

Parameters:
  • indx – The 0-based index of this issue in the utility function.

  • issue – The issue this function is defined over.

  • bias – Additional bias to add to all evaluation values.

Returns:

XML string representing this value function.

class negmas.preferences.TableMultiFun(mapping: dict[tuple, Any])[source]

Bases: BaseMultiFun

Table-based multi-issue value function using dictionary lookup.

Maps tuples of issue values to real numbers using a dictionary. This is the most flexible multi-issue function, suitable for modeling arbitrary interactions between issues.

Mathematical definition:

\[f(\mathbf{x}) = T[\mathbf{x}]\]

where \(T\) is the mapping dictionary and \(\mathbf{x}\) is a tuple of issue values.

Parameters:

mapping – Dictionary mapping value tuples to utility values.

Example

>>> f = TableMultiFun(
...     mapping={
...         ("red", "large"): 1.0,
...         ("red", "small"): 0.8,
...         ("blue", "large"): 0.6,
...         ("blue", "small"): 0.4,
...     }
... )
>>> f(("red", "large"))
1.0
>>> f(("blue", "small"))
0.4

Note

Raises KeyError if called with a value tuple not in the mapping.

property dim: int[source]

Dim.

Returns:

The result.

Return type:

int

mapping: dict[tuple, Any][source]
minmax(input: Iterable[Issue]) tuple[float, float][source]

Minmax.

Parameters:

input – Input.

Returns:

The result.

Return type:

tuple[float, float]

scale_by(scale: float) TableMultiFun[source]

Scale by.

Parameters:

scale – Scale.

Returns:

The result.

Return type:

TableMultiFun

shift_by(offset: float) TableMultiFun[source]

Shift by.

Parameters:

offset – Offset.

Returns:

The result.

Return type:

TableMultiFun

xml(indx, issues, bias: float = 0) str[source]

Xml.

Parameters:
  • indx – Indx.

  • issues – Issues.

  • bias – Bias.

Returns:

The result.

Return type:

str

class negmas.preferences.TriangularFun(start: float, middle: float, end: float, bias: float = 0, scale: float = 1)[source]

Bases: BaseFun

Triangular (tent) value function.

A piecewise-linear function that rises from bias at start to bias + scale at middle, then falls back to bias at end.

Mathematical definition:

\[\begin{split}f(x) = \begin{cases} b & \text{if } x \le s \\ b + k \cdot \frac{x - s}{m - s} & \text{if } s < x \le m \\ b + k \cdot \frac{e - x}{e - m} & \text{if } m < x < e \\ b & \text{if } x \ge e \end{cases}\end{split}\]

where \(s\) is start, \(m\) is middle, \(e\) is end, \(b\) is bias, and \(k\) is scale.

Parameters:
  • start – x value where function starts rising from bias.

  • middle – x value where function reaches maximum (bias + scale).

  • end – x value where function returns to bias.

  • bias – Offset added to all values (default: 0).

  • scale – Height of the peak above bias (default: 1).

Example

>>> f = TriangularFun(start=0.0, middle=5.0, end=10.0)
>>> f(0)   # At start: bias = 0
0
>>> f(5)   # At middle: bias + scale = 1
1.0
>>> f(10)  # At end: bias = 0
0
>>> f(2.5) # Halfway up: 0.5
0.5
bias: float[source]
end: float[source]
middle: float[source]
minmax(input) tuple[float, float][source]
scale: float[source]
scale_by(scale: float) TriangularFun[source]
shift_by(offset: float) TriangularFun[source]
start: float[source]
xml(indx: int, issue: Issue, bias) str[source]
class negmas.preferences.UFun(*args, **kwargs)[source]

Bases: CardinalProb, Protocol

Can be called to map an Outcome to a Distribution or a float

eval(offer: tuple) Distribution | float[source]

Evaluates the ufun without normalization (See eval_normalized )

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

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 caached in the ufun, the cache will be used.

abstractmethod minmax() tuple[float, float][source]

Finds the minimum and maximum for the ufun

class negmas.preferences.UFunCrisp(*args, **kwargs)[source]

Bases: UFun, Protocol

Can be called to map an Outcome to a float

eval(offer: tuple) float[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

float

to_stationary() T[source]

To stationary.

Returns:

The result.

Return type:

T

class negmas.preferences.UFunProb(*args, **kwargs)[source]

Bases: UFun, Protocol

Can be called to map an Outcome to a Distribution

abstractmethod eval(offer: tuple) Distribution[source]

Eval.

Parameters:

offer – Offer being considered.

Returns:

The result.

Return type:

Distribution

class negmas.preferences.UniformUtilityFunction(loc: UtilityFunction, scale: UtilityFunction, *args, **kwargs)[source]

Bases: ILSUtilityFunction

A utility function which represents the loc and scale deviations as any crisp ufun

class negmas.preferences.UtilityFunction(*args, reserved_value: float = -inf, invalid_value: float | None = None, **kwargs)[source]

Bases: _ExtremelyDynamic, BaseUtilityFunction

Base for all crisp ufuns

difference_prob(first: tuple | None, second: tuple | None) Distribution[source]

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

abstractmethod eval(offer: tuple) float[source]

Evaluate the utility value of an offer.

Parameters:

offer – Outcome being evaluated (e.g., dict of issue values or tuple)

Returns:

Utility value for this offer, typically normalized between 0 and 1

Return type:

float

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

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.

classmethod generate_bilateral(outcomes: int | Sequence[tuple], conflict_level: float = 0.5, conflict_delta=0.005) tuple[UtilityFunction, UtilityFunction][source]

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][source]

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][source]

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.

is_not_worse(first: tuple | None, second: tuple | None) bool[source]

Check if not worse.

Parameters:
  • first – First.

  • second – Second.

Returns:

The result.

Return type:

bool

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][source]

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

to_crisp() UtilityFunction[source]

Convert to a crisp (non-probabilistic) utility function.

Returns:

Self, as this is already a crisp utility function

Return type:

UtilityFunction

class negmas.preferences.VolatileUFunMixin[source]

Bases: object

Indicates that the ufun is volatile

is_volatile()[source]

Check if volatile.

class negmas.preferences.WeightedUtilityFunction(ufuns: Iterable[BaseUtilityFunction], weights: Iterable[float] | None = None, **kwargs)[source]

Bases: _DependenceMixin, BaseUtilityFunction

A utility function composed of linear aggregation of other utility functions

Parameters:
  • ufuns – An iterable of utility functions

  • weights – Weights used for combination. If not given all weights are assumed to equal 1.

  • name – Utility function name

eval(offer: tuple) Distribution | float[source]

Calculate the utility_function value for a given outcome.

Parameters:

offer – The offer to be evaluated.

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

  • Return A Value not a float for real-valued utilities for the benefit of inspection code.

Returns:

The utility_function value which may be a distribution. If None it means the utility_function value cannot be calculated.

Return type:

Value

classmethod from_dict(d: dict[str, Any], python_class_identifier='__python_class__')[source]

From dict.

Parameters:
  • d

  • python_class_identifier – Python class identifier.

classmethod random(outcome_space, reserved_value, normalized=True, n_ufuns=(1, 4), ufun_types=(<class 'negmas.preferences.crisp.linear.LinearAdditiveUtilityFunction'>, ), **kwargs) WeightedUtilityFunction[source]

Generates a random ufun of the given type

to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

Returns:

The result.

Return type:

dict[str, Any]

to_stationary()[source]

Returns a stationary version with all component utility functions converted to stationary.

class negmas.preferences.XmlSerializableUFun(*args, **kwargs)[source]

Bases: Protocol

Can be serialized to XML format (compatible with GENIUS)

classmethod from_genius(issues: list[Issue], file_name: PathLike, **kwargs) X[source]

From genius.

Parameters:
  • issues – Issues.

  • file_name – File name.

  • **kwargs – Additional keyword arguments.

Returns:

The result.

Return type:

X

abstractmethod classmethod from_xml_str(xml_str: str, **kwargs) X[source]

Imports a utility function from a GENIUS XML string.

Parameters:

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

Returns:

A utility function object (depending on the input file)

to_genius(file_name: PathLike, **kwargs) None[source]

Exports a utility function to a GENIUS XML file.

Parameters:

file_name (str) – File name to export to

Returns:

None

Remarks:

See to_xml_str for all the parameters

abstractmethod to_xml_str(**kwargs) str[source]

Exports a utility function to a well formatted string

abstractmethod xml(issues: list[Issue]) str[source]

Xml.

Parameters:

issues – Issues.

Returns:

The result.

Return type:

str

negmas.preferences.calc_outcome_distances(utils: tuple[float, ...], stats: ScenarioStats) OutcomeDistances[source]

Calc outcome distances.

Parameters:
  • utils – Utils.

  • stats – Stats.

Returns:

The result.

Return type:

OutcomeDistances

negmas.preferences.calc_outcome_optimality(dists: OutcomeDistances, stats: ScenarioStats, max_dist: float) OutcomeOptimality[source]

Calc outcome optimality.

Parameters:
  • dists – Dists.

  • stats – Stats.

  • max_dist – Max dist.

Returns:

The result.

Return type:

OutcomeOptimality

negmas.preferences.calc_reserved_value(ufun: UtilityFunction, fraction: float = inf, nmin: int = 0, nmax: int = inf, max_cardinality: int | float = inf, finite: bool = True, tight: bool = True) float[source]

Calculates a reserved value that keeps the given fraction of outcomes (saturated between nmin and nmax).

Remarks:
  • If finite, the returned reserved value will be guaranteed to be finite as long as ufun always returns finite values.

  • max_cardinality is used to sample outcomes for continuous outcome spaces

  • If tight is given then the reserved values will be as near as possible to the range of the ufun

negmas.preferences.calc_scenario_stats(ufuns: tuple[UtilityFunction, ...] | list[UtilityFunction], outcomes: Sequence[Outcome] | None = None, eps=1e-12) ScenarioStats[source]

Calc scenario stats.

Parameters:
  • ufuns – Ufuns.

  • outcomes – Outcomes.

  • eps – Eps.

Returns:

The result.

Return type:

ScenarioStats

negmas.preferences.conflict_level(u1: UtilityFunction, u2: UtilityFunction, outcomes: int | Sequence[Outcome], max_tests: int = 10000) float[source]

Finds the conflict level in these two ufuns.

Parameters:
  • u1 – first utility function

  • u2 – second utility function

Examples

  • A nonlinear strictly zero sum case

>>> from negmas.preferences.crisp.mapping import MappingUtilityFunction
>>> from negmas.preferences import conflict_level
>>> outcomes = [(_,) for _ in range(10)]
>>> u1 = MappingUtilityFunction(
...     dict(zip(outcomes, np.random.random(len(outcomes))))
... )
>>> u2 = MappingUtilityFunction(
...     dict(zip(outcomes, 1.0 - np.array(list(u1.mapping.values()))))
... )
>>> print(conflict_level(u1=u1, u2=u2, outcomes=outcomes))
1.0
  • The same ufun

>>> print(conflict_level(u1=u1, u2=u1, outcomes=outcomes))
0.0
  • A linear strictly zero sum case

>>> outcomes = [(i,) for i in range(10)]
>>> u1 = MappingUtilityFunction(
...     dict(zip(outcomes, np.linspace(0.0, 1.0, len(outcomes), endpoint=True)))
... )
>>> u2 = MappingUtilityFunction(
...     dict(zip(outcomes, np.linspace(1.0, 0.0, len(outcomes), endpoint=True)))
... )
>>> print(conflict_level(u1=u1, u2=u2, outcomes=outcomes))
1.0
negmas.preferences.distance_between(w: tuple[float, ...], n: tuple[float, ...]) float[source]

Distance between.

Parameters:
  • w

  • n – Number of items.

Returns:

The result.

Return type:

float

negmas.preferences.distance_to(w: tuple[float, ...], p: Iterable[tuple[float, ...]]) float[source]

Distance to.

Parameters:
  • w

  • p

Returns:

The result.

Return type:

float

negmas.preferences.dominating_points(utils: ndarray[tuple[Any, ...], dtype[floating[Any]]] | tuple[float, ...], points: ndarray[tuple[Any, ...], dtype[floating[Any]]] | tuple[tuple[float, ...]]) ndarray[tuple[Any, ...], dtype[integer[Any]]][source]

Tests whether the given point in utility space is dominated by any in the given points (eps is the tolerance).

negmas.preferences.extreme_outcomes(ufun: UtilityFunction, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, max_cardinality=1000) tuple[Outcome, Outcome][source]

Finds the best and worst outcomes.

Parameters:
  • ufun – The utility function

  • outcome_space – An outcome-space to consider

  • 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)

Returns:

Outcomes with minumum utility, maximum utility

negmas.preferences.get_ranks(ufun: UtilityFunction, outcomes: Sequence[Outcome | None], normalize=False) list[float] | NDArray[np.floating[Any]][source]

Get ranks.

Parameters:
  • ufun – Ufun.

  • outcomes – Outcomes.

  • normalize – Normalize.

Returns:

The result.

Return type:

list[float] | NDArray[np.floating[Any]]

negmas.preferences.kalai_points(ufuns: Sequence[UtilityFunction], frontier: Sequence[tuple[float, ...]], ranges: Sequence[tuple[float, ...]] | None = None, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, eps: float = 1e-12, subtract_reserved_value: bool = True) tuple[tuple[tuple[float, ...], int], ...][source]

Calculates the all Kalai bargaining solutions on the Pareto frontier of a negotiation which is the most Egaliterian solution ref: Kalai, Ehud (1977). “Proportional solutions to bargaining situations: Intertemporal utility comparisons” (PDF). Econometrica. 45 (7): 1623–1630. doi:10.2307/1913954. JSTOR 1913954.

Parameters:
  • ufuns – A list of ufuns to use

  • frontier – a list of tuples each giving the utility values at some outcome on the frontier (usually found by pareto_frontier) to search within

  • outcome_space – The outcome-space to consider

  • issues – The issues on which the ufun is defined (outcomes may be passed instead)

  • outcomes – The outcomes on which the ufun is defined (outcomes may be passed instead)

Returns:

A tuple of three values (all will be None if reserved values are unknown)

  • A tuple of utility values at the nash point

  • The index of the given frontier corresponding to the nash point

Remarks:

  • The function searches within the given frontier only.

negmas.preferences.ks_points(ufuns: Sequence[UtilityFunction], frontier: Sequence[tuple[float, ...]], ranges: Sequence[tuple[float, ...]] | None = None, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, eps: float = 1e-12, subtract_reserved_value: bool = True, exponent: float = inf) tuple[tuple[tuple[float, ...], int], ...][source]

Calculates the all Kalai-Somordinsky bargaining solutions on the Pareto frontier of a negotiation which is the bargaining solution that maximizes minimum advantage ratio ref: Kalai, Ehud, and Meir Smorodinsky. “Other solutions to Nash’s bargaining problem.” Econometrica: Journal of the Econometric Society (1975): 513-518.

Parameters:
  • ufuns – A list of ufuns to use

  • frontier – a list of tuples each giving the utility values at some outcome on the frontier (usually found by pareto_frontier) to search within

  • outcome_space – The outcome-space to consider

  • issues – The issues on which the ufun is defined (outcomes may be passed instead)

  • outcomes – The outcomes on which the ufun is defined (outcomes may be passed instead)

  • exponent – The exponent used for evaluating distance to the optimal KS solution as the degree of the L-norm used. The default is infinity which indicates the maximum difference. Currently not used

Returns:

A tuple of three values (all will be None if reserved values are unknown)

  • A tuple of utility values at the nash point

  • The index of the given frontier corresponding to the nash point

Remarks:

  • The function searches within the given frontier only.

negmas.preferences.make_discounted_ufun(ufun: UFunType, cost_per_round: float | None = None, power_per_round: float | None = None, discount_per_round: float | None = None, cost_per_relative_time: float | None = None, power_per_relative_time: float | None = None, discount_per_relative_time: float | None = None, cost_per_real_time: float | None = None, power_per_real_time: float | None = None, discount_per_real_time: float | None = None, dynamic_reservation: bool = True) DiscountedUtilityFunction | UFunType[source]

Make discounted ufun.

Parameters:
  • ufun – Ufun.

  • cost_per_round – Cost per round.

  • power_per_round – Power per round.

  • discount_per_round – Discount per round.

  • cost_per_relative_time – Cost per relative time.

  • power_per_relative_time – Power per relative time.

  • discount_per_relative_time – Discount per relative time.

  • cost_per_real_time – Cost per real time.

  • power_per_real_time – Power per real time.

  • discount_per_real_time – Discount per real time.

  • dynamic_reservation – Dynamic reservation.

Returns:

The result.

Return type:

DiscountedUtilityFunction | UFunType

negmas.preferences.make_fun_from_xml(item) tuple[BaseFun, str][source]

Make fun from xml.

Parameters:

item – Item.

Returns:

The result.

Return type:

tuple[BaseFun, str]

negmas.preferences.max_relative_welfare_points(ufuns: Sequence[UtilityFunction], frontier: Sequence[tuple[float, ...]], ranges: Sequence[tuple[float, ...]] | None = None, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, eps=1e-12) tuple[tuple[tuple[float, ...], int], ...][source]

Calculates all the points with maximum relative welfare (i.e. sum of improvements above reserved value) on the Pareto frontier of a negotiation.

Parameters:
  • ufuns – A list of ufuns to use

  • frontier – a list of tuples each giving the utility values at some outcome on the frontier (usually found by pareto_frontier) to search within

  • outcome_space – The outcome-space to consider

  • issues – The issues on which the ufun is defined (outcomes may be passed instead)

  • outcomes – The outcomes on which the ufun is defined (outcomes may be passed instead)

Returns:

  • A tuple of utility values at the Nash point

  • The index of the given frontier corresponding to the Nash point

Return type:

A list of tuples (empty if cannot be calculated) each consists of

Remarks:

  • The function searches within the given frontier only.

negmas.preferences.max_welfare_points(ufuns: Sequence[UtilityFunction], frontier: Sequence[tuple[float, ...]], ranges: Sequence[tuple[float, ...]] | None = None, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, eps=1e-12) tuple[tuple[tuple[float, ...], int], ...][source]

Calculates all the points with maximum relative welfare (i.e. sum of improvements above reserved value) on the Pareto frontier of a negotiation.

Parameters:
  • ufuns – A list of ufuns to use

  • frontier – a list of tuples each giving the utility values at some outcome on the frontier (usually found by pareto_frontier) to search within

  • ranges – the minimum and maximum value for each ufun. If not given, outcome_space, issues, or outcomes must be given to calculate it

  • outcome_space – The outcome-space to consider

  • issues – The issues on which the ufun is defined (outcomes may be passed instead)

  • outcomes – The outcomes on which the ufun is defined (outcomes may be passed instead)

Returns:

  • A tuple of utility values at the Nash point

  • The index of the given frontier corresponding to the Nash point

Return type:

A list of tuples (empty if cannot be calculated) each consists of

Remarks:

  • The function searches within the given frontier only.

negmas.preferences.minmax(ufun: UtilityFunction, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | tuple[Issue, ...] | None = None, outcomes: Sequence[Outcome] | tuple[Outcome, ...] | None = None, max_cardinality=1000) tuple[float, float][source]

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

Parameters:
  • ufun – The utility function

  • outcome_space – An outcome-space to consider

  • 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)

Returns:

Minumum utility, maximum utility

negmas.preferences.nash_points(ufuns: Sequence[UtilityFunction] | None, frontier: Sequence[tuple[float, ...]], ranges: Sequence[tuple[float, ...]] | None = None, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, eps=1e-12) tuple[tuple[tuple[float, ...], int], ...][source]

Calculates all the Nash Bargaining Solutions on the Pareto frontier of a negotiation.

Parameters:
  • ufuns – A list of ufuns to use. If not given, the reserved value is assumed to be zero for all ufuns

  • frontier – a list of tuples each giving the utility values at some outcome on the frontier (usually found by pareto_frontier) to search within

  • ranges – The ranges of the utility functions involved.

  • outcome_space – The outcome-space to consider

  • issues – The issues on which the ufun is defined (outcomes may be passed instead)

  • outcomes – The outcomes on which the ufun is defined (outcomes may be passed instead)

Returns:

  • A tuple of utility values at the Nash point

  • The index of the given frontier corresponding to the Nash point

Return type:

A list of tuples (empty if cannot be calculated) each consists of

Remarks:

  • The function searches within the given frontier only.

negmas.preferences.normalize(ufun: BaseUtilityFunction, to: tuple[float, float] = (0.0, 1.0), outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None) BaseUtilityFunction[source]

Normalizes a utility function to the given range.

Parameters:
  • ufun – The utility function to normalize

  • to – range to normalize to. Default is [0, 1]

  • outcomes – A collection of outcomes to normalize for

Returns:

A utility function that is guaranteed to be normalized for the set of given outcomes

Return type:

UtilityFunction

negmas.preferences.opposition_level(ufuns: Sequence[UtilityFunction], max_utils: float | tuple[float | int, ...] | list[float | int] = 1.0, outcomes: int | Sequence[Outcome] | None = None, issues: Sequence[Issue] | None = None, max_tests: int = 10000) float[source]

Finds the opposition level of the two ufuns defined as the minimum distance to outcome (1, 1)

Parameters:
  • ufuns – A list of utility functions to use.

  • max_utils – A list of maximum utility value for each ufun (or a single number if they are equal).

  • outcomes – A list of outcomes (should be the complete issue space) or an integer giving the number of outcomes. In the later case, ufuns should expect a tuple of a single integer.

  • issues – The issues (only used if outcomes is None).

  • max_tests – The maximum number of outcomes to use. Only used if issues is given and has more outcomes than this value.

Examples

  • Opposition level of the same ufun repeated is always 0

>>> from negmas.preferences.crisp.mapping import MappingUtilityFunction
>>> from negmas.preferences.ops import opposition_level
>>> u1, u2 = lambda x: x[0], lambda x: x[0]
>>> opposition_level([u1, u2], outcomes=10, max_utils=9)
0.0
  • Opposition level of two ufuns that are zero-sum

>>> u1, u2 = (
...     MappingUtilityFunction(lambda x: x[0]),
...     MappingUtilityFunction(lambda x: 9 - x[0]),
... )
>>> opposition_level([u1, u2], outcomes=10, max_utils=9)
0.7114582486036499
negmas.preferences.pareto_frontier(ufuns: Sequence[BaseUtilityFunction], outcomes: Sequence[Outcome] | None = None, issues: Sequence[Issue] | None = None, n_discretization: int | None = None, max_cardinality: int | float = inf, sort_by_welfare=True, eps: float = 1e-12) tuple[tuple[tuple[float, ...], ...], tuple[int, ...]][source]

Finds all pareto-optimal outcomes in the list.

Parameters:
  • 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 results are sorted descendingly by total welfare

  • rational_only – If true, only rational outcomes can be members of the Pareto frontier.

  • eps – resolution

Returns:

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

negmas.preferences.pareto_frontier_active(points: ndarray | list[tuple[float, ...]], eps=-1e-12, sort_by_welfare=True, presort=True) ndarray[source]

Finds the pareto-frontier of a set of points.

Parameters:
  • points – list of points each is a tuple of utility values for one outcome

  • eps – A (usually negative) small number to treat as zero during calculations

  • sort_by_welfare – If True, the results are sorted descindingly by total welfare

  • presort – Apply the heuristic of pre-sorting all points by sum of utility

Returns:

indices of Pareto optimal outcomes

negmas.preferences.pareto_frontier_bf(points: ndarray | Iterable[Iterable[float]], eps=-1e-12, sort_by_welfare=True) ndarray[source]

Pareto frontier bf.

Parameters:
  • points – Points.

  • eps – Eps.

  • sort_by_welfare – Sort by welfare.

Returns:

The result.

Return type:

np.ndarray

negmas.preferences.pareto_frontier_of(points: ndarray | Iterable[Iterable[float]], eps=-1e-12, sort_by_welfare=True) ndarray[source]

Finds the pareto-frontier of a set of utils (i.e. utility values). Uses a fast algorithm.

Parameters:
  • points – list of utils

  • eps – A (usually negative) small number to treat as zero during calculations

  • sort_by_welfare – If True, the results are sorted descindingly by total welfare

Returns:

negmas.preferences.sample_outcome_with_utility(ufun: BaseUtilityFunction, rng: tuple[float, float], outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None, n_trials: int = 100) Outcome | None[source]

Gets one outcome within the given utility range or None on failure.

Parameters:
  • ufun – The utility function

  • rng – The utility range

  • outcome_space – The outcome-space within which to sample

  • issues – The issues the utility function is defined on

  • outcomes – The outcomes to sample from

  • n_trials – The maximum number of trials

Returns:

  • Either issues, or outcomes should be given but not both

negmas.preferences.scale_max(ufun: BaseUtilityFunction, to: float = 1.0, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None) BaseUtilityFunction[source]

Normalizes a utility function to the given range.

Parameters:
  • ufun – The utility function to normalize

  • outcomes – A collection of outcomes to normalize for

  • rng – range to normalize to. Default is [0, 1]

  • epsilon – A small number specifying the resolution

Returns:

A utility function that is guaranteed to be normalized for the set of given outcomes

Return type:

UtilityFunction

negmas.preferences.sort_by_utility(ufun: BaseUtilityFunction, outcomes: Iterable[tuple] | None = None, *, max_cardinality: int | float = float('inf'), best_first: bool = True, rational_only: bool = False, return_sorted_outcomes: Literal[True] = True) tuple[ndarray[tuple[Any, ...], dtype[floating[Any]]], list[tuple]][source]
negmas.preferences.sort_by_utility(ufun: BaseUtilityFunction, outcomes: Iterable[tuple] | None = None, *, max_cardinality: int | float = float('inf'), best_first: bool = True, rational_only: bool = False, return_sorted_outcomes: Literal[False]) ndarray[tuple[Any, ...], dtype[floating[Any]]]

Returns an ordered list of utility values and outcomes for the given ufun

Remarks:
  • If outcomes is not given, the outcome-space of the ufun is used

Returns:

  • utility values ordered from best to worst or worst to best based on best_first

  • outcomes corresponding to the sorted utility values

Return type:

A tuple of two lists (first two are numpy arrays)

negmas.preferences.winwin_level(u1: UtilityFunction, u2: UtilityFunction, outcomes: int | Sequence[Outcome], max_tests: int = 10000) float[source]

Finds the win-win level in these two ufuns.

Parameters:
  • u1 – first utility function

  • u2 – second utility function

Examples

  • A nonlinear same ufun case

>>> from negmas.preferences.crisp.mapping import MappingUtilityFunction
>>> outcomes = [(_,) for _ in range(10)]
>>> u1 = MappingUtilityFunction(
...     dict(zip(outcomes, np.linspace(1.0, 0.0, len(outcomes), endpoint=True)))
... )
  • A linear strictly zero sum case

>>> outcomes = [(_,) for _ in range(10)]
>>> u1 = MappingUtilityFunction(
...     dict(zip(outcomes, np.linspace(0.0, 1.0, len(outcomes), endpoint=True)))
... )
>>> u2 = MappingUtilityFunction(
...     dict(zip(outcomes, np.linspace(1.0, 0.0, len(outcomes), endpoint=True)))
... )