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.AdaptiveInverseUtilityFunction(ufun: Any, max_presorting_outcomes: int = 1000000, bids_precision: int = 3, bids_n_samples: int = 50, bids_continuous_levels: int = 10, **presorting_kwargs: Any)[source]

Bases: InverseUFun

Automatically selects the best InverseUFun implementation.

At init() time the outcome-space cardinality is checked and the best concrete inverter is chosen:

  • Small/medium spaces (cardinality ≤ max_presorting_outcomes) → PresortingInverseUtilityFunction: exact enumeration + sort. Preferred whenever feasible because BIDS is inherently approximate.

  • Large additive spaces (LinearAdditiveUtilityFunction or LinearUtilityFunction with cardinality > max_presorting_outcomes) → BIDSInverseUtilityFunction: approximate dynamic programming, scalable to hundreds of issues / 10^250 outcomes. Continuous issues are discretized internally, so this includes continuous and hybrid outcome spaces.

  • Large non-additive spacesPresortingInverseUtilityFunction with sampling (max_cache_size limits the cached outcomes).

All InverseUFun method calls are forwarded to the selected delegate. The fallback/tolerance behavior is inherited from the delegate (which is always a clamping inverter — see module docs).

Parameters:
  • ufun – The utility function to invert.

  • max_presorting_outcomes – Outcome-space cardinality threshold below which PresortingInverseUtilityFunction is always used (even for additive ufuns), because it is exact. Default: 1,000,000.

  • bids_precisionprecision argument forwarded to BIDSInverseUtilityFunction when BIDS is selected (default: 3).

  • bids_n_samplesn_samples argument forwarded to BIDSInverseUtilityFunction (default: 50).

  • bids_continuous_levelscontinuous_levels argument forwarded to BIDSInverseUtilityFunction, controlling how finely any non-discrete issue is discretized. Defaults to negmas.outcomes.DEFAULT_LEVELS.

  • **presorting_kwargs – Keyword arguments forwarded to PresortingInverseUtilityFunction when presorting is selected (e.g. rational_only, levels, max_cache_size).

best() tuple | None[source]
best_in(rng: float | tuple[float, float], normalized: bool) tuple | None[source]
closest(target: float, normalized: bool = False) tuple | None[source]
property delegate: InverseUFun | None[source]

The concrete inverter currently in use (set after init()).

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

Select and initialise the best concrete inverter for ufun.

property initialized: bool[source]
max() float[source]
min() float[source]
minmax() tuple[float, float][source]
next_better() tuple | None[source]
next_worse() tuple | None[source]
one_in(rng: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]
outcome_at(indx: int) tuple | None[source]

Returns the outcome at rank indx (0 = best) when supported.

If the selected delegate does not provide an outcome_at method (e.g. BIDS), this falls back to within_indices((indx, indx)).

property outcomes: list[tuple][source]

Returns delegate outcomes when available, otherwise an empty list.

some(rng: float | tuple[float, float], normalized: bool, n: int | None = None) list[tuple][source]
property ufun: Any[source]
utility_at(indx: int) float | None[source]

Returns utility at rank indx when supported.

within_fractions(rng: tuple[float, float]) list[tuple][source]
within_indices(rng: tuple[int, int]) list[tuple][source]
worst() tuple | None[source]
worst_in(rng: float | tuple[float, float], normalized: bool) tuple | None[source]
class negmas.preferences.AdaptiveParetoSampler(max_bruteforce_outcomes: int = 10000, large_sampler: type[ParetoSampler] | None = None, max_cardinality: int = 1000000)[source]

Bases: object

Selects the best ParetoSampler backend based on the outcome-space size.

  • For small outcome spaces (cardinality <= max_bruteforce_outcomes) it uses BruteForceParetoSampler — exact, works with any utility function, and fast enough when the space fits comfortably in memory.

  • For larger spaces it uses the more scalable large_sampler (the most accurate non-brute-force backend, MOBANOSParetoSampler by default — exact, no rounding). If that backend cannot handle the ufuns (e.g. it requires additive utilities and they are not additive) it falls back to BruteForceParetoSampler with the max_cardinality sampling cap.

Because a sampler’s operands are supplied to init() (not the constructor), the decision is made there — the constructor only stores the thresholds/config. This is the default sampler used by BaseUtilityFunction.make_pareto_sampler (aliased DefaultParetoSampler).

Parameters:
  • max_bruteforce_outcomes – Largest outcome-space cardinality for which the exact BruteForceParetoSampler is used. Above it, large_sampler is tried first. Default 10_000.

  • large_sampler – The ParetoSampler type used for large spaces. Defaults to MOBANOSParetoSampler. Pass IPSParetoSampler for very large additive domains where an exact frontier is too costly.

  • max_cardinality – Enumeration/sampling cap for the brute-force backend.

best_for_opponent(*, min_util: float, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) Outcome | None[source]
property impl: ParetoSampler | None[source]

The concrete sampler chosen at init() (None before init).

init(ufun: BaseUtilityFunction | None = None, opponent_ufun: BaseUtilityFunction | None = None) None[source]
property initialized: bool[source]
pareto_outcomes(n: int | None = None, *, min_util: float = 0.0, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) list[Outcome][source]
property ufun: BaseUtilityFunction | None[source]
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]

Compute the minimum and maximum values this function can produce for the given issue.

Parameters:

input – The issue whose value range should be evaluated.

Returns:

Tuple of (minimum_value, maximum_value) for this function over the issue’s range.

scale_by(scale: float) AffineFun[source]

Return a new AffineFun with slope and bias scaled by the given factor.

shift_by(offset: float) AffineFun[source]

Return a new AffineFun with the bias shifted by the given offset.

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

Export this value function to GENIUS XML format.

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]

Return the number of issues (not implemented).

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

Find the min/max values over the monotonic affine function.

scale_by(scale: float) AffineMultiFun[source]

Return a new AffineMultiFun with all slopes and bias scaled.

shift_by(offset: float) AffineMultiFun[source]

Return a new AffineMultiFun with the bias shifted by offset.

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

Export to GENIUS XML format (not implemented).

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

Bases: 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. If provided (different from ufun’s outcome space), caching is skipped.

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

Note

Results are cached based on stability flags. Volatile ufuns skip caching.

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 | LinearAdditiveUtilityFunction[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, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000) ConstUtilityFunction | AffineUtilityFunction | LinearUtilityFunction | LinearAdditiveUtilityFunction[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

  • guarantee_max – If True, ensures maximum utility equals to[1]. Defaults to True. Ignored by: AffineUtilityFunction/LinearUtilityFunction (always guaranteed).

  • guarantee_min – If True, ensures minimum utility equals to[0]. Defaults to True. Ignored by: AffineUtilityFunction/LinearUtilityFunction (always guaranteed).

  • max_cardinality – Maximum number of outcomes to consider when normalizing. Defaults to 10 billion. Ignored by: AffineUtilityFunction/LinearUtilityFunction (minmax is exact).

Remarks:
  • AffineUtilityFunction and LinearUtilityFunction always guarantee both min and max values exactly match the target range, so guarantee_max and guarantee_min are ignored.

  • These classes compute exact min/max analytically without sampling, so max_cardinality is also ignored.

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.AggregatingFun(funs: tuple[BaseFun, ...], weights: tuple[float, ...] | None = None, bias: float = 0, normalize: bool = False, issue: Issue | None = None)[source]

Bases: BaseFun

Linearly aggregating value function: a weighted sum of base value funs.

Combines multiple single-issue value functions (all defined over the same issue) into one, computing a weighted sum plus a bias. Optionally normalizes its output to the range [0, 1] over a given issue.

Mathematical definition:

\[f(x) = b + \sum_{i=1}^{n} w_i \cdot g_i(x)\]

where \(g_i\) are the component value functions, \(w_i\) are their weights, and \(b\) is the bias.

Parameters:
  • funs – Tuple of component BaseFun instances to combine.

  • weights – Tuple of weights, one per component (default: 1.0 each).

  • bias – Constant offset added to the weighted sum (default: 0).

  • normalize – If True, rescale the combination so that its range over issue is exactly [0, 1]. Requires issue to be given.

  • issue – The issue used to compute the normalization range. Only needed (and only used) when normalize=True; once the normalization is baked into weights/bias at construction time, this is reset to None.

Example

>>> from negmas.outcomes import make_issue
>>> f = AggregatingFun(
...     funs=(AffineFun(slope=1.0), ConstFun(bias=1.0)), weights=(0.5, 2.0)
... )
>>> f(10)  # 0.5*10 + 2.0*1 = 7
7.0
>>> # Normalize a mixture of two Gaussians to [0, 1] over an issue
>>> issue = make_issue((0.0, 10.0), "x")
>>> g = AggregatingFun(
...     funs=(
...         GaussianFun(center=2.0, sigma=1.0),
...         GaussianFun(center=8.0, sigma=1.0),
...     ),
...     normalize=True,
...     issue=issue,
... )
>>> mn, mx = g.minmax(issue)
>>> abs(mn - 0.0) < 1e-6 and abs(mx - 1.0) < 1e-6
True
bias: float[source]
classmethod from_dict(d: dict, python_class_identifier='__python_class__')[source]
funs: tuple[BaseFun, ...][source]
issue: Issue | None[source]
minmax(input) tuple[float, float][source]
normalize: bool[source]
scale_by(scale: float) AggregatingFun[source]
shift_by(offset: float) AggregatingFun[source]
to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

Serialize, preserving the concrete type of each component fun.

weights: tuple[float, ...] | None[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]

Export this function to GENIUS XML format.

GENIUS has no native evaluator for an arbitrary weighted sum, so this is only supported for discrete issues via a lookup table.

class negmas.preferences.AttributePlanningInverseUtilityFunction(ufun: BaseUtilityFunction, n_samples: int = 50, continuous_levels: int = 10)[source]

Bases: InverseUFun

Utility function inverter using the Attribute Planning algorithm.

Attribute Planning exploits the additive structure of LinearAdditiveUtilityFunction to answer single utility-lookup queries in O(|I|·|V|) time with O(|I|·|V|) space. For each query with target utility t, the algorithm independently selects the per-issue value whose normalised per-issue utility is closest to t, then combines these into an outcome.

Important: only works with LinearAdditiveUtilityFunction (or its subclass LinearUtilityFunction). init() raises TypeError for any other ufun type.

Continuous/hybrid issues: the algorithm needs an explicit list of per-issue values, which continuous issues cannot provide (they are uncountable). Any issue that is not discrete is therefore discretized into continuous_levels evenly-spaced grid points via Issue.to_discrete(), so Attribute Planning works on fully continuous and hybrid (mixed continuous/discrete) outcome spaces too – at the cost of only approximating the true continuous value set.

This is a clamping inverter (see module docs). worst_in/best_in expand the range upward and fall back to the nearest boundary outcome (best if the range is in the upper half of the utility range, worst if in the lower half) rather than returning None.

Parameters:
  • ufun – The utility function to invert.

  • n_samples – Number of random targets sampled for some(), best_in(), and worst_in(). Default: 50.

  • continuous_levels – Number of evenly-spaced grid points used to discretize any issue that is not already discrete (e.g. ContinuousIssue). Ignored for issues that are already discrete. Defaults to negmas.outcomes.DEFAULT_LEVELS (the same discretization level used throughout the outcomes module).

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

Return the outcome with the highest utility in rng.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found and fallback_to_higher is True, the range is expanded upward to [rng[0], max] and the search is retried.

  • If still nothing is found and fallback_to_best is True, the best outcome overall is returned.

  • Otherwise None is returned.

closest(target: float, normalized: bool = False) tuple | None[source]

Return the outcome built by Attribute Planning targeting target.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalised [0,1] space.

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

Precompute per-issue normalised utilities.

Raises:

TypeError – if ufun is not a LinearAdditiveUtilityFunction.

property initialized: bool[source]
max() float[source]
min() float[source]
minmax() tuple[float, float][source]
one_in(rng: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]
some(rng: float | tuple[float, float], normalized: bool, n: int | None = None) list[tuple][source]
property ufun: BaseUtilityFunction[source]
within_fractions(rng: tuple[float, float]) list[tuple][source]
within_indices(rng: tuple[int, int]) list[tuple][source]
worst() tuple[source]
worst_in(rng: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_worst: bool = True) tuple | None[source]

Return the outcome with the lowest utility in rng.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found and fallback_to_higher is True, the range is expanded upward to [rng[0], max] and the search is retried.

  • If still nothing is found and fallback_to_worst is True, the nearest boundary outcome is returned: the best outcome if the range lies above the maximum utility, the worst outcome if it lies below the minimum.

  • Otherwise None is returned.

class negmas.preferences.BIDSInverseUtilityFunction(ufun: BaseUtilityFunction, precision: int = 3, n_samples: int = 50, continuous_levels: int = 10)[source]

Bases: InverseUFun

Utility function inverter using the BIDS dynamic-programming algorithm.

BIDS exploits the additive structure of LinearAdditiveUtilityFunction to answer utility-lookup queries over very large outcome spaces efficiently:

  • Offline phase (init()): builds a DP table of size O(|I|·10^p) in time O(|I|·|V|·10^p), where |I| is the number of issues, |V| is the maximum number of values per issue, and p is the precision parameter.

  • Online phase (one_in, best_in, etc.): each utility-lookup query is answered in O(1) (single table look-up), and n utility-sampling queries (some) take O(n) via Sampling-BIDS.

The approximation error for a single call is at most |I| · 10^-p in normalised utility. Increasing precision reduces this error at the cost of more memory and initialisation time.

Important: BIDS only works with LinearAdditiveUtilityFunction (or its subclass LinearUtilityFunction, which is also additive). init() will raise TypeError for any other ufun type.

Continuous/hybrid issues: BIDS needs an explicit list of per-issue values, which continuous issues cannot provide (they are uncountable). Any issue that is not discrete is therefore discretized into continuous_levels evenly-spaced grid points via Issue.to_discrete() before the DP table is built, so BIDS works on fully continuous and hybrid (mixed continuous/discrete) outcome spaces too – at the cost of only approximating the true continuous value set.

Parameters:
  • ufun – The utility function to invert (must be a LinearAdditiveUtilityFunction or LinearUtilityFunction).

  • precision – Grid precision p (number of decimal places). The table uses 10^p + 1 grid points over [0, 1]. Default: 3 (1001 points, error at most |I|·0.001). Increase for higher accuracy at the cost of more memory/init time.

  • n_samples – Number of targets sampled when some() is called without an explicit n argument, and when best_in/worst_in search for the best/worst outcome in a range.

  • continuous_levels – Number of evenly-spaced grid points used to discretize any issue that is not already discrete (e.g. ContinuousIssue). Ignored for issues that are already discrete. Defaults to negmas.outcomes.DEFAULT_LEVELS (the same discretization level used throughout the outcomes module).

Remarks:
  • min, max, best, worst and minmax are exact: they delegate to the wrapped ufun’s own minmax/extreme_outcomes (which are closed-form for additive ufuns).

  • within_fractions and within_indices return approximate results via dense Sampling-BIDS over the requested range.

  • For maximum accuracy over small or medium outcome spaces, prefer PresortingInverseUtilityFunction (which is exact). Use BIDS when the outcome space is too large to enumerate.

  • This is a clamping inverter (see module docs). worst_in/ best_in expand the range upward and fall back to the nearest boundary outcome (best if the range is in the upper half of the utility range, worst if in the lower half) rather than returning None.

best() tuple[source]

Outcome with the highest utility (exact, from the wrapped ufun).

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

Return the outcome with the highest utility in rng.

Uses Sampling-BIDS with n_samples targets and returns the one with the highest utility that actually lies within the range.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found and fallback_to_higher is True, the range is expanded upward to [rng[0], max] and the search is retried.

  • If still nothing is found and fallback_to_best is True, the best outcome overall is returned.

  • Otherwise None is returned.

closest(target: float, normalized: bool = False) tuple | None[source]

Return the outcome with utility closest to target via a single O(1) BIDS table lookup.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalised [0,1] space.

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

(worst, best) outcomes (exact, from the wrapped ufun).

init() None[source]

Build the BIDS dynamic-programming table.

Raises:

TypeError – if ufun is not a LinearAdditiveUtilityFunction (or its subclass LinearUtilityFunction).

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

Maximum utility (exact, from the wrapped ufun).

min() float[source]

Minimum utility (exact, from the wrapped ufun).

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

(min, max) utilities (exact, from the wrapped ufun).

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

Return one outcome with utility in rng, or a fallback.

Uses a single BIDS query targeting the midpoint of rng, then checks whether the result falls within the range. If not (due to discretisation approximation), falls back as requested.

Parameters:
  • rng – Utility range.

  • normalized – if True, rng is in normalised [0,1] space.

  • fallback_to_higher – if True and nothing found strictly in rng, return the closest outcome above the requested minimum.

  • fallback_to_best – if True and still nothing found, return the outcome with the best overall utility.

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

Return a diverse list of outcomes with utilities near the given range.

Uses Sampling-BIDS: samples n utility targets uniformly from rng and applies BIDS to each, returning up to n distinct outcomes.

Parameters:
  • rng – Utility range (scalar = exact target; tuple = interval).

  • normalized – if True, rng is in normalised [0,1] space.

  • n – Number of samples. Defaults to self.n_samples.

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

Return a diverse sample of outcomes within the given normalised fraction range.

Parameters:

rng(lo, hi) in normalised [0,1] space (0=worst, 1=best).

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

Return outcomes approximately corresponding to the given sorted-rank range.

Maps the index range to a normalised utility range (0=index 0 = best, high index = worst) and applies Sampling-BIDS. Results are approximate.

Parameters:

rng(lo_idx, hi_idx) into a hypothetical sorted-by-utility list of all outcomes (index 0 = best, largest = worst).

worst() tuple[source]

Outcome with the lowest utility (exact, from the wrapped ufun).

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

Return the outcome with the lowest utility in rng.

Uses Sampling-BIDS with n_samples targets and returns the one with the lowest utility that actually lies within the range.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found and fallback_to_higher is True, the range is expanded upward to [rng[0], max] and the search is retried.

  • If still nothing is found and fallback_to_worst is True, the nearest boundary outcome is returned: the best outcome if the range lies above the maximum utility, the worst outcome if it lies below the minimum.

  • Otherwise None is returned.

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, tagged with its concrete type so that it can be reconstructed correctly even when nested inside a heterogeneous collection of BaseFun (e.g. AggregatingFun.funs) via the generic deserialize.

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, tagged with its concrete type so that it can be reconstructed correctly even when nested inside a heterogeneous collection via the generic deserialize.

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: Distribution | float = -inf, invalid_value: float | None = None, constraints: Iterable[Callable[[tuple], bool]] | None = None, **kwargs)[source]

Bases: Preferences, ABC

Base class for all utility functions in negmas

add_constraint(constraint: Callable[[tuple], bool]) None[source]

Add a constraint function to this utility function.

Parameters:

constraint – A callable that takes an Outcome and returns True if valid, False otherwise.

Remarks:
  • Adding constraints may invalidate cached values, so caches are cleared.

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(outcome_space: OutcomeSpace | None = None) tuple[source]

Return the outcome with the highest utility value.

Parameters:

outcome_space – The outcome space to search. If None, uses the ufun’s outcome space.

clear_caches() None[source]

Clear all cached values (minmax, extreme_outcomes, inverter).

clear_constraints() None[source]

Remove all constraints from this utility function.

Remarks:
  • Clears all caches since removing constraints changes valid outcomes.

property constraints: list[Callable[[tuple], bool]][source]

Returns the list of constraint functions.

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]

Evaluate the utility of an offer and return its 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]

Find the worst and best outcomes by evaluating utilities.

Parameters:
  • outcome_space – The outcome space to search. If None, uses the ufun’s outcome space. If provided (different from ufun’s outcome space), the intersection is used and results are not cached.

  • issues – Alternative to outcome_space - list of issues defining the space.

  • outcomes – Alternative to outcome_space - explicit iterable of outcomes to evaluate.

  • max_cardinality – Maximum number of outcomes to enumerate or sample.

Returns:

A tuple of (worst_outcome, best_outcome).

Raises:

ValueError – If no outcomes can be found to evaluate.

Note

Results are cached based on stability flags: - Stationary ufuns always cache results - Volatile ufuns never cache results - Ufuns with STABLE_ORDERING or STABLE_DIFF_RATIOS cache results - If outcome_space/issues/outcomes are provided, caching is skipped

forget_inverter()[source]

Deletes the cached inverter.

forget_pareto_sampler()[source]

Deletes the cached Pareto sampler.

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

Deserialize a utility function from a dictionary.

Parameters:
  • d – The dictionary containing serialized utility function data.

  • python_class_identifier – The key used to identify the Python class name in the dictionary. Defaults to PYTHON_CLASS_IDENTIFIER.

Returns:

A new utility function instance reconstructed from the dictionary.

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
>>> from pathlib import Path
>>> import negmas
>>> from negmas.inout import load_genius_domain
>>> domain = load_genius_domain(
...     Path(negmas.__file__).parent.parent.parent
...     / "tests/data/Laptop/Laptop-C-domain.xml"
... )
>>> u, d = UtilityFunction.from_genius(
...     file_name=Path(negmas.__file__).parent.parent.parent
...     / "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
>>> from pathlib import Path
>>> import negmas
>>> from negmas.inout import load_genius_domain
>>> domain = load_genius_domain(
...     Path(negmas.__file__).parent.parent.parent
...     / "tests/data/Laptop/Laptop-C-domain.xml"
... )
>>> with open(
...     Path(negmas.__file__).parent.parent.parent
...     / "tests/data/Laptop/Laptop-C-prof1.xml",
...     "r",
... ) as ff:
...     u, _ = UtilityFunction.from_xml_str(ff.read(), issues=domain.issues)
>>> with open(
...     Path(negmas.__file__).parent.parent.parent
...     / "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 the first outcome is at least as good as the second.

Parameters:
  • first – The first outcome to compare (None represents no agreement).

  • second – The second outcome to compare (None represents no agreement).

Returns:

True if the utility of first is greater than or equal to the utility of second.

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

Creates (or reuses) an initialized inverter.

This is a convenience alias for invert().

make_pareto_sampler(opponent_ufun: BaseUtilityFunction | None = None, pareto_sampler: type[ParetoSampler] | None = None, **kwargs) ParetoSampler[source]

Creates (or reuses) an initialized Pareto sampler.

The sampler takes its operands (this ufun as own, and opponent_ufun) in ParetoSampler.init(), not the constructor — so a cached sampler of the same type is reused and merely re-init-ed when the opponent estimate changes, instead of being reconstructed.

Parameters:
  • opponent_ufun – Estimated opponent utility function. Can be None.

  • pareto_sampler – Sampler class to use. Defaults to DefaultParetoSampler (AdaptiveParetoSampler).

  • **kwargs – Forwarded to the sampler constructor (configuration only, e.g. precision / max_cardinality). Ignored when an existing sampler of the same type is reused.

Returns:

An initialized Pareto sampler.

max(outcome_space: OutcomeSpace | None = None) Distribution | float[source]

Return the maximum utility value over the outcome space.

Parameters:

outcome_space – The outcome space to search. If None, uses the ufun’s outcome space.

min(outcome_space: OutcomeSpace | None = None) Distribution | float[source]

Return the minimum utility value over the outcome space.

Parameters:

outcome_space – The outcome space to search. If None, uses the ufun’s outcome space.

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:
  • outcome_space – The outcome space to search. If None, uses the ufun’s outcome space. If provided (different from ufun’s outcome space), the intersection is used and results are not cached.

  • 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

Note

Results are cached based on stability flags (only when above_reserve=False): - Stationary ufuns always cache results - Volatile ufuns never cache results - Ufuns with both STABLE_MIN and STABLE_MAX cache results - If outcome_space/issues/outcomes are provided, caching is skipped

normalize(to: tuple[float, float] = (0.0, 1.0), normalize_weights: bool = False, normalize_reserved_values: bool = False, reserved_value_penalty: float | None = None, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000) T | ConstUtilityFunction[source]

Normalize utilities to the target range over the ufun’s outcome space.

Parameters:
  • to – The target (min, max) range for normalized utilities. Defaults to (0.0, 1.0).

  • normalize_weights – Currently unused, kept for API compatibility.

  • normalize_reserved_values – If True, corrects non-finite reserved values (None, inf, -inf, NaN). Defaults to False.

  • reserved_value_penalty – Penalty to subtract from ufun.min() when correcting reserved values. If None, uses DEFAULT_RESERVED_VALUE_PENALTY from negmas.common.

  • guarantee_max – If True (default), ensures the maximum utility equals to[1].

  • guarantee_min – If True (default), ensures the minimum utility equals to[0]. With both defaults the result is stretched to exactly [to[0], to[1]] (backward-compatible behavior). Passing guarantee_min=False only guarantees the maximum and leaves the minimum anywhere >= to[0].

  • max_cardinality – Maximum number of outcomes to consider when normalizing.

Returns:

A new normalized utility function. Returns a ConstUtilityFunction if the original range is degenerate (< NORMALIZE_EPS).

Raises:

ValueError – If the ufun has no outcome space defined.

Remarks:
  • This is a thin wrapper around normalize_all_for() (the single normalization funnel shared by every ufun type).

  • If normalize_reserved_values is True, any non-finite reserved value will be corrected to ufun.min() - penalty before normalization.

classmethod normalize_all_for(ufuns: tuple[T, ...], to: tuple[float | None, float | None] = (0.0, 1.0), max_cardinality: int = 10000000000, outcome_space: OutcomeSpace | None = None, guarantee_max: bool = True, guarantee_min: bool = False) tuple[T | ConstUtilityFunction, ...][source]

Normalize multiple utility functions to a common scale.

This method normalizes a collection of utility functions together so that they share the same scale. This is critical for multi-agent scenarios where utility values need to be comparable across agents.

Parameters:
  • ufuns – Tuple of utility functions to normalize together.

  • to – Target range (min, max) for normalized utilities. If either is None, only the other bound is enforced.

  • max_cardinality – Maximum number of outcomes to consider when computing min/max values for outcome spaces.

  • outcome_space – The outcome space to normalize over. If None, uses each ufun’s own outcome space.

  • guarantee_max – If True, ensures at least one ufun reaches exactly to[1].

  • guarantee_min – If True, ensures at least one ufun reaches exactly to[0].

Returns:

Tuple of normalized utility functions on a common scale.

Raises:

ValueError – If both to[0] and to[1] are None.

Example

>>> from negmas import make_issue
>>> from negmas.preferences import LinearUtilityFunction
>>> issues = [make_issue([0, 5, 10], "x"), make_issue([5, 10, 15], "y")]
>>> # Agent 1: utilities range [0, 10]
>>> u1 = LinearUtilityFunction(weights=[1.0, 0.0], issues=issues)
>>> # Agent 2: utilities range [5, 15]
>>> u2 = LinearUtilityFunction(weights=[0.0, 1.0], issues=issues)
>>> # Normalize to common scale
>>> n1, n2 = LinearUtilityFunction.normalize_all_for(
...     (u1, u2), to=(0.0, 1.0)
... )
>>> # Now n1 range [0, 0.67] and n2 range [0.33, 1.0]
>>> # Utilities are comparable across agents

Note

  • This method handles discounted utility functions by recursively normalizing their base utility functions.

  • When guarantee_max=True, the agent with the highest utility will have its maximum map to exactly to[1].

  • When guarantee_min=True, the agent with the lowest utility will have its minimum map to exactly to[0].

normalize_for(to: tuple[float, float] = (0.0, 1.0), outcome_space: OutcomeSpace | None = None, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000, normalize_reserved_values: bool = False, reserved_value_penalty: float | None = None) T | ConstUtilityFunction[source]

Normalize utilities to the target range over the given outcome space.

Parameters:
  • to – The target (min, max) range for normalized utilities. Defaults to (0.0, 1.0).

  • outcome_space – The outcome space to normalize over. If None, uses the ufun’s outcome space.

  • guarantee_max – If True, ensures maximum utility equals to[1]. Defaults to True. Active for: LinearAdditiveUtilityFunction only. Ignored by: BaseUtilityFunction (this implementation).

  • guarantee_min – If True, ensures minimum utility equals to[0]. Defaults to True. Active for: LinearAdditiveUtilityFunction only. Ignored by: BaseUtilityFunction (this implementation).

  • max_cardinality – Maximum number of outcomes to consider when normalizing. Defaults to 10 billion. Active for: All implementations (used in minmax()).

  • normalize_reserved_values – If True, corrects non-finite reserved values (None, inf, -inf, NaN). Defaults to False.

  • reserved_value_penalty – Penalty to subtract from ufun.min() when correcting reserved values. If None, uses DEFAULT_RESERVED_VALUE_PENALTY from negmas.common.

Returns:

A new normalized utility function. Returns a ConstUtilityFunction if the original range is degenerate (< NORMALIZE_EPS).

Raises:

ValueError – If no outcome space is provided or defined for the ufun.

Remarks:
  • This is a thin wrapper around normalize_all_for() (the single normalization funnel shared by every ufun type). With the default guarantee_min=True and guarantee_max=True the result is stretched to exactly [to[0], to[1]]; passing guarantee_min=False only guarantees the maximum and leaves the minimum anywhere >= to[0].

  • Subclasses like LinearAdditiveUtilityFunction and AffineUtilityFunction override this with an analytic (closed-form) implementation.

  • If normalize_reserved_values is True, any non-finite reserved value will be corrected to ufun.min() - penalty before normalization.

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

remove_constraint(constraint: Callable[[tuple], bool]) None[source]

Remove a constraint function from this utility function.

Parameters:

constraint – The constraint function to remove.

Remarks:
  • Removing constraints may change which outcomes are valid, so caches are cleared.

property reserved_distribution: Distribution[source]

Returns the reserved value as a Distribution.

If the underlying value is a float, returns a delta distribution at that value.

property reserved_value: float[source]

Returns the reserved value as a float.

If the underlying value is a Distribution, returns its mean. If it’s already a numeric type (int/float), returns it as-is for backward compatibility.

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”]

satisfies_constraints(outcome: tuple) bool[source]

Check if an outcome satisfies all constraints.

Parameters:

outcome – The outcome to check.

Returns:

True if the outcome satisfies all constraints, False otherwise.

scale_by(scale: float, scale_reserved=True) WeightedUtilityFunction | T[source]

Return a new ufun with all utility values scaled by the given factor.

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

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

Returns:

A new WeightedUtilityFunction wrapping this ufun with the given scale applied.

Raises:

ValueError – If scale is negative.

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

Scale utilities so the maximum value equals the target over the ufun’s outcome space.

Parameters:
  • to – The target value for the maximum utility.

  • rng – Pre-computed (min, max) range to avoid recomputation.

Returns:

A new scaled utility function.

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 utilities so the maximum value equals the target over the given space.

Parameters:
  • to – The target value for the maximum utility.

  • outcome_space – The outcome space to compute maximum over.

  • issues – Alternative to outcome_space - list of issues defining the space.

  • outcomes – Alternative to outcome_space - explicit list of outcomes.

  • rng – Pre-computed (min, max) range to avoid recomputation.

Returns:

A new scaled utility function.

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

Scale utilities so the minimum value equals the target over the ufun’s outcome space.

Parameters:
  • to – The target value for the minimum utility.

  • rng – Pre-computed (min, max) range to avoid recomputation.

Returns:

A new scaled utility function.

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 utilities so the minimum value equals the target over the given space.

Parameters:
  • to – The target value for the minimum utility.

  • outcome_space – The outcome space to compute minimum over.

  • issues – Alternative to outcome_space - list of issues defining the space.

  • outcomes – Alternative to outcome_space - explicit list of outcomes.

  • rng – Pre-computed (min, max) range to avoid recomputation.

Returns:

A new scaled utility function.

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

Return a new ufun with all utility values shifted by the given offset.

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

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

Returns:

A new WeightedUtilityFunction combining this ufun with a constant offset.

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 utilities so the maximum value equals the target over the given space.

Parameters:
  • to – The target value for the maximum utility.

  • outcome_space – The outcome space to compute maximum over.

  • issues – Alternative to outcome_space - list of issues defining the space.

  • outcomes – Alternative to outcome_space - explicit list of outcomes.

  • rng – Pre-computed (min, max) range to avoid recomputation.

Returns:

A new shifted utility function.

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 utilities so the minimum value equals the target over the given space.

Parameters:
  • to – The target value for the minimum utility.

  • outcome_space – The outcome space to compute minimum over.

  • issues – Alternative to outcome_space - list of issues defining the space.

  • outcomes – Alternative to outcome_space - explicit list of outcomes.

  • rng – Pre-computed (min, max) range to avoid recomputation.

Returns:

A new shifted utility function.

to_crisp() UtilityFunction[source]

Convert this utility function to a crisp (deterministic) utility function.

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

Serialize this utility function to a dictionary.

Parameters:

python_class_identifier – The key used to store the Python class name in the serialized dictionary. Defaults to PYTHON_CLASS_IDENTIFIER.

Returns:

A dictionary containing the serialized utility function data including the outcome space, reserved value, stability, name, and id.

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
>>> from pathlib import Path
>>> import negmas
>>> domain = load_genius_domain(
...     domain_file_name=Path(negmas.__file__).parent.parent.parent
...     / "tests/data/Laptop/Laptop-C-domain.xml"
... )
>>> u, d = UtilityFunction.from_genius(
...     file_name=Path(negmas.__file__).parent.parent.parent
...     / "tests/data/Laptop/Laptop-C-prof1.xml",
...     issues=domain.issues,
... )
>>> u.to_genius(
...     discount_factor=d,
...     file_name=Path(negmas.__file__).parent.parent.parent
...     / "tests/data/LaptopConv/Laptop-C-prof1.xml",
...     issues=domain.issues,
... )
Remarks:

See to_xml_str for all the parameters

to_prob() ProbUtilityFunction[source]

Convert this utility function to a probabilistic utility function.

to_stationary() T[source]

Convert this utility function to a stationary (time-independent) version.

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

Exports a utility function to a well formatted string

worst(outcome_space: OutcomeSpace | None = None) tuple[source]

Return the outcome with the lowest utility value.

Parameters:

outcome_space – The outcome space to search. If None, uses the ufun’s outcome space.

class negmas.preferences.BiasedFun(fun: BaseFun, bias: float = 0, normalize: bool = False, issue: Issue | None = None)[source]

Bases: BaseFun

Wraps any value function, adding a constant bias (and optional 0-1 normalization).

Useful for value function types that don’t already expose a bias parameter of their own (e.g. IdentityFun): f(x) = g(x) + b.

Mathematical definition:

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

where \(g\) is the wrapped value function and \(b\) is the bias.

Parameters:
  • fun – The BaseFun to wrap.

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

  • normalize – If True, rescale fun(x) + bias so that its range over issue is exactly [0, 1]. Requires issue to be given.

  • issue – The issue used to compute the normalization range. Only needed (and only used) when normalize=True; once the normalization is baked in at construction time, this is reset to None.

Example

>>> f = BiasedFun(fun=IdentityFun(), bias=3.0)
>>> f(5)  # 5 + 3
8.0
>>> from negmas.outcomes import make_issue
>>> issue = make_issue((0.0, 10.0), "x")
>>> g = BiasedFun(fun=IdentityFun(), normalize=True, issue=issue)
>>> g.minmax(issue)
(0.0, 1.0)
bias: float[source]
classmethod from_dict(d: dict, python_class_identifier='__python_class__')[source]
fun: BaseFun[source]
issue: Issue | None[source]
minmax(input) tuple[float, float][source]
normalize: bool[source]
scale_by(scale: float) BiasedFun[source]
shift_by(offset: float) BiasedFun[source]
to_dict(python_class_identifier='__python_class__') dict[str, Any][source]

Serialize, preserving the concrete type of the wrapped fun.

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

Export this function to GENIUS XML format by delegating to the wrapped function, shifted by this wrapper’s bias.

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.BruteForceInverseUtilityFunction(ufun: BaseUtilityFunction, levels: int = 10, max_cache_size: int = 10000000000, rational_only: bool = False)[source]

Bases: InverseUFun

A dead-simple, always-correct utility function inverter used as ground truth.

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 (for stationary ufuns only). Every query is answered by a plain linear scan over that list.

This is a strict inverter (see module docs). worst_in/best_in return None when no outcome’s utility falls inside the requested range — they never clamp, expand the range, or fall back to an out-of-range outcome. one_in is the exception: it always had fallback_to_higher and fallback_to_best parameters (both default True), so it never returns None for a non-empty outcome space.

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)

Remarks:
  • This class is intentionally implemented using simple linear scans over the fully sorted outcome list rather than bisection so that it can serve as a trusted, easy-to-verify ground truth for testing other (faster, more complex) inverters such as PresortingInverseUtilityFunction.

  • Unlike the clamping inverters, best_in/worst_in here are strict: they return None when no outcome exists in the requested range (no clamping to the nearest boundary outcome). Callers that need a non-None result (e.g. AspirationNegotiator) must handle None by falling back to the best outcome themselves.

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

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

Finds an outcome with the highest utility within the given range.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • eps – Tolerance used when comparing utilities against the range bounds.

Returns:

The outcome with highest utility in the range, or None if not found.

closest(target: float, normalized: bool = False) tuple | None[source]

Finds the single (rational) outcome whose utility is closest to target.

This is the ground-truth utility-lookup query (argmin_ω |u(ω) - target|): a plain linear scan over the sorted rational outcomes, guaranteed to return the true argmin.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalized [0, 1] space.

Returns:

The closest outcome, or None if there are no rational 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]

Initializes the inverter by enumerating and sorting outcomes by utility.

property initialized[source]

Whether the inverter has been initialized with sorted outcomes.

max() float[source]

Finds the maximum utility value

min() float[source]

Finds the minimum utility value

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 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: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]

Finds any outcome within the given utility range.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • fallback_to_higher – If True, expand range upward when no match found.

  • fallback_to_best – If True, return best outcome as last resort.

Returns:

An outcome within the range, or None if not found and fallbacks disabled.

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

Returns the outcome at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The outcome at that rank, or None if index is out of bounds.

reset() None[source]

Clears cached outcomes and resets the inverter to uninitialized state.

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

Finds some outcomes within the given utility range (if discrete, all of them).

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:
  • Returns only outcomes whose utility lies inside the range (never falls back to out-of-range outcomes). May return an empty list.

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

property ufun[source]

The utility function being inverted.

utility_at(indx: int) float[source]

Returns the utility value at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The utility value at that rank, or -inf if index is out of bounds.

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)

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

worst() tuple | None[source]

Finds the worst outcome

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

Finds an outcome with the lowest utility within the given range.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • eps – Tolerance used when comparing utilities against the range bounds.

Returns:

The outcome with lowest utility in the range, or None if not found.

class negmas.preferences.BruteForceParetoSampler(max_cardinality: int = 1000000)[source]

Bases: object

Exact Pareto sampler via full enumeration and exact frontier extraction.

The utility functions are supplied to init (not the constructor): the constructor only stores configuration, and the expensive frontier build happens in init. A single instance can therefore be re-init-ed with new operands instead of being recreated.

Parameters:

max_cardinality – Max outcomes to enumerate.

AI supported (config-only constructor; frontier built in ``init``; uses the vectorized ``pareto_frontier_numpy``).

best_for_opponent(*, min_util: float, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) Outcome | None[source]
init(ufun: BaseUtilityFunction | None = None, opponent_ufun: BaseUtilityFunction | None = None) None[source]
property initialized: bool[source]
pareto_outcomes(n: int | None = None, *, min_util: float = 0.0, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) list[Outcome][source]
property ufun: BaseUtilityFunction | None[source]
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: BaseUtilityFunction

A utility function composed of nonlinear aggregation of other utility functions.

This combines multiple utility functions using an arbitrary combination function:

u(o) = f(u_1(o), u_2(o), …, u_n(o))

where f is the combination_function.

Stability Properties:
  • Inherits stability by ANDing all component ufuns’ stability

  • Does NOT assume STABLE_ORDERING or STABLE_DIFF_RATIOS since the combination function is arbitrary (could be non-monotonic)

  • If you know your combination function preserves these properties, you can explicitly pass them via the stability parameter

Parameters:
  • ufuns – An iterable of utility functions

  • combination_function – The function used to combine results of ufuns

  • name – Utility function name

Example

>>> from negmas.preferences import LinearUtilityFunction, STATIONARY
>>> from negmas.preferences.stability import STABLE_ORDERING, STABLE_DIFF_RATIOS
>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(5)]
>>> u1 = LinearUtilityFunction(weights=[1.0], issues=issues)
>>> u2 = LinearUtilityFunction(weights=[0.5], issues=issues)
>>> # Product combination - by default does not assume ordering preservation
>>> combined = ComplexNonlinearUtilityFunction(
...     ufuns=[u1, u2], combination_function=lambda vals: vals[0] * vals[1]
... )
>>> combined.is_stationary()  # False because ordering not guaranteed
False
>>> # If you know your function preserves ordering, specify it explicitly:
>>> combined_explicit = ComplexNonlinearUtilityFunction(
...     ufuns=[u1, u2],
...     combination_function=lambda vals: vals[0] * vals[1],
...     stability=STATIONARY,
... )
>>> combined_explicit.is_stationary()
True
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]

Return (bias, bias) since the function is constant.

scale_by(scale: float) ConstFun[source]

Return a new ConstFun with the bias scaled by the given factor.

Since f(x) = c for all x, scaling gives f’(x) = c * scale for all x.

shift_by(offset: float) ConstFun[source]

Return a new ConstFun with the bias shifted by the given offset.

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

Export this constant function to GENIUS XML format.

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

Bases: 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]

Generate XML representation of the utility function.

Parameters:

issues – The issues defining the outcome space.

Returns:

XML string representation of this constant utility function.

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]

Find the min/max values by sampling (exact method not yet implemented).

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

Return a new CosFun with amplitude and bias scaled.

shift_by(offset: float) CosFun[source]

Return a new CosFun with the bias shifted by the given offset.

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

Export this cosine function to GENIUS XML format.

negmas.preferences.DefaultInverseUtilityFunction[source]

alias of AdaptiveInverseUtilityFunction

negmas.preferences.DefaultParetoSampler[source]

alias of AdaptiveParetoSampler

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

Bases: UtilityFunctionAdapter

Base class for all discounted ufuns.

Discounted utility functions wrap another utility function and apply a time/state-dependent discount to the utility values. They preserve: - Ordering of outcomes (STABLE_ORDERING) - Difference ratios between utilities (STABLE_DIFF_RATIOS)

Stability Properties:

Discounted ufuns are ALWAYS state-dependent (they use state.step or state.time to compute the discount factor), so they clear the STATE_INDEPENDENT flag.

However, discounted ufuns inherit SESSION_INDEPENDENT from the inner ufun. Discounting does not depend on NMI parameters (like n_negotiators), only on state variables (like time/step). So if the inner ufun is session-independent, the discounted ufun will also be session-independent.

Note: State independence and session independence are orthogonal concepts: - STATE_INDEPENDENT: Does not depend on MechanismState (time, step, etc.) - SESSION_INDEPENDENT: Does not depend on NMI (n_negotiators, mechanism params)

A discounted ufun is a typical example of a ufun that is session-independent but state-dependent.

Subclasses must implement eval_on_state() to define their discounting logic.

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

Evaluate the utility of an offer using current negotiation state.

This method retrieves the current state from the owner’s NMI (if available) and delegates to eval_on_state().

Parameters:

offer – The outcome to evaluate.

Returns:

The discounted utility value.

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

Evaluates the offer given a session and state.

Subclasses must implement this to define their discounting logic.

Parameters:
  • offer – The outcome to evaluate.

  • nmi – Negotiator-mechanism interface (optional).

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

Returns:

The discounted utility value.

extract_base_ufun(deep: bool = False) BaseUtilityFunction[source]

Extracts the underlying base utility function without discounting.

is_state_dependent()[source]

Returns True since discounted utility functions depend on negotiation state.

to_stationary()[source]

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

property ufun: BaseUtilityFunction[source]

The wrapped utility function (alias for _ufun for backward compatibility).

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 utility function with exponential discounting based on negotiation state.

The discounted utility is computed as: u_discounted = (discount ^ factor) * u_base

Where: - discount: The discount rate (typically 0 < discount <= 1) - factor: A value from the mechanism state (e.g., step, time) - u_base: The utility from the underlying utility function

Stability Properties:
  • Always STATE-DEPENDENT: Clears STATE_INDEPENDENT (depends on state.step/time)

  • Inherits SESSION_INDEPENDENT from inner ufun (discounting doesn’t use NMI)

  • Always preserves ordering (STABLE_ORDERING) - multiplication by positive factor

  • Always preserves difference ratios (STABLE_DIFF_RATIOS) - proportional scaling

  • If dynamic_reservation=True: STABLE_RESERVED_VALUE, STABLE_RATIONAL_OUTCOMES, STABLE_IRRATIONAL_OUTCOMES (everything scales together)

  • If dynamic_reservation=False: FIXED_RESERVED_VALUE, plus: - If discount > 1: STABLE_RATIONAL_OUTCOMES (utilities increase, rational stays rational) - If discount <= 1: STABLE_IRRATIONAL_OUTCOMES (utilities decrease, irrational stays irrational)

  • If discount == 1 or None: Inherits full stability from inner ufun (no effective discounting)

Note on Independence:

State independence and session independence are orthogonal. This ufun is state-dependent (uses state.step) but can be session-independent (doesn’t use NMI parameters like n_negotiators).

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

  • discount – Discount factor (e.g., 0.9 means 90% retained per unit)

  • factor – str -> The name of the MechanismState variable for discounting callable -> receives a MechanismState and returns a float

  • dynamic_reservation – If True, apply discounting to reserved value too

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) Distribution | float[source]

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

Computes: (discount ^ factor) * u_base

Parameters:
  • offer – The outcome to evaluate.

  • nmi – Negotiator-mechanism interface (optional).

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

Returns:

The discounted utility value.

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]

Returns the type name with exponential discounting suffix.

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]

Find the min/max values over the monotonic exponential function.

scale_by(scale: float) ExponentialFun[source]

Return a new ExponentialFun scaled by adjusting tau and bias.

shift_by(offset: float) ExponentialFun[source]

Return a new ExponentialFun with the bias shifted by the given offset.

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

Export this exponential function to GENIUS XML format.

negmas.preferences.FastInverseUtilityFunction[source]

alias of BIDSInverseUtilityFunction

class negmas.preferences.FullMetrics(optimality: OutcomeOptimality, session: SessionMetrics, negotiators: list[NegotiatorMetrics])[source]

Bases: object

All metrics of a single negotiation.

Bundles the agreement’s solution-concept OutcomeOptimality, the negotiator-independent SessionMetrics, and one NegotiatorMetrics per negotiator (in negotiator/ufun order). Built by calc_full_metrics().

negotiators: list[NegotiatorMetrics][source]
optimality: OutcomeOptimality[source]
session: SessionMetrics[source]
to_dict(negotiator_names: Sequence[str] | None = None) dict[str, float][source]

Flatten every metric into a single {name: value} dictionary.

The optimality and session fields are emitted under their own names (e.g. pareto_optimality, welfare) since those two views are already disjoint. Per-negotiator fields are prefixed so the different negotiators do not collide:

  • by default the prefix is neg{i}_ where i is the negotiator index in negotiator/ufun order (e.g. neg0_advantage),

  • if negotiator_names is given, {name}_ is used instead (e.g. buyer_advantage).

Parameters:

negotiator_names – Optional per-negotiator names (in negotiator/ufun order) used to prefix the per-negotiator metric keys. When omitted (or shorter than the number of negotiators), the neg{i}_ index-based prefix is used for the missing entries.

Returns:

A flat dictionary holding every metric of the negotiation.

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: 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: 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.GaussianFun(center: float, sigma: float, bias: float = 0, scale: float = 1)[source]

Bases: BaseFun

Gaussian (bell-curve) value function.

Maps numeric issue values to utilities using a Gaussian bump centered at center. The center is a free parameter (it need not lie inside the issue’s range); the function is simply evaluated (and its min/max computed) over whatever domain the issue restricts it to – i.e. it is “restricted to the edges of the issue” in the sense that minmax only considers the bounded interval [issue.min_value, issue.max_value] rather than the whole real line.

Mathematical definition:

\[f(x) = b + k \cdot \exp\left(-\frac{(x - c)^2}{2 \sigma^2}\right)\]

where \(c\) is the center, \(\sigma\) is the standard deviation, \(b\) is the bias, and \(k\) is the scale (peak height above bias).

Parameters:
  • center – The x value \(c\) where the peak (or trough, if scale < 0) occurs.

  • sigma – Standard deviation \(\sigma\) controlling the width of the bump. Must be strictly positive.

  • bias – Offset added to all values (default: 0).

  • scale – Height of the peak above bias (default: 1). Use a negative value for a dip instead of a bump.

Example

>>> f = GaussianFun(center=5.0, sigma=1.0)
>>> f(5)  # At the center: bias + scale = 1
1.0
>>> 0 < f(6) < 1  # One sigma away: less than the peak
True
>>> f(6) == f(4)  # Symmetric around the center
True
bias: float[source]
center: float[source]
minmax(input) tuple[float, float][source]
scale: float[source]
scale_by(scale: float) GaussianFun[source]
shift_by(offset: float) GaussianFun[source]
sigma: float[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]

Export this function to GENIUS XML format.

GENIUS has no native Gaussian evaluator, so this is only supported for discrete issues via a lookup table.

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

property reserved_distribution: Distribution[source]

Returns the reserved value as a distribution.

If the reserved value was set as a float, returns a delta distribution at that value. If it was set as a Distribution, returns that distribution.

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.

The reserved_value property always returns a float (the mean if the underlying value is a Distribution). Use reserved_distribution to get the full distribution.

property reserved_value: float[source]

Returns the reserved value as a float.

If the underlying value is a Distribution, returns its mean.

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: 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.

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

Exact (min, max) via the rectangle-overlap clique (no enumeration).

Falls back to the base implementation when an explicit set of outcomes is supplied or the per-rectangle utilities are non-constant.

normalize(to: tuple[float, float] = (0.0, 1.0), normalize_weights: bool = False, normalize_reserved_values: bool = False, reserved_value_penalty=None, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000)[source]
normalize_for(to: tuple[float, float] = (0.0, 1.0), outcome_space=None, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000, normalize_reserved_values: bool = False, reserved_value_penalty=None)[source]

Affinely range-normalize this hyper-rectangle ufun to to.

Uses _range_extremes() (exact, no enumeration) to build the affine map u' = a*u + c, applied by scaling the per-rectangle weights and the bias; the reserved value undergoes the same map. This preserves the shape of the ufun and maps it onto to (conditions 1-4). It is not the linear-additive Method 3: a non-linear ufun has no per-issue weights/value functions, so conditions 5-8 do not apply.

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 – The issues defining the negotiation domain structure.

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: 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.IPSParetoSampler(precision: int = 3)[source]

Bases: object

Pareto sampler using the IPS (Iterative Pareto Search) algorithm.

IPS builds an approximate Pareto frontier for a pair of additive utility functions by iteratively combining per-issue non-dominated solution sets, with utilities rounded to a p-decimal-place grid (controlled by precision) to induce overlapping sub-problems.

Requirements: both the agent’s own ufun and the opponent ufun must be LinearAdditiveUtilityFunction (or LinearUtilityFunction) instances with the same set of issues and the same issue ordering. init() (or any query method) will raise TypeError if this is not satisfied.

The utility functions are supplied to init (init(ufun, opponent_ufun)), not the constructor: the constructor takes configuration only, and the expensive frontier build happens in init.

Parameters:

precision – Grid precision p. Utilities are rounded to p decimal places when computing dominance. Default: 3.

Remarks:
  • The algorithm has worst-case space complexity O(|I|·|V|·10^p) and time complexity O(|I|·|V|·10^p).

  • init(ufun, opponent_ufun) must be called before any query method is used. If opponent_ufun changes, call init again to rebuild the frontier (the same instance is reused).

  • IPS requires both ufuns to be additive (LinearAdditiveUtilityFunction or its subclass LinearUtilityFunction). For non-additive ufuns, use a sampling-based approach instead.

AI supported (config-only constructor; operands supplied to ``init``).

best_for_opponent(*, min_util: float, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) Outcome | None[source]

Return the Pareto-optimal outcome maximising opponent utility subject to own utility ≥ min_util.

Parameters:
  • min_util – Minimum required own utility.

  • normalized – if True, min_util is in normalised [0,1] space.

  • opponent_ufun – If provided, reinitialises IPS with this opponent ufun.

init(ufun: BaseUtilityFunction | None = None, opponent_ufun: BaseUtilityFunction | None = None) None[source]

Build the approximate Pareto frontier using IPS.

Parameters:
  • ufun – The agent’s own utility function. If provided, replaces the one from a previous init (the expensive build happens here, not in the constructor). Omit to keep the current ufun.

  • opponent_ufun – Estimate of the opponent’s utility function. Omit to keep the current estimate (e.g. to rebuild after the own ufun changed).

Raises:

TypeError – if own or opponent ufun is not a LinearAdditiveUtilityFunction/LinearUtilityFunction.

property initialized: bool[source]
pareto_outcomes(n: int | None = None, *, min_util: float = 0.0, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) list[Outcome][source]

Return approximately Pareto-optimal outcomes, optionally filtered.

Parameters:
  • n – Maximum number of outcomes (None = all).

  • min_util – Minimum required own utility (raw or normalised).

  • normalized – if True, min_util is in normalised [0,1] space.

  • opponent_ufun – If provided, reinitialises IPS with this opponent ufun before answering the query.

set_opponent_ufun(opponent_ufun: BaseUtilityFunction | None) None[source]

Update the opponent utility function. Call init() afterwards to rebuild the Pareto frontier with the new estimate.

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

Bases: 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[tuple, Distribution | float], range: tuple[float, float] = (0.0, 1.0), uncertainty: float = 0.5, variability: float = 0.0, reserved_value: Distribution | 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]

Generate XML representation (not implemented for probabilistic utility functions).

Parameters:

issues – The issues defining the outcome space.

Raises:

NotImplementedError – This utility function type cannot be serialized to XML.

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]

Return the issue’s min and max values directly.

scale_by(scale: float) LinearFun[source]

Return a LinearFun with the given scale as slope.

shift_by(offset: float) AffineFun[source]

Return f(x) = x + offset as an AffineFun (slope 1).

Note

Returning ConstFun(bias=offset) here would collapse the identity map to a constant, dropping the issue’s contribution during normalization (the overall maximum would fall below 1). The shift of f(x) = x by offset is f(x) = x + offset, i.e. slope 1.

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

Export this identity function to GENIUS XML format.

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

Finds the best outcome, or None if no outcomes are available.

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 closest(target: float, normalized: bool = False) tuple | None[source]

Finds the single outcome whose utility is closest to target.

This is the utility-lookup query argmin_{ω} |u(ω) - target| (Koça et al. 2024). Unlike one_in, it is not a range query: it always returns the nearest outcome and only returns None for an empty outcome space (or when the inverter has no rational outcomes).

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalized [0, 1] space (0 = min, 1 = max) independent of the ufun’s actual range.

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

Finds the worst and best outcomes that can be returned, each of which may be None if no outcomes are available.

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.

property initialized: bool[source]

Whether init() has been called.

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 the next higher utility relative to the last outcome returned by this method (stateful cursor). Returns None when the cursor reaches the best outcome or when the implementation does not maintain a sorted cursor (e.g. sampling-based inverters).

next_worse() tuple | None[source]

Returns the rational outcome with the next lower utility relative to the last outcome returned by this method (stateful cursor). Returns None when the cursor reaches the worst outcome or when the implementation does not maintain a sorted cursor (e.g. sampling-based inverters).

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

property ufun: UFun[source]

The utility function being inverted.

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

Finds the worst outcome, or None if no outcomes are available (e.g. when the outcome space is empty or no rational outcome exists).

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]

Find the min/max values, using cached bounds if available.

scale_by(scale: float) LambdaFun[source]

Return a new LambdaFun scaled by the given factor.

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

Return a new LambdaFun shifted by the given offset.

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

Export this function to GENIUS XML format (discrete issues only).

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]

Return the number of issues (not implemented).

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

Find the min/max values, using cached bounds if available.

scale_by(scale: float) LinearMultiFun[source]

Scale operation (not implemented for lambda functions).

shift_by(offset: float) AffineMultiFun[source]

Shift operation (not implemented for lambda functions).

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

Export to GENIUS XML format (not implemented).

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 negotiation state.

The discounted utility is computed as: u_discounted = u_base - ((factor * cost) ^ power)

Where: - cost: The cost per unit of the factor - factor: A value from the mechanism state (e.g., step, time) - power: Exponent applied to the total cost - u_base: The utility from the underlying utility function

Stability Properties:
  • Always STATE-DEPENDENT: Clears STATE_INDEPENDENT (depends on state.step/time)

  • Inherits SESSION_INDEPENDENT from inner ufun (discounting doesn’t use NMI)

  • Always preserves ordering (STABLE_ORDERING) - subtracting same value from all

  • Always preserves difference ratios (STABLE_DIFF_RATIOS) - constant subtraction

  • If dynamic_reservation=True: STABLE_RESERVED_VALUE, STABLE_RATIONAL_OUTCOMES, STABLE_IRRATIONAL_OUTCOMES (everything reduces together)

  • If dynamic_reservation=False: FIXED_RESERVED_VALUE, plus: - If cost < 0: STABLE_RATIONAL_OUTCOMES (utilities increase, rational stays rational) - If cost >= 0: STABLE_IRRATIONAL_OUTCOMES (utilities decrease, irrational stays irrational)

  • If cost == 0 or None: Inherits full stability from inner ufun (no effective discounting)

Note on Independence:

State independence and session independence are orthogonal. This ufun is state-dependent (uses state.step) but can be session-independent (doesn’t use NMI parameters like n_negotiators).

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

  • cost – Cost per unit of the factor (subtracted from utility)

  • factor – str -> The name of the MechanismState variable for discounting callable -> receives a MechanismState and returns a float

  • power – Exponent applied to (factor * cost) before subtraction

  • dynamic_reservation – If True, apply discounting to reserved value too

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) Distribution | float[source]

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

Computes: u_base - ((factor * cost) ^ power)

Parameters:
  • offer – The outcome to evaluate.

  • nmi – Negotiator-mechanism interface (optional).

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

Returns:

The discounted utility value.

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]

Returns the type name with linear discounting suffix.

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: 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. If provided (different from ufun’s outcome space), caching is skipped.

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

Note

Results are cached based on stability flags. Volatile ufuns skip caching.

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.

normalize(to: tuple[float, float] = (0.0, 1.0), normalize_weights: bool = False, normalize_reserved_values: bool = False, reserved_value_penalty: float | None = None, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000) LinearAdditiveUtilityFunction | ConstUtilityFunction[source]

Normalize over the ufun’s own outcome space.

Delegates to normalize_for() so that normalize and normalize_for share the same analytic (weights-summing-to-one) canonicalization (Method 3, see docs/normalization.rst) instead of falling back to the generic sampling-based scaling inherited from the base class.

normalize_for(to: tuple[float, float] = (0.0, 1.0), outcome_space: OutcomeSpace | None = None, guarantee_max: bool = True, guarantee_min: bool = True, max_cardinality: int = 10000000000) LinearAdditiveUtilityFunction | ConstUtilityFunction[source]

Normalize utility function with proper handling of compositional structure.

This method implements sophisticated normalization specifically for LinearAdditiveUtilityFunction that:

  1. Makes all weights positive

  2. Makes all value functions non-negative

  3. Normalizes each value function to [0, 1]

  4. Normalizes weights to sum to 1

  5. Properly adjusts the reserved value

Parameters:
  • to – Target range (min, max) for normalized utilities. Defaults to (0.0, 1.0).

  • outcome_space – The outcome space to normalize over. If None, uses the ufun’s outcome space.

  • guarantee_max – If True, ensures maximum utility equals to[1]. Defaults to True. Active for: LinearAdditiveUtilityFunction (this implementation). When True, may result in non-uniform weight scaling to hit exact max.

  • guarantee_min – If True, ensures minimum utility equals to[0]. Defaults to True. Active for: LinearAdditiveUtilityFunction (this implementation). When True, may result in non-uniform weight scaling to hit exact min.

  • max_cardinality – Maximum number of outcomes to consider when normalizing. Defaults to 10 billion. Active for: LinearAdditiveUtilityFunction (used when converting non-Cartesian outcome spaces).

Returns:

  • All weights are positive and sum to 1

  • All value functions map to [0, 1]

  • The overall utility range matches the target ‘to’ range

Return type:

A normalized LinearAdditiveUtilityFunction where

Example

>>> from negmas import make_issue
>>> from negmas.preferences.value_fun import AffineFun
>>> issues = (make_issue(10), make_issue(10))
>>> values = [AffineFun(1.0, -5.0), AffineFun(2.0, -3.0)]
>>> weights = [5.0, 3.0]
>>> u = LinearAdditiveUtilityFunction(values, weights, issues=issues)
>>> normalized = u.normalize_for(to=(0.0, 1.0))
>>> # Now: all weights sum to 1, all value functions in [0,1]
>>> assert abs(sum(normalized.weights) - 1.0) < 1e-6
Remarks:
  • The guarantee_max and guarantee_min parameters control strict bounds enforcement.

  • When both are True, the normalization ensures the actual min/max exactly match the target range, which may require adjusting weights non-uniformly.

  • When False, a simpler uniform scaling is used that may not hit exact bounds.

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]

Return the constant offset (always 0 for LinearFun).

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

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

scale_by(scale: float) LinearFun[source]

Return a new LinearFun with the slope scaled by the given factor.

shift_by(offset: float) AffineFun[source]

Return an AffineFun with this slope and the given offset as bias.

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

Export this linear function to GENIUS XML format.

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]

Return the constant offset (always 0 for LinearMultiFun).

property dim: int[source]

Return the number of issues (not implemented).

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

Find the min/max values over the monotonic linear function.

scale_by(scale: float) LinearMultiFun[source]

Return a new LinearMultiFun with all slopes scaled.

shift_by(offset: float) AffineMultiFun[source]

Return an AffineMultiFun with this slope and the given offset as bias.

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

Export to GENIUS XML format (not implemented).

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]

Find the min/max values over the monotonic logarithmic function.

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

Return a new LogFun with scale and bias multiplied by the factor.

shift_by(offset: float) LogFun[source]

Return a new LogFun with the bias shifted by the given offset.

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

Export this logarithmic function to GENIUS XML format.

class negmas.preferences.MCTSInverseUtilityFunction(ufun: BaseUtilityFunction, n_simulations: int = 200, c_ucb: float = 1.41421356, max_ranking_outcomes: int = 20000, continuous_levels: int = 10)[source]

Bases: InverseUFun

Utility function inverter using Monte Carlo Tree Search (MCTS).

MCTS builds a search tree over the issue-value assignment space using UCB1 selection, random rollouts, and backpropagation. The algorithm works with any ufun whose outcome space has enumerable issues and values (unlike BIDS/Attribute-Planning which require additive ufuns).

This is a clamping inverter (see module docs). worst_in/best_in expand the range upward and fall back to the nearest boundary outcome (best if the range is in the upper half of the utility range, worst if in the lower half) rather than returning None.

Continuous/hybrid issues: the search tree is built over explicit per-issue value lists, which continuous issues cannot provide (they are uncountable). Any issue that is not discrete is therefore discretized into continuous_levels evenly-spaced grid points via Issue.to_discrete(), so MCTS works on fully continuous and hybrid (mixed continuous/discrete) outcome spaces too – at the cost of only approximating the true continuous value set.

Parameters:
  • ufun – The utility function to invert.

  • n_simulations – Number of MCTS iterations per query. Default: 200.

  • c_ucb – UCB1 exploration constant. Default: √2 ≈ 1.41421356.

  • continuous_levels – Number of evenly-spaced grid points used to discretize any issue that is not already discrete (e.g. ContinuousIssue). Ignored for issues that are already discrete. Defaults to negmas.outcomes.DEFAULT_LEVELS (the same discretization level used throughout the outcomes module).

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

Return the outcome with the highest utility in rng via MCTS.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found and fallback_to_higher is True, the range is expanded upward to [rng[0], max] and the search is retried.

  • If still nothing is found and fallback_to_best is True, the best outcome overall is returned.

  • Otherwise None is returned.

closest(target: float, normalized: bool = False) tuple | None[source]

Return the outcome whose utility is (approximately) closest to target.

When a full best-first ranking was built at init() time (small outcome spaces), this does an exact bisection lookup. Otherwise it runs MCTS with a reward function that rewards outcomes closer to the target.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalised [0,1] space.

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

Enumerate issues and values from the ufun’s outcome space.

Raises:

ValueError – if the ufun has no outcome space or no issues.

property initialized: bool[source]
max() float[source]
min() float[source]
minmax() tuple[float, float][source]
one_in(rng: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]
outcome_at(indx: int) tuple | None[source]

Returns outcome at rank index (0 = best) when available.

property outcomes: list[tuple][source]

Returns outcomes sorted worst→best when ranking is available.

some(rng: float | tuple[float, float], normalized: bool, n: int | None = None) list[tuple][source]
property ufun: BaseUtilityFunction[source]
utility_at(indx: int) float | None[source]

Returns utility at rank index (0 = best) when available.

within_fractions(rng: tuple[float, float]) list[tuple][source]
within_indices(rng: tuple[int, int]) list[tuple][source]
worst() tuple[source]
worst_in(rng: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_worst: bool = True) tuple | None[source]

Return the outcome with the lowest utility in rng via MCTS.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found and fallback_to_higher is True, the range is expanded upward to [rng[0], max] and the search is retried.

  • If still nothing is found and fallback_to_worst is True, the nearest boundary outcome is returned: the best outcome if the range lies above the maximum utility, the worst outcome if it lies below the minimum.

  • Otherwise None is returned.

class negmas.preferences.MOBANOSParetoSampler(max_pareto_size: int = 100000)[source]

Bases: object

Pareto sampler using the MOBANOS exact iterative construction algorithm.

MOBANOS is similar to IPS (Iterative Pareto Search) but uses exact utilities instead of rounded ones. This avoids any discretisation error but can make the intermediate Pareto set exponentially large for many-valued issues. A max_pareto_size parameter limits memory usage by keeping only the most promising candidates when the set grows too large.

Requirements: both ufuns must be LinearAdditiveUtilityFunction instances. init() raises TypeError otherwise.

The utility functions are supplied to init (init(ufun, opponent_ufun)), not the constructor: the constructor takes configuration only.

Parameters:

max_pareto_size – Maximum number of candidates retained at any point during the iterative construction. Default: 100000.

best_for_opponent(*, min_util: float, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) Outcome | None[source]
init(ufun: BaseUtilityFunction | None = None, opponent_ufun: BaseUtilityFunction | None = None) None[source]

Build the exact Pareto frontier using MOBANOS.

Parameters:
  • ufun – The agent’s own utility function (supplied here, not in the constructor). Omit to keep the current one.

  • opponent_ufun – Estimate of the opponent’s utility function. Omit to keep the current estimate.

Raises:

TypeError – if own or opponent ufun is not a LinearAdditiveUtilityFunction.

property initialized: bool[source]
pareto_outcomes(n: int | None = None, *, min_util: float = 0.0, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) list[Outcome][source]
set_opponent_ufun(opponent_ufun: BaseUtilityFunction | None) None[source]

Update the opponent utility function and mark as not initialized.

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

Bases: 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]

Generate a random mapping utility function.

Parameters:
  • outcome_space – The space of possible outcomes to generate mappings for.

  • reserved_value – The utility for no agreement or range (min, max) for random selection.

  • normalized – If True, normalize utility values to [0, 1] range.

  • max_cardinality – Maximum number of outcomes to sample for discrete approximation.

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]

Returns the number of issues this function operates on.

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

Compute the minimum and maximum values over the given issues.

Parameters:

input – The tuple of issues to compute bounds over.

Returns:

A tuple of (minimum, maximum) utility values.

scale_by(scale: float) MultiIssueFun[source]

Create a new function scaled by a constant factor.

Parameters:

scale – The factor to multiply all output values by.

Returns:

A new multi-issue function with all values scaled.

shift_by(offset: float) MultiIssueFun[source]

Create a new function shifted by a constant offset.

Parameters:

offset – The amount to add to all output values.

Returns:

A new multi-issue function with all values shifted.

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

Generate XML representation for GENIUS compatibility.

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

  • issues – The issues this function maps values from.

  • bias – A constant offset to add to all values in the XML output.

Returns:

XML string representation of this value function.

class negmas.preferences.MultiModalGaussianFun(centers: tuple[float, ...], sigmas: tuple[float, ...], biases: tuple[float, ...] | None = None, scales: tuple[float, ...] | None = None, weights: tuple[float, ...] | None = None, bias: float = 0)[source]

Bases: BaseFun

A mixture (weighted sum) of several GaussianFun, for multi-modal values.

Equivalent to building an AggregatingFun out of several GaussianFun instances, but takes each GaussianFun parameter as a tuple (one entry per component) plus a weights tuple, which is more convenient when all components are Gaussian. This is the standard way to build a multi-modal (multi-peak) value function out of Gaussian bumps.

Note

minmax is approximate for continuous issues (a mixture of several bumps need not have a closed-form extremum): it delegates to AggregatingFun.minmax, which samples the issue’s domain on a dense grid.

Mathematical definition:

\[f(x) = b + \sum_{i=1}^{n} w_i \cdot \left(b_i + k_i \exp\left( -\frac{(x - c_i)^2}{2 \sigma_i^2}\right)\right)\]

where each component is a GaussianFun built from the i-th entries of centers, sigmas, biases and scales.

Parameters:
  • centers – Tuple of center values, one per component (peak).

  • sigmas – Tuple of sigma values, one per component.

  • biases – Tuple of per-component biases (default: 0 each).

  • scales – Tuple of per-component scales (default: 1 each).

  • weights – Tuple of weights multiplying each component before summing (default: 1 each).

  • bias – Overall constant offset added after summing (default: 0).

Example

>>> f = MultiModalGaussianFun(centers=(2.0, 8.0), sigmas=(0.5, 0.5))
>>> abs(f(2.0) - 1.0) < 1e-9  # peak of the first bump
True
>>> abs(f(8.0) - 1.0) < 1e-9  # peak of the second bump
True
>>> f(5.0) < 0.1  # far from both peaks
True
bias: float[source]
biases: tuple[float, ...] | None[source]
centers: tuple[float, ...][source]
minmax(input) tuple[float, float][source]
scale_by(scale: float) MultiModalGaussianFun[source]
scales: tuple[float, ...] | None[source]
shift_by(offset: float) MultiModalGaussianFun[source]
sigmas: tuple[float, ...][source]
weights: tuple[float, ...] | None[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]
class negmas.preferences.MultiModalTrapezoidalFun(starts: tuple[float, ...], rise_ends: tuple[float, ...], fall_starts: tuple[float, ...], ends: tuple[float, ...], biases: tuple[float, ...] | None = None, scales: tuple[float, ...] | None = None, weights: tuple[float, ...] | None = None, bias: float = 0)[source]

Bases: BaseFun

A mixture (weighted sum) of several TrapezoidalFun, for multi-modal values.

Equivalent to building an AggregatingFun out of several TrapezoidalFun instances, but takes each TrapezoidalFun parameter as a tuple (one entry per component) plus a weights tuple, which is more convenient when all components are trapezoidal.

Note

minmax is approximate for continuous issues (a mixture of several trapezoids need not have a closed-form extremum): it delegates to AggregatingFun.minmax, which samples the issue’s domain on a dense grid.

Mathematical definition:

\[f(x) = b + \sum_{i=1}^{n} w_i \cdot T_i(x)\]

where each \(T_i\) is a TrapezoidalFun built from the i-th entries of starts, rise_ends, fall_starts, ends, biases and scales.

Parameters:
  • starts – Tuple of start values, one per component.

  • rise_ends – Tuple of rise_end values, one per component.

  • fall_starts – Tuple of fall_start values, one per component.

  • ends – Tuple of end values, one per component.

  • biases – Tuple of per-component biases (default: 0 each).

  • scales – Tuple of per-component scales (default: 1 each).

  • weights – Tuple of weights multiplying each component before summing (default: 1 each).

  • bias – Overall constant offset added after summing (default: 0).

Example

>>> f = MultiModalTrapezoidalFun(
...     starts=(0.0, 5.0),
...     rise_ends=(1.0, 6.0),
...     fall_starts=(2.0, 7.0),
...     ends=(3.0, 8.0),
... )
>>> f(1.5)  # peak of the first trapezoid
1.0
>>> f(6.5)  # peak of the second trapezoid
1.0
>>> f(4.0)  # between the two, both are at bias (0)
0.0
bias: float[source]
biases: tuple[float, ...] | None[source]
ends: tuple[float, ...][source]
fall_starts: tuple[float, ...][source]
minmax(input) tuple[float, float][source]
rise_ends: tuple[float, ...][source]
scale_by(scale: float) MultiModalTrapezoidalFun[source]
scales: tuple[float, ...] | None[source]
shift_by(offset: float) MultiModalTrapezoidalFun[source]
starts: tuple[float, ...][source]
weights: tuple[float, ...] | None[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]
class negmas.preferences.NB3ParetoSampler(max_nodes: int = 10000)[source]

Bases: object

Pareto sampler using the NB3 Branch-and-Bound algorithm.

NB3 exploits the additive structure of both utility functions to prune the search space via per-agent upper-bound estimates, finding the Pareto frontier in an anytime fashion (stops after max_nodes node expansions).

Requirements: both the agent’s own ufun and the opponent ufun must be LinearAdditiveUtilityFunction instances. init() raises TypeError if this is not satisfied.

The utility functions are supplied to init (init(ufun, opponent_ufun)), not the constructor: the constructor takes configuration only.

Parameters:

max_nodes – Maximum number of nodes to expand. Default: 10000.

AI supported (config-only constructor; operands supplied to ``init``).

best_for_opponent(*, min_util: float, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) Outcome | None[source]
init(ufun: BaseUtilityFunction | None = None, opponent_ufun: BaseUtilityFunction | None = None) None[source]

Run the NB3 branch-and-bound algorithm to build the Pareto frontier.

Parameters:
  • ufun – The agent’s own utility function (supplied here, not in the constructor). Omit to keep the current one.

  • opponent_ufun – Estimate of the opponent’s utility function. Omit to keep the current estimate.

Raises:

TypeError – if own or opponent ufun is not a LinearAdditiveUtilityFunction.

property initialized: bool[source]
pareto_outcomes(n: int | None = None, *, min_util: float = 0.0, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) list[Outcome][source]
set_opponent_ufun(opponent_ufun: BaseUtilityFunction | None) None[source]

Update the opponent utility function and mark as not initialized.

property ufun: BaseUtilityFunction | None[source]
class negmas.preferences.NegotiatorMetrics(utility: float = nan, advantage: float = nan, opponent_advantage: float = nan, utility_agreed: float = nan, advantage_agreed: float = nan, opponent_advantage_agreed: float = nan, surplus_share: float = nan, rationality: float = nan, exploited: float = nan, rational_agreement: float = nan, dominance: float = nan, concession_rate: float = nan, total_concession: float = nan, temporal_patience: float = nan, first_offer_utility: float = nan, monotonic_concession: float = nan, relative_n_offers: float = nan, outcome_space_exploration: float = nan, offer_variability: float = nan, own_gain: float = nan, copling_raio: float = nan, concession_toward_counterparty: float = nan, valid_offer_fraction: float = nan, produced_any_offers: float = nan, opp_kendall_optimality: float = nan, opp_ndcg: float = nan, opp_euclidean: float = nan)[source]

Bases: object

Per-negotiator metrics evaluating one party’s behaviour and outcome in a single negotiation.

Every field is a float; nan means the metric is undefined for this negotiation (e.g. trace-based metrics when no offer trace was supplied, or opponent-model metrics when no opponent_ufun estimate was exposed). Booleans are encoded as 1.0 / 0.0. All metrics are for the negotiator at index passed to calc_negotiator_metrics().

These are exactly the metrics that depend on which negotiator is being scored; negotiator-independent (session-level) quantities live in SessionMetrics instead, and the two field sets are disjoint.

Outcome-level (need only the realised utilities + reserved values):

  • utility: realised utility of indexufun(agreement) if an agreement was reached, else its reservation value (the “Score(all)” convention of lewis2017, where a failed negotiation is worth the walk-away value).

  • advantage: scale-free gain (u - r) / (max - r) of index (negmas’ advantage; 0.0 when max == r). Falls back to the raw surplus u - r when utility_ranges is not supplied.

  • opponent_advantage: mean advantage of the other parties (the advantage-scale analogue of negmas’ partner_welfare).

  • utility_agreed / advantage_agreed / opponent_advantage_agreed: the same readings but nan when no agreement was reached, so an nan-ignoring mean over negotiations gives the “agreement-only” reading (lewis2017’s “Score(agreed)” vs “Score(all)”).

  • surplus_share: index’s share (u_i - r_i) / sum_j (u_j - r_j) (xia2024 Share). Not clipped – may exceed 1 or be negative; nan when the total surplus is <= 0.

Individual rationality:

  • rationality: 0.0 if index accepted an agreement below its own reservation value (an individually-irrational acceptance, the ir_violation of bilateraltrade2026), else 1.0. Walking away is always rational.

  • exploited: 1.0 if index’s rationality is 0.0 (it accepted an individually-irrational deal) and at least one other party realised strictly more than its own reservation value (someone else profited from that irrational acceptance), else 0.0.

  • rational_agreement: 1.0 if an agreement was reached and every party (not just index) realised at least its reservation value, else 0.0 (bilateraltrade2026 Def. 4). Identical for every party of the same negotiation.

Win/loss:

  • dominance: 1.0 if index’s realised advantage strictly exceeds the best realised advantage among the other parties (a win), 0.0 for a tie, -1.0 for a loss (bianchi2024). The aggregate win rate is conventionally sum(won) / (sum(won) + sum(lost)) – ties excluded from the denominator. nan when there are no other parties.

Concession behaviour (trace-based; nan without an offer trace or if the party made no own offers):

  • total_concession: s[0] - s[-1] where s is index’s own utility over its own successive offers; positive means it conceded (bilateraltrade2026).

  • concession_rate: average per-offer drop in own utility, (s[0] - s[-1]) / max(k - 1, 1).

  • temporal_patience: how long index held its opening anchor before conceding, as the fraction of its own offers before the first whose utility dropped below s[0]; 1.0 if it never dropped (bilateraltrade2026).

  • first_offer_utility: index’s own utility of its first own offer, s[0]; on a normalized [0, 1] scale, values near 1.0 mean it opened by demanding nearly everything for itself.

  • monotonic_concession: fraction of consecutive own-offer steps that are non-increasing in own utility (s[t + 1] <= s[t] + eps), i.e. how consistently index conceded rather than oscillated; nan when it made fewer than two own offers (no step to evaluate).

Offer coverage (trace-based; needs trace_offers/outcome_space, in addition to an offer trace):

  • relative_n_offers: number of index’s own offers, relative to the size of the outcome space – len(own_offers) / |outcome_space|. nan when the outcome space’s cardinality is unavailable or infinite.

  • outcome_space_exploration: fraction of the outcome space index touched via unique own offers – |unique(own_offers)| / |outcome_space|. nan under the same conditions as relative_n_offers, or without trace_offers.

  • offer_variability: fraction of index’s own offers that were distinct outcomes – |unique(own_offers)| / len(own_offers); 1.0 means it never repeated an offer, values near 0 mean it kept re-submitting the same few outcomes. nan without trace_offers.

Strategic coupling (trace-based; nan without a trace or fewer than two own offers):

  • concession_toward_counterparty: sum, over consecutive own offers, of the positive part of the change in the primary partner’s utility of those offers (counterparty2026).

  • own_gain: signed net change s[-1] - s[0] in index’s own utility over its own offers (<= 0 for a purely conceding agent).

  • copling_raio: coupling ratio – concession_toward_counterparty / (abs(own_gain) + eps) (counterparty2026). (Field name retains the original spelling; reads “coupling ratio”.)

Instruction / format following (trace-based):

  • valid_offer_fraction: fraction of index’s own offers that are structured and lie in the outcome space; nan when no trace_offers / outcome_space were supplied or the party made no own offers.

  • produced_any_offers: 1.0 if index made at least one own offer, 0.0 if it has a trace but made none, nan only when there is no trace at all.

Opponent-model accuracy (only when index exposes an opponent_ufun estimate and the true opponent ufun + outcome space are supplied):

  • opp_kendall_optimality / opp_ndcg / opp_euclidean: agreement between index’s estimated opponent ufun and the true opponent ufun, via compare_ufuns(), in [0, 1] (higher = better model). nan when no opponent model is available.

References

  • lewis2017: Lewis et al., “Deal or No Deal? End-to-End Learning for Negotiation Dialogues”, EMNLP 2017.

  • bianchi2024: Bianchi et al., “How Well Can LLMs Negotiate? NegotiationArena Platform and Analysis”, ICML 2024.

  • xia2024: Xia et al., “Measuring Bargaining Abilities of LLMs”, Findings of ACL 2024.

  • bilateraltrade2026: “Training Language Models for Bilateral Trade with Private Information”, arXiv 2026.

  • counterparty2026: “Counterparty Modeling is Not Strategy: The Limits of LLM Negotiators”, arXiv 2026.

advantage: float[source]
advantage_agreed: float[source]
concession_rate: float[source]
concession_toward_counterparty: float[source]
copling_raio: float[source]
dominance: float[source]
exploited: float[source]
first_offer_utility: float[source]
monotonic_concession: float[source]
offer_variability: float[source]
opp_euclidean: float[source]
opp_kendall_optimality: float[source]
opp_ndcg: float[source]
opponent_advantage: float[source]
opponent_advantage_agreed: float[source]
outcome_space_exploration: float[source]
own_gain: float[source]
produced_any_offers: float[source]
rational_agreement: float[source]
rationality: float[source]
relative_n_offers: float[source]
surplus_share: float[source]
temporal_patience: float[source]
total_concession: float[source]
utility: float[source]
utility_agreed: float[source]
valid_offer_fraction: float[source]
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: 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: 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 utility values to a specified range.

Parameters:

to – The target range as (min, max), defaults to (0.0, 1.0).

Returns:

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

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

Euclidean distances from an outcome to various solution concept points.

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

Optimality metrics measuring how close an outcome is to various solution concepts.

property fairness: float[source]
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: 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.ParetoSampler(*args, **kwargs)[source]

Bases: Protocol

Protocol for components that sample from the approximate Pareto frontier.

A ParetoSampler wraps the agent’s own utility function and, optionally, an estimate of the opponent’s utility function to answer trade-off queries: finding outcomes that are approximately Pareto-optimal with respect to both the agent’s own utility and the opponent’s utility.

Access to the opponent’s utility estimate is expected via Negotiator.opponent_ufun (which returns None when no estimate is available, e.g. at the start of a negotiation).

best_for_opponent(*, min_util: float, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) Outcome | None[source]

Return the outcome that maximises the opponent’s utility subject to own utility ≥ min_util.

This corresponds to the trade-off query from the BIDS paper (Koça et al., 2024):

argmax  u'(ω)
 ω ∈ Ω
subject to  u(ω) ≥ min_util
Parameters:
  • min_util – Minimum required own utility.

  • normalized – if True, min_util is in normalised [0,1] space.

  • opponent_ufun – Opponent utility function. Defaults to the stored opponent ufun.

Returns:

The best trade-off outcome, or None if no opponent ufun is available or no outcome satisfies the constraint.

init(ufun: BaseUtilityFunction | None = None, opponent_ufun: BaseUtilityFunction | None = None) None[source]

One-time (offline) initialisation — receives the operands.

The agent’s own ufun and the opponent estimate are supplied here rather than to the constructor, because this is where the expensive setup (building a DP table / computing the Pareto frontier) happens. A single instance can therefore be re-init-ed with new operands instead of being recreated.

Parameters:
  • ufun – The agent’s own utility function. Omit to keep the value from a previous init (e.g. when only the opponent estimate changed).

  • opponent_ufun – Estimate of the opponent’s utility function. Omit to keep the previous estimate. While it is None the sampler stays uninitialised (queries return empty / None).

property initialized: bool[source]

Whether init() has been called.

pareto_outcomes(n: int | None = None, *, min_util: float = 0.0, normalized: bool = False, opponent_ufun: BaseUtilityFunction | None = None) list[Outcome][source]

Return a list of approximately Pareto-optimal outcomes.

Parameters:
  • n – Maximum number of outcomes to return (None = return all found on the approximate frontier).

  • min_util – Only return outcomes with own utility ≥ this value.

  • normalized – if True, min_util is in normalised [0,1] space (0 = worst, 1 = best for own ufun).

  • opponent_ufun – Opponent utility function to use for this call. If None, the instance’s stored opponent ufun is used.

Returns:

A list of outcomes on (or close to) the Pareto frontier, filtered by min_util. May be empty if no opponent ufun is available or if no rational outcome exists.

property ufun: BaseUtilityFunction | None[source]

The agent’s own utility function (None until init sets it).

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 maximum utility to a target value for a subset of outcomes.

Parameters:
  • to – The target value for the maximum utility.

  • outcome_space – The outcome space to consider for scaling.

  • issues – Alternative way to specify the domain via issues.

  • outcomes – Alternative way to specify the domain via explicit outcomes.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the maximum scaled for the specified domain.

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 minimum utility to a target value for a subset of outcomes.

Parameters:
  • to – The target value for the minimum utility.

  • outcome_space – The outcome space to consider for scaling.

  • issues – Alternative way to specify the domain via issues.

  • outcomes – Alternative way to specify the domain via explicit outcomes.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the minimum scaled for the specified domain.

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 maximum utility to a target value for a subset of outcomes.

Parameters:
  • to – The target value for the maximum utility.

  • outcome_space – The outcome space to consider for shifting.

  • issues – Alternative way to specify the domain via issues.

  • outcomes – Alternative way to specify the domain via explicit outcomes.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the maximum shifted for the specified domain.

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 minimum utility to a target value for a subset of outcomes.

Parameters:
  • to – The target value for the minimum utility.

  • outcome_space – The outcome space to consider for shifting.

  • issues – Alternative way to specify the domain via issues.

  • outcomes – Alternative way to specify the domain via explicit outcomes.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the minimum shifted for the specified domain.

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]

Find the min/max values by sampling (exact method not yet implemented).

scale_by(scale: float) PolynomialFun[source]

Return a new PolynomialFun with all coefficients scaled.

shift_by(offset: float) PolynomialFun[source]

Return a new PolynomialFun with the bias shifted by the given offset.

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

Export this polynomial function to GENIUS XML format.

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, stability: Stability | int = <Stability.SESSION_INDEPENDENT|STATE_INDEPENDENT|STABLE_MIN|STABLE_MAX|STABLE_EXTREMES|STABLE_RESERVED_VALUE|FIXED_RESERVED_VALUE|STABLE_RATIONAL_OUTCOMES|STABLE_IRRATIONAL_OUTCOMES|STABLE_ORDERING|STABLE_DIFF_RATIOS: 2047>, **kwargs)[source]

Bases: NamedObject, ABC

Base class for all preferences.

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

  • stability – Stability flags describing which aspects of the preferences remain stable. Default is STATIONARY (all stability flags set).

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.

property has_fixed_reserved_value: bool[source]

Check if reserved value (absolute) is fixed.

property has_stable_diff_ratios: bool[source]

Check if relative utility differences are stable.

property has_stable_extremes: bool[source]

Check if extreme (best/worst) outcomes are stable.

property has_stable_irrational_outcomes: bool[source]

Check if irrational outcomes remain irrational.

property has_stable_max: bool[source]

Check if maximum utility is stable.

property has_stable_min: bool[source]

Check if minimum utility is stable.

property has_stable_ordering: bool[source]

Check if outcome ordering is stable.

property has_stable_rational_outcomes: bool[source]

Check if rational outcomes remain rational.

property has_stable_reserved_value: bool[source]

Check if reserved value (relative) is stable.

property has_stable_scale: bool[source]

Check if scale is stable (min, max, and relative reserved value).

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

property is_scale_invariant: bool[source]

Check if scale-invariant (stable diff ratios and relative reserved value).

is_session_dependent() bool[source]

Does the utility of an outcome depend on the NegotiatorMechanismInterface?

Returns True if not all stability flags are set (i.e., not fully stationary).

is_state_dependent() bool[source]

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

Returns True if not all stability flags are set (i.e., not fully stationary).

is_stationary() bool[source]

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

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

  • Returns True if stability is VOLATILE (value = 0, no stability guarantees)

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

property owner: Rational | None[source]

Returns the owner of these preferences.

The owner is the negotiator currently using these preferences in a negotiation.

Note

The owner is only valid during an active negotiation. It is set when the negotiator enters a negotiation (during _on_negotiation_start) and cleared when the negotiation ends (during _on_negotiation_end). Outside of an active negotiation, owner will be None.

reset_changes() None[source]

Will be called whenever we need to reset changes.

property stability: Stability[source]

Returns the stability flags for these preferences.

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), "price")]
...     ).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, eps: float = 1e-12, rel_eps: float = 1e-06, clamp_tolerance: float = inf)[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. Queries (worst_in/best_in/some/one_in) then binary-search this cached, sorted array using numpy.searchsorted, giving O(log n) lookups after an O(n log n) one-time construction cost.

This is the recommended/default presorting-based inverter. PresortingLegacyInverseUtilityFunction is a functionally-equivalent (but slower, legacy) sibling that adds coarse waypoint-based search-window narrowing before the final bisection; use it only if you specifically need that legacy behavior for backwards compatibility.

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)

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

  • clamp_tolerance – Maximum distance (in utility units) that worst_in/best_in/one_in are allowed to clamp outside the requested range when the range contains no outcome. When the requested range is empty, these methods return the nearest achievable outcome on the appropriate side (worst_in clamps up, best_in clamps down) so negotiators never stall. If that nearest outcome lies further than clamp_tolerance outside the range, None is returned instead (and one_in falls back per its fallback_to_* flags). Defaults to float("inf") which disables the cap entirely (unbounded clamping — the historical behavior).

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

  • worst_in/best_in/some/one_in binary-search directly over the full sorted range of rational outcomes ([0, last_rational]).

  • Clamping is always to the single nearest achievable outcome (it never skips a closer one), but its distance is only bounded by the gap in the utility distribution; use clamp_tolerance to cap it.

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

closest(target: float, normalized: bool = False) tuple | None[source]

Finds the single (rational) outcome whose utility is closest to target.

Uses bisection over the sorted array of rational-outcome utilities to locate the insertion point, then compares the neighbor immediately below and above it, returning the true argmin.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalized [0, 1] space.

Returns:

The closest outcome, or None if there are no rational 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]

Initializes the inverter by enumerating and sorting outcomes by utility.

property initialized[source]

Whether the inverter has been initialized with sorted outcomes.

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: float | 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]

Returns the outcome at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The outcome at that rank, or None if index is out of bounds.

reset() None[source]

Clears cached outcomes and resets the inverter to uninitialized state.

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]

The utility function being inverted.

utility_at(indx: int) float[source]

Returns the utility value at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The utility value at that rank, or -inf if index is out of bounds.

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-06) 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.PresortingInverseUtilityFunctionBruteForce(ufun: BaseUtilityFunction, levels: int = 10, max_cache_size: int = 10000000000, rational_only: bool = False)[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.

This is a strict inverter (see module docs). worst_in/best_in return None when no outcome’s utility falls inside the requested range — they never clamp, expand the range, or fall back to an out-of-range outcome. one_in has the usual fallback_to_higher/fallback_to_best fallbacks (both default True).

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

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

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

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

Finds an outcome with the highest utility within the given range.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

Returns:

The outcome with highest utility in the range, or None if not found.

closest(target: float, normalized: bool = False) tuple | None[source]

Finds the single (rational) outcome whose utility is closest to target.

This is the ground-truth utility-lookup query (argmin_ω |u(ω) - target|): a plain linear scan over the sorted rational outcomes, guaranteed to return the true argmin.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalized [0, 1] space.

Returns:

The closest outcome, or None if there are no rational 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]

Initializes the inverter by enumerating and sorting outcomes by utility.

property initialized[source]

Whether the inverter has been initialized with sorted outcomes.

max() float[source]

Finds the maximum utility value

min() float[source]

Finds the minimum utility value

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 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: float | tuple[float, float], normalized: bool, fallback_to_higher: bool = True, fallback_to_best: bool = True) tuple | None[source]

Finds any outcome within the given utility range.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • fallback_to_higher – If True, expand range upward when no match found.

  • fallback_to_best – If True, return best outcome as last resort.

Returns:

An outcome within the range, or None if not found and fallbacks disabled.

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

Returns the outcome at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The outcome at that rank, or None if index is out of bounds.

reset() None[source]

Clears cached outcomes and resets the inverter to uninitialized state.

some(rng: float | tuple[float, float], normalized: bool, n: int | None = None, fallback_to_higher: bool = True, fallback_to_best: bool = True) 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]

The utility function being inverted.

utility_at(indx: int) float[source]

Returns the utility value at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The utility value at that rank, or -inf if index is out of bounds.

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)

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

worst() tuple | None[source]

Finds the worst outcome

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

Finds an outcome with the lowest utility within the given range.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

Returns:

The outcome with lowest utility in the range, or None if not found.

class negmas.preferences.PresortingLegacyInverseUtilityFunction(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.

This is a clamping inverter (see module docs). worst_in/best_in use _nearest_around to clamp to the nearest achievable outcome when the requested range is empty, and one_in falls back per its fallback_to_* flags. The clamping distance is not capped (unlike PresortingInverseUtilityFunction’s clamp_tolerance).

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

closest(target: float, normalized: bool = False) tuple | None[source]

Finds the single (rational) outcome whose utility is closest to target.

Uses bisection over the sorted array of rational-outcome utilities to locate the insertion point, then compares the neighbor immediately below and above it, returning the true argmin.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalized [0, 1] space.

Returns:

The closest outcome, or None if there are no rational 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]

Initializes the inverter by enumerating and sorting outcomes by utility.

property initialized[source]

Whether the inverter has been initialized with sorted outcomes.

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]

Returns the outcome at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The outcome at that rank, or None if index is out of bounds.

reset() None[source]

Clears cached outcomes and resets the inverter to uninitialized state.

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]

The utility function being inverted.

utility_at(indx: int) float[source]

Returns the utility value at the given rank index (0 = best).

Parameters:

indx – The rank index, where 0 is the best outcome.

Returns:

The utility value at that rank, or -inf if index is out of bounds.

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-06) 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: 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]

Generate a random probabilistic mapping utility function.

Parameters:
  • outcome_space – The space of possible outcomes to generate mappings for.

  • reserved_value – The utility for no agreement or range (min, max) for random selection.

  • normalized – If True, normalize utility distribution parameters to [0, 1] range.

  • max_cardinality – Maximum number of outcomes to sample for discrete approximation.

  • type – The type of scipy distribution to use (e.g. ‘uniform’, ‘norm’).

to_dict(python_class_identifier='__python_class__')[source]

To dict.

Parameters:

python_class_identifier – Python class identifier.

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

Generate XML representation (not implemented for probabilistic utility functions).

Parameters:

issues – The issues defining the outcome space.

Raises:

NotImplementedError – This utility function type cannot be serialized to XML.

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: 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: Distribution | float = -inf, invalid_value: float | None = None, constraints: Iterable[Callable[[tuple], bool]] | 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]

Find the min/max values, accounting for the parabola’s extremum.

scale_by(scale: float) QuadraticFun[source]

Return a new QuadraticFun with all coefficients scaled.

shift_by(offset: float) QuadraticFun[source]

Return a new QuadraticFun with the bias shifted by the given offset.

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

Export this quadratic function to GENIUS XML format.

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: UtilityFunction

A random utility function for a discrete outcome space

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

Evaluates the given offer, returning a cached random utility value.

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: 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, rel_max_samples_per_call: float = 1.5, eps: float = 0.001, rel_eps: float = 0.05, multiplier: int = 3, strict_limit: float = 0.1)[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.

This is a clamping inverter (see module docs). When worst_in/best_in fail to find an in-range outcome (common when the range is narrow and contains only a single outcome that the random sample missed), they expand the range upward and, if still nothing is found, fall back to the nearest boundary outcome (best if the range is in the upper half of the utility range, worst if in the lower half). one_in always had these fallbacks; worst_in/ best_in gained them to avoid returning None and breaking the SAO mechanism.

Parameters:
  • ufun – The utility function to invert

  • max_samples_per_call – The maximum number of samples to draw per call

  • rel_max_samples_per_call – The maximum number of samples to draw per call relative to the size of the outcome space (default: 1.5)

  • eps – The absolute tolerance for utility matching (default: 0.001)

  • rel_eps – The relative tolerance for utility matching (default: 0.05)

  • multiplier – The number of samples to draw per call relative to the requested number of outcomes (default: 3)

  • strict_limit – The fraction of the sampling loop during which we search with zero tolerance (default: 0.1)

Remarks:
  • min, max, worst, best and minmax are not computed through sampling. They simply delegate to the wrapped ufun’s own minmax/extreme_outcomes (which may use closed-form solutions for some ufun types, e.g. linear ufuns, or fall back to sampling internally). This avoids duplicating (weaker) sampling logic here.

  • within_fractions and within_indices are approximate: because this inverter never maintains a full ranking of outcomes, a fresh sample is ranked every time these are called. Use PresortingInverseUtilityFunction if you need exact results.

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() tuple | None[source]

Finds the best outcome.

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

Finds an outcome with the highest utility within the given range using sampling.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found, and fallback_to_higher is True, the range is expanded upward to [rng[0], 1] (normalized) or [rng[0], self.max] (raw) and the search is retried without fallback_to_higher.

  • If still nothing is found and fallback_to_best is True, the best outcome overall is returned.

  • Otherwise None is returned.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • fallback_to_higher – If True, expand the range upward when no match found.

  • fallback_to_best – If True, return the best outcome as a last resort.

Returns:

The outcome with highest utility in the range, or a fallback, or None.

closest(target: float, normalized: bool = False) tuple | None[source]

Approximates the outcome whose utility is closest to target by drawing the usual number of random samples and returning the sampled outcome minimizing |u(o) - target|.

Parameters:
  • target – The target utility value.

  • normalized – if True, target is in normalized [0, 1] space.

Returns:

The (approximately) closest outcome, or None if the outcome space is unknown/empty.

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

Finds the worst and best outcomes that can be returned.

Remarks:
  • Delegates to ufun.extreme_outcomes() for the same reason as minmax().

init()[source]

Initialize the inverter (no-op for sampling-based inverter).

property initialized[source]

Whether the inverter has been initialized.

max() float[source]

Finds the maximum utility value that can be returned.

min() float[source]

Finds the minimum utility value that can be returned.

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

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

Remarks:
  • Delegates to ufun.minmax() (which may itself use closed-form solutions for some ufun types or fall back to sampling) instead of re-implementing sampling here, since this is cheaper and at least as accurate.

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

Finds any outcome within the given utility range using random sampling.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • fallback_to_higher – If True, expand range upward when no match found.

  • fallback_to_best – If True, return best outcome as last resort.

Returns:

An outcome within the range, or None if not found and fallbacks disabled.

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]

The utility function being inverted.

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

Approximates the outcomes within the given fractions of utility values using sampling.

Remarks:
  • This is inherently approximate: max_samples_per_call outcomes are drawn, sorted by utility, and the outcomes whose rank (as a fraction of the sample) falls within rng are returned. Use PresortingInverseUtilityFunction for exact results.

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

Approximates the outcomes within the given rank indices (0 = best) using sampling.

Remarks:
worst() tuple | None[source]

Finds the worst outcome.

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

Finds an outcome with the lowest utility within the given range using sampling.

Fallback behavior (clamping inverter — see module docs):

  • If no in-range outcome is found, and fallback_to_higher is True, the range is expanded upward to [rng[0], 1] (normalized) or [rng[0], self.max] (raw) and the search is retried without fallback_to_higher.

  • If still nothing is found and fallback_to_worst is True, the nearest boundary outcome is returned: the best outcome if the range lies above the maximum utility, the worst outcome if it lies below the minimum. This keeps the fallback close to the requested range (important for negotiators that ask for high-utility outcomes).

  • Otherwise None is returned.

Parameters:
  • rng – The utility range (single value or (min, max) tuple).

  • normalized – Whether the range is normalized to [0, 1].

  • fallback_to_higher – If True, expand the range upward when no match found.

  • fallback_to_worst – If True, return the nearest boundary outcome as a last resort.

Returns:

The outcome with lowest utility in the range, or a fallback, or 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]

Multiply all utility values by a constant factor.

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

  • scale_reserved – Whether to also scale the reserved value.

Returns:

A new utility function with scaled values.

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

Scale utility values so the maximum becomes the target value.

Parameters:
  • to – The target value for the maximum utility.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the maximum scaled to the target.

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

Scale utility values so the minimum becomes the target value.

Parameters:
  • to – The target value for the minimum utility.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the minimum scaled to the target.

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, rational_fraction: float | None = None, convex_hull: bool = False)[source]

Bases: object

Statistics computed for a negotiation scenario including Pareto frontier and solution concepts.

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]

rational_fraction[source]

Fraction of outcomes rational for all negotiators (optional). May be None if loaded from older versions or not calculated.

Type:

float | None

convex_hull[source]

Whether these stats were computed under the P∞ (multiple-negotiations / convex-hull) evaluation model of pareto_frontier_convex_hull (True) or the ordinary single-negotiation P model (False, default). Carried on the stats object so calc_outcome_distances/calc_outcome_optimality honor the same model without a separate parameter. When True, the Nash/Kalai/KS *_utils hold a single mixture point (a lottery over hull vertices, not any one outcome) and the corresponding *_outcomes are empty.

Type:

bool

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.

The rational_fraction field may be None when: - Stats were loaded from older versions that didn’t include this field - Stats were explicitly calculated without this metric

convex_hull: bool[source]
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, convex_hull: bool = False) ScenarioStats[source]

Computes scenario statistics from a collection of utility functions.

Parameters:
  • ufuns – The utility functions for all negotiators.

  • outcomes – The outcomes to consider. If None, derived from the outcome space.

  • eps – Tolerance for floating-point comparisons.

  • convex_hull – If True, compute under the P∞ (convex-hull / multiple-negotiations) evaluation model; otherwise the ordinary single-negotiation P model (default).

Returns:

ScenarioStats containing Pareto frontier and solution concept points.

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]
rational_fraction: float | None[source]
restrict(ufuns: tuple[UtilityFunction], reserved_values: tuple[float, ...], convex_hull: bool | None = None) ScenarioStats[source]

Restricts scenario stats to outcomes above given reserved values.

Parameters:
  • ufuns – The utility functions for all negotiators.

  • reserved_values – Minimum acceptable utility for each negotiator.

  • convex_hull – Whether to recompute the solution concepts under the P∞ (convex-hull) evaluation model. If None (default), the mode is inherited from self.convex_hull.

Returns:

New ScenarioStats with only rational outcomes above the reserved values.

to_dict(include_pareto_frontier: bool = True, include_pareto_utils: bool | None = None, include_pareto_outcomes: bool | None = None) dict[source]

Convert to dictionary with optional exclusion of pareto frontier data.

Parameters:
  • include_pareto_frontier – If True, include both pareto_utils and pareto_outcomes. If False, exclude both. Default is True. This is overridden by the more specific include_pareto_utils and include_pareto_outcomes parameters.

  • include_pareto_utils – If specified, controls inclusion of pareto_utils independently. If None, uses the value of include_pareto_frontier.

  • include_pareto_outcomes – If specified, controls inclusion of pareto_outcomes independently. If None, uses the value of include_pareto_frontier.

Returns:

Dictionary representation of the ScenarioStats.

Notes

When pareto data is excluded, the corresponding 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(*args, **kwargs)[source]

Bases: object

Indicates that the ufun is session-dependent (i.e. utility value of outcomes depend on the NMI).

Deprecated since version Use: appropriate stability parameter instead::

# Old way (deprecated): class MyUfun(SessionDependentUFunMixin, BaseUtilityFunction):

def eval_on_session(self, offer, nmi): …

# New way: Clear SESSION_INDEPENDENT flag in constructor ufun = MyUtilityFunction(…, stability=STATIONARY & ~SESSION_INDEPENDENT)

This mixin clears the SESSION_INDEPENDENT flag from stability while preserving other stability guarantees. Being session-dependent does not imply volatility - the ufun may still have stable ordering, diff ratios, etc.

The preferred approach is to pass an appropriate stability value to the constructor.

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.SessionMetrics(welfare: float = nan, welfare_agreed: float = nan, utility_sum: float = nan, agreement_reached: float = nan, utility_gap: float = nan, advantage_gap: float = nan, gains_from_trade: float = nan, surplus_efficiency: float = nan, relative_rounds: float = nan, agreement_speed: float = nan, relative_efficiency: float = nan)[source]

Bases: object

Session-level metrics evaluating a single negotiation as a whole.

Every field is a float; nan means the metric is undefined for this negotiation. Booleans are encoded as 1.0 / 0.0. All metrics here are negotiator-independent: they take the same value no matter which party you ask about (welfare, agreement, timing, inequality/spread and total surplus). Metrics that depend on a specific negotiator live in NegotiatorMetrics instead, and the two field sets are disjoint.

All metrics are computed from the realised (agreement or reserved) utilities of every party plus the per-party reservation values; none of them needs the offer trace.

Welfare:

  • welfare: mean realised utility across all parties (negmas’ welfare; the “collective score” of abdelnabi2024).

  • welfare_agreed: welfare but nan when no agreement was reached (so an nan-ignoring mean over negotiations gives the agreement-only reading).

  • utility_sum: sum of realised utilities across all parties (the papers’ “social welfare” sum form; welfare is the mean).

Agreement / feasibility:

  • agreement_reached: 1.0 if an agreement was reached, 0.0 otherwise.

Inequality (fairness as inequality between parties – distinct from negmas’ solution-concept fairness):

  • utility_gap: raw-utility inequality across all parties, max(u) - min(u) (bilateral: abs(u_i - u_j)). Larger = less fair (he2018, shea2024, chatterjee2024).

  • advantage_gap: scale-free inequality across all parties, max(adv) - min(adv). Preferred headline since it is unaffected by per-party utility scaling. Falls back to raw-surplus advantages when utility_ranges is not supplied.

Surplus / efficiency:

  • gains_from_trade: total surplus over disagreement sum_j (u_j - r_j) (signed; bilateraltrade2026 / xia2024).

  • surplus_efficiency: captured surplus over the maximum achievable, T / T_max where T_max is the largest total gains-from-trade on the Pareto frontier (or, failing that, over the utility ranges). nan when T_max <= 0 (termsbench SE+).

Length / efficiency:

  • relative_rounds: the mechanism’s relative time at the end, in [0, 1].

  • agreement_speed: 1.0 - relative_time when an agreement was reached, 0.0 otherwise (faster agreements score higher).

  • relative_efficiency: fairness-per-turn, -utility_gap / max(rounds, 1) (chatterjee2024).

References

  • he2018: He et al., “Decoupling Strategy and Generation in Negotiation Dialogues”, EMNLP 2018.

  • shea2024: Shea & Yu, “A Fairness-Driven Method for Learning Human-Compatible Negotiation Strategies”, Findings of EMNLP 2024.

  • chatterjee2024: Chatterjee et al., “AgreeMate: Teaching LLMs to Haggle”, arXiv 2024.

  • abdelnabi2024: Abdelnabi et al., “Cooperation, Competition, and Maliciousness: LLM-Stakeholders Interactive Negotiation”, NeurIPS D&B 2024.

  • xia2024: Xia et al., “Measuring Bargaining Abilities of LLMs”, Findings of ACL 2024.

  • bilateraltrade2026: “Training Language Models for Bilateral Trade with Private Information”, arXiv 2026.

  • termsbench2026: “TERMS-Bench: Diagnosing LLM Negotiation Agents Beyond Deal Rate”, arXiv 2026.

advantage_gap: float[source]
agreement_reached: float[source]
agreement_speed: float[source]
gains_from_trade: float[source]
relative_efficiency: float[source]
relative_rounds: float[source]
surplus_efficiency: float[source]
utility_gap: float[source]
utility_sum: float[source]
welfare: float[source]
welfare_agreed: float[source]
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 all utility values by a constant offset.

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

  • shift_reserved – Whether to also shift the reserved value.

Returns:

A new utility function with shifted values.

abstractmethod shift_max(to: float, rng: tuple[float, float] | None = None) Shiftable[source]

Shift utility values so the maximum becomes the target value.

Parameters:
  • to – The target value for the maximum utility.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the maximum shifted to the target.

abstractmethod shift_min(to: float, rng: tuple[float, float] | None = None) Shiftable[source]

Shift utility values so the minimum becomes the target value.

Parameters:
  • to – The target value for the minimum utility.

  • rng – Optional current range; if None, computed automatically.

Returns:

A new utility function with the minimum shifted to the target.

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]

Find the min/max values by sampling (exact method not yet implemented).

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

Return a new SinFun with amplitude and bias scaled.

shift_by(offset: float) SinFun[source]

Return a new SinFun with the bias shifted by the given offset.

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

Export this sine function to GENIUS XML format.

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]

Compute the maximum value of this function over the given issue.

Parameters:

input – The issue to compute the maximum over.

Returns:

The maximum utility value for any value of the issue.

min(input: Issue) float[source]

Compute the minimum value of this function over the given issue.

Parameters:

input – The issue to compute the minimum over.

Returns:

The minimum utility value for any value of the issue.

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

Generate XML representation for GENIUS compatibility.

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

  • issue – The issue this function maps values from.

  • bias – A constant offset to add to all values in the XML output.

Returns:

XML string representation of this value function.

class negmas.preferences.Stability(*values)[source]

Bases: IntFlag

Flags describing stability and independence properties of utility functions.

These flags can be combined using bitwise OR (|) to describe which aspects of a utility function remain stable during a negotiation.

Independence Flags:
SESSION_INDEPENDENT: The ufun does not depend on negotiation session details

(NMI values, number of negotiators, mechanism parameters, etc.)

STATE_INDEPENDENT: The ufun does not depend on negotiation state variables

(time, step, current offers, history, etc.). Note: anything that is NOT state-independent is considered VOLATILE.

Stability Flags (for specific aspects):

STABLE_MIN: The minimum utility value does not change STABLE_MAX: The maximum utility value does not change STABLE_EXTREMES: The extreme (best/worst) outcomes do not change. This is

weaker than STABLE_ORDERING - ordering may change but extremes stay fixed.

STABLE_RESERVED_VALUE: The reserved value relative to min/max does not change FIXED_RESERVED_VALUE: The absolute numeric reserved value does not change STABLE_RATIONAL_OUTCOMES: Rational outcomes (utility > reserved) stay rational STABLE_IRRATIONAL_OUTCOMES: Irrational outcomes (utility <= reserved) stay irrational STABLE_ORDERING: The ordering of outcomes by utility does not change.

Implies STABLE_EXTREMES (if ordering is stable, extremes are stable).

STABLE_DIFF_RATIOS: Relative differences between utilities stay the same.

Implies STABLE_ORDERING (if diff ratios are stable, ordering is stable).

Predefined Combinations:

VOLATILE: No stability guarantees (value = 0, all aspects may change) STATIONARY: All flags set - fully stable, session/state independent STABLE_SCALE: STABLE_MIN | STABLE_MAX | STABLE_RESERVED_VALUE SCALE_INVARIANT: STABLE_DIFF_RATIOS | STABLE_RESERVED_VALUE

Examples

>>> from negmas.preferences import (
...     Stability,
...     STABLE_MIN,
...     STABLE_MAX,
...     STATIONARY,
...     VOLATILE,
... )
>>> # Create a ufun with stable min and max
>>> stability = STABLE_MIN | STABLE_MAX
>>> bool(stability & STABLE_MIN)
True
>>> stability.is_volatile  # Not volatile - has some stability flags
False
>>> stability.is_stationary  # Not fully stationary either
False
>>> # Check volatile (no flags set)
>>> VOLATILE.is_volatile
True
>>> VOLATILE == 0
True
>>> # Check if fully stationary
>>> STATIONARY.is_stationary
True
>>> STATIONARY.is_volatile
False
FIXED_RESERVED_VALUE = 8[source]
SESSION_INDEPENDENT = 256[source]
STABLE_DIFF_RATIOS = 128[source]
STABLE_EXTREMES = 1024[source]
STABLE_IRRATIONAL_OUTCOMES = 32[source]
STABLE_MAX = 2[source]
STABLE_MIN = 1[source]
STABLE_ORDERING = 64[source]
STABLE_RATIONAL_OUTCOMES = 16[source]
STABLE_RESERVED_VALUE = 4[source]
STATE_INDEPENDENT = 512[source]
VOLATILE = 0[source]
property has_fixed_reserved_value: bool[source]

Check if reserved value (absolute) is fixed.

property has_stable_diff_ratios: bool[source]

Check if relative utility differences are stable.

property has_stable_extremes: bool[source]

Check if extreme (best/worst) outcomes are stable.

Note: STABLE_ORDERING implies STABLE_EXTREMES, and STABLE_DIFF_RATIOS implies STABLE_ORDERING, so this returns True if any of these are set.

property has_stable_irrational_outcomes: bool[source]

Check if irrational outcomes remain irrational.

property has_stable_max: bool[source]

Check if maximum utility is stable.

property has_stable_min: bool[source]

Check if minimum utility is stable.

property has_stable_ordering: bool[source]

Check if outcome ordering is stable.

property has_stable_rational_outcomes: bool[source]

Check if rational outcomes remain rational.

property has_stable_reserved_value: bool[source]

Check if reserved value (relative) is stable.

property has_stable_scale: bool[source]

Check if scale is stable (min, max, and relative reserved value).

property is_scale_invariant: bool[source]

Check if scale-invariant (stable diff ratios and relative reserved value).

property is_session_dependent: bool[source]

Check if the ufun depends on session details (NMI).

property is_session_independent: bool[source]

Check if the ufun does not depend on session details (NMI).

property is_state_dependent: bool[source]

Check if the ufun depends on state variables.

property is_state_independent: bool[source]

Check if the ufun does not depend on state variables.

property is_stationary: bool[source]

Check if fully stationary (all flags set, session and state independent).

property is_volatile: bool[source]

Check if volatile (no stability guarantees, value == 0).

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

Bases: object

Indicates that the ufun is state-dependent (i.e. utility value of outcomes depend on the mechanism state).

Deprecated since version Use: appropriate stability parameter instead::

# Old way (deprecated): class MyUfun(StateDependentUFunMixin, BaseUtilityFunction):

def eval_on_state(self, offer, nmi, state): …

# New way: Clear STATE_INDEPENDENT and SESSION_INDEPENDENT flags ufun = MyUtilityFunction(

…, stability=STATIONARY & ~STATE_INDEPENDENT & ~SESSION_INDEPENDENT

)

This mixin clears the STATE_INDEPENDENT flag from stability while preserving other stability guarantees. Being state-dependent does not imply volatility - the ufun may still have stable ordering, diff ratios, etc.

Note: State-dependent ufuns are also implicitly session-dependent since state is accessed through the session, so SESSION_INDEPENDENT is also cleared.

The preferred approach is to pass an appropriate stability value to the constructor.

eval(offer: Outcome) Value[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) Value[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(*args, **kwargs)[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.

Deprecated since version This: mixin is no longer needed since STATIONARY is the default stability. Simply don’t pass any stability parameter, or use the default::

# Old way (deprecated): class MyUfun(StationaryMixin, UtilityFunction):

pass

# New way (stability=STATIONARY is the default): ufun = MyUtilityFunction(…) # Already stationary by default

This mixin sets stability to STATIONARY (all stability flags set) by default. The preferred approach is to pass stability=STATIONARY to the constructor (which is the default).

Note: When using this mixin, if you pass a custom stability parameter to the constructor, the stability-related methods (is_stationary, is_volatile, etc.) will reflect that custom stability.

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.

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]

Return the number of issues from the first mapping key’s tuple length.

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

Find the min/max values by sampling all value combinations.

scale_by(scale: float) TableMultiFun[source]

Return a new TableMultiFun with all mapped values scaled.

shift_by(offset: float) TableMultiFun[source]

Return a new TableMultiFun with all mapped values shifted by offset.

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

Export to GENIUS XML format (not implemented for multi-issue tables).

class negmas.preferences.TrapezoidalFun(start: float, rise_end: float, fall_start: float, end: float, bias: float = 0, scale: float = 1)[source]

Bases: BaseFun

Trapezoidal value function: a triangular function with a flat top.

A piecewise-linear function that rises from bias at start to bias + scale at rise_end, stays at bias + scale until fall_start, 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}{r - s} & \text{if } s < x < r \\ b + k & \text{if } r \le x \le f \\ b + k \cdot \frac{e - x}{e - f} & \text{if } f < x < e \\ b & \text{if } x \ge e \end{cases}\end{split}\]

where \(s\) is start, \(r\) is rise_end, \(f\) is fall_start, \(e\) is end, \(b\) is bias, and \(k\) is scale.

Parameters:
  • start – x value where function starts rising from bias.

  • rise_end – x value where function first reaches the plateau (bias + scale).

  • fall_start – x value where function starts falling from the plateau.

  • end – x value where function returns to bias.

  • bias – Offset added to all values (default: 0).

  • scale – Height of the plateau above bias (default: 1).

Example

>>> f = TrapezoidalFun(start=0.0, rise_end=2.0, fall_start=8.0, end=10.0)
>>> f(0)    # At start: bias = 0
0.0
>>> f(1)    # Halfway up the rise: 0.5
0.5
>>> f(5)    # On the plateau: bias + scale = 1
1
>>> f(9)    # Halfway down the fall: 0.5
0.5
>>> f(10)   # At end: bias = 0
0.0

Note

Setting start == rise_end and fall_start == end reduces this to a rectangular (step) function. Setting rise_end == fall_start reduces this to TriangularFun.

bias: float[source]
end: float[source]
fall_start: float[source]
minmax(input) tuple[float, float][source]
rise_end: float[source]
scale: float[source]
scale_by(scale: float) TrapezoidalFun[source]
shift_by(offset: float) TrapezoidalFun[source]
start: float[source]
xml(indx: int, issue: Issue, bias=0.0) str[source]

Export this function to GENIUS XML format.

GENIUS has no native trapezoidal evaluator, so this is only supported for discrete issues via a lookup table.

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.UFunConstraint(ufun: BaseUtilityFunction, constraint: Callable[[Outcome], bool], *, name: str | None = None, outcome_space: OutcomeSpace | None = None, reserved_value: float | None = None, stability: Stability | int | None = None, **kwargs)[source]

Bases: UtilityFunctionAdapter

A utility function adapter that applies a constraint.

This adapter wraps a utility function and applies a constraint predicate. If the constraint is satisfied (predicate returns True), the utility value is returned unchanged. If the constraint is violated (predicate returns False), negative infinity is returned.

This is useful for enforcing constraints like budget limits, capacity constraints, or other feasibility requirements.

constraint[source]

A callable that takes an outcome and returns True if valid.

Example

>>> from negmas.preferences import LinearUtilityFunction
>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(5), make_issue(5)]
>>> base_ufun = LinearUtilityFunction(weights=[1.0, 1.0], issues=issues)
>>> # Constraint: sum of values must be <= 6
>>> constrained = UFunConstraint(
...     ufun=base_ufun, constraint=lambda o: sum(o) <= 6
... )
>>> constrained((2, 3))  # sum=5, valid
5.0
>>> constrained((4, 4))  # sum=8, invalid
-inf
property constraint: Callable[[tuple], bool][source]

The constraint predicate.

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

Evaluate the constrained utility of an offer.

Parameters:

offer – The outcome to evaluate.

Returns:

The utility value if constraint is satisfied, -inf otherwise.

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

Deserialize from dictionary.

Parameters:
  • d – Dictionary representation.

  • python_class_identifier – Key for class type.

Returns:

New instance.

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

Serialize to dictionary.

Parameters:

python_class_identifier – Key for storing class type.

Returns:

Dictionary representation.

to_stationary() UFunConstraint[source]

Returns a stationary version of this constrained utility function.

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]

Evaluate the utility of an offer.

Parameters:

offer – The outcome to evaluate.

Returns:

The crisp (deterministic) utility value as a float.

to_stationary() T[source]

Convert this utility function to a stationary (time-independent) version.

Returns:

A stationary version of this utility function.

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]

Evaluate the utility of an offer as a probability distribution.

Parameters:

offer – The outcome to evaluate.

Returns:

A distribution representing the probabilistic utility value.

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: Distribution | float = -inf, invalid_value: float | None = None, constraints: Iterable[Callable[[tuple], bool]] | 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 the first outcome is at least as good as the second.

Parameters:
  • first – The first outcome to compare.

  • second – The second outcome to compare.

Returns:

True if first has utility >= second, False otherwise.

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

  • outcome_space – The outcome space to search. If None, uses the ufun’s outcome space.

  • 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

Note

Results are cached based on stability flags (only when above_reserve=False): - Stationary ufuns always cache results - Volatile ufuns never cache results - Ufuns with both STABLE_MIN and STABLE_MAX cache results - If outcome_space/issues/outcomes are provided (different from ufun’s), caching is skipped

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.UtilityFunctionAdapter(ufun: BaseUtilityFunction, *, name: str | None = None, outcome_space: OutcomeSpace | None = None, reserved_value: float | None = None, stability: Stability | int | None = None, **kwargs)[source]

Bases: BaseUtilityFunction

Base class for utility function adapters that wrap a single utility function.

This class provides a foundation for creating utility functions that wrap and transform another utility function. It automatically inherits: - Stability from the inner ufun (ANDed with any additional stability) - Outcome space from the inner ufun (if not explicitly provided) - Reserved value from the inner ufun (if not explicitly provided)

Subclasses should override eval() to implement their transformation logic.

ufun[source]

The wrapped utility function.

Example

>>> from negmas.preferences import LinearUtilityFunction
>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(5), make_issue(3)]
>>> base_ufun = LinearUtilityFunction.random(issues=issues)
>>> adapter = UtilityFunctionAdapter(ufun=base_ufun)
>>> adapter.stability == base_ufun.stability
True
eval(offer: tuple) Distribution | float[source]

Evaluate the utility of an offer.

Default implementation delegates to the inner ufun. Subclasses should override this to implement their transformation.

Parameters:

offer – The outcome to evaluate.

Returns:

The utility value.

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

Deserialize from dictionary.

Parameters:
  • d – Dictionary representation.

  • python_class_identifier – Key for class type.

Returns:

New instance.

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

Serialize to dictionary.

Parameters:

python_class_identifier – Key for storing class type.

Returns:

Dictionary representation.

to_stationary() UtilityFunctionAdapter[source]

Returns a stationary version of this adapter.

Creates a new adapter wrapping the stationary version of the inner ufun.

property ufun: BaseUtilityFunction[source]

The wrapped utility function.

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

Bases: object

Indicates that the ufun is volatile.

Deprecated since version Use: stability=VOLATILE parameter instead::

# Old way (deprecated): class MyUfun(VolatileUFunMixin, BaseUtilityFunction):

pass

# New way: ufun = MyUtilityFunction(…, stability=VOLATILE)

This mixin sets stability to VOLATILE (no stability guarantees). The preferred approach is to pass stability=VOLATILE to the constructor.

is_volatile()[source]

Check if volatile.

class negmas.preferences.WeightedUtilityFunction(ufuns: Iterable[BaseUtilityFunction], weights: Iterable[float] | None = None, **kwargs)[source]

Bases: BaseUtilityFunction

A utility function composed of linear aggregation of other utility functions.

This combines multiple utility functions using weighted sum:

u(o) = sum(w_i * u_i(o))

where w_i are the weights and u_i are the component utility functions.

Stability Properties:
  • Inherits stability by ANDing all component ufuns’ stability

  • Additionally preserves STABLE_ORDERING and STABLE_DIFF_RATIOS (weighted sum preserves relative ordering and ratios)

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

Example

>>> from negmas.preferences import LinearUtilityFunction
>>> from negmas.outcomes import make_issue
>>> issues = [make_issue(5)]
>>> u1 = LinearUtilityFunction(weights=[1.0], issues=issues)
>>> u2 = LinearUtilityFunction(weights=[0.5], issues=issues)
>>> combined = WeightedUtilityFunction(ufuns=[u1, u2], weights=[0.6, 0.4])
>>> combined.is_stationary()
True
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]

Import a utility function from a GENIUS XML file.

Parameters:
  • issues – The list of issues defining the negotiation domain.

  • file_name – Path to the GENIUS XML file.

  • **kwargs – Additional keyword arguments passed to the parser.

Returns:

A utility function object parsed from the file.

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]

Generate the XML representation of this utility function.

Parameters:

issues – The list of issues defining the negotiation domain.

Returns:

A string containing the XML representation compatible with GENIUS.

negmas.preferences.calc_full_metrics(trace_utils: Sequence[tuple[float, ...]], agreement_utils: Sequence[float] | None, reserved_values: Sequence[float], *, utility_ranges: Sequence[tuple[float, float]] | None = None, relative_time: float = 0.0, last_step: int = 0, trace_parties: Sequence[int] | None = None, first_offer_party: int = 0, trace_offers: Sequence[Outcome | None] | None = None, outcome_space: OutcomeSpace | None = None, ufuns: Sequence[BaseUtilityFunction] | None = None, opponent_ufuns: Sequence[BaseUtilityFunction | None] | None = None, pareto_utils: Sequence[tuple[float, ...]] | None = None, stats: ScenarioStats | None = None, max_dist: float | None = None, eps: float = 1e-09) FullMetrics[source]

Calculate the FullMetrics of a single negotiation.

Bundles three views of one negotiation:

Parameters:
  • trace_utils – One tuple per offer in the trace, in trace order, each holding every negotiator’s utility for that offer. Empty when no trace is available (all trace-based per-negotiator metrics become nan).

  • agreement_utils – Per-negotiator utilities at the agreement, or None when no agreement was reached.

  • reserved_values – Per-negotiator reservation values (already corrected to finite values). Its length defines the number of negotiators.

  • utility_ranges – Optional per-negotiator (min, max) achievable utility (for scale-free advantage/inequality metrics).

  • relative_time – The mechanism’s relative time at the end, in [0, 1].

  • last_step – The final round index actually reached.

  • trace_parties – Optional party index per trace entry (offer attribution). When omitted, round-robin attribution from first_offer_party is used.

  • first_offer_party – The party that made the first offer (attribution fallback).

  • trace_offers – Optional outcomes aligned with trace_utils (for valid_offer_fraction).

  • outcome_space – Optional outcome space (for valid_offer_fraction and opponent-model comparison).

  • ufuns – The true per-negotiator utility functions (for the optimality max_dist estimate and the opponent-model comparison).

  • opponent_ufuns – Optional per-negotiator opponent-utility estimates (opponent_ufuns[i] is the model exposed by negotiator i); drives the opp_* metrics.

  • pareto_utils – Optional Pareto-frontier utility tuples (for surplus_efficiency). When omitted, stats.pareto_utils is used if stats is supplied.

  • stats – Optional pre-computed ScenarioStats. When supplied with an agreement, the optimality block is populated.

  • max_dist – Optional maximum utility-space distance for the optimality normalisation. When omitted, estimate_max_dist() is used on ufuns (so ufuns is required to populate optimality without an explicit max_dist).

  • eps – Numerical tolerance forwarded to calc_negotiator_metrics().

Returns:

A FullMetrics with optimality, session and one negotiators entry per party.

negmas.preferences.calc_negotiator_metrics(trace_utils: Sequence[tuple[float, ...]], agreement_utils: Sequence[float] | None, reserved_values: Sequence[float], *, index: int = 0, utility_ranges: Sequence[tuple[float, float]] | None = None, trace_parties: Sequence[int] | None = None, first_offer_party: int = 0, trace_offers: Sequence[Outcome | None] | None = None, outcome_space: OutcomeSpace | None = None, opponent_ufun: BaseUtilityFunction | None = None, ufuns: Sequence[BaseUtilityFunction] | None = None, eps: float = 1e-09) NegotiatorMetrics[source]

Calculate the per-negotiator NegotiatorMetrics for index.

Computes every field of NegotiatorMetrics from the utilities of all parties to all offers in the trace and the agreement utilities, plus the per-party reservation values. Only quantities that depend on which negotiator is being scored are computed here; negotiator-independent quantities live in SessionMetrics / calc_session_metrics().

Parameters:
  • trace_utils – One tuple per offer in the trace, in trace order, each holding every negotiator’s utility for that offer (trace_utils[t][j] = utility of negotiator j for offer t). Empty when no trace is available (all trace-based metrics then become nan).

  • agreement_utils – Per-negotiator utilities at the agreement, or None when no agreement was reached (realised utility then falls back to reserved_values for every party).

  • reserved_values – Per-negotiator reservation values (already corrected to finite values).

  • index – The negotiator (in the order used by trace_utils / agreement_utils / reserved_values) to score.

  • utility_ranges – Optional per-negotiator (min, max) achievable utility, used for the scale-free advantage / opponent_advantage / dominance. When omitted, advantage falls back to the raw surplus u - r.

  • trace_parties – Optional party index per trace entry (length must match trace_utils). When omitted, offers are attributed round-robin: offer t is made by party (first_offer_party + t) % n_negotiators (the standard alternating-offer / SAO convention).

  • first_offer_party – The party that made the first offer, for the round-robin attribution fallback (default 0).

  • trace_offers – Optional outcomes aligned with trace_utils, used with outcome_space to compute valid_offer_fraction. Without these, valid_offer_fraction is nan.

  • outcome_space – Optional outcome space for valid_offer_fraction and the opponent-model comparison.

  • opponent_ufun – Optional opponent-utility estimate exposed by negotiator index; when given with ufuns and outcome_space, the opp_* opponent-model accuracy metrics are computed.

  • ufuns – The true per-negotiator utility functions, used for the opponent-model comparison.

  • eps – Numerical tolerance for temporal_patience and the coupling_ratio zero-guard.

Returns:

A populated NegotiatorMetrics for party index. Metrics whose required inputs were not supplied are left as nan rather than fabricated.

Remarks:
  • Metrics that require the outcomes themselves (valid_offer_fraction) or the negotiator’s opponent model (opp_*) cannot be derived from utilities alone; pass trace_offers/outcome_space and opponent_ufun/ufuns respectively to populate them, otherwise they are nan.

  • No metric clips a paper-defined ratio that may legitimately exceed 1 or go negative; only a genuinely undefined quotient (zero/nan denominator) becomes nan.

negmas.preferences.calc_outcome_distances(utils: tuple[float, ...], stats: ScenarioStats) OutcomeDistances[source]

Calculates distances from an outcome’s utilities to various solution concept points.

Parameters:
  • utils – Utility values for an outcome (one per negotiator).

  • stats – Pre-computed scenario statistics containing solution concept points. The stats.convex_hull flag selects the evaluation model: when True the Pareto distance is measured to the continuous P∞ (convex-hull) frontier via dist_to_convex_hull_frontier (which includes mixture-only points between frontier vertices) for two-negotiator scenarios; for more than two negotiators it falls back to the discrete distance to the P∞ vertices, since dist_to_convex_hull_frontier is only implemented for two objectives. Distances to Nash/Kalai/KS use the (single) mixture point stored in stats and are mode-agnostic.

Returns:

Distances to Pareto frontier, Nash, Kalai, and other solution points.

negmas.preferences.calc_outcome_optimality(dists: OutcomeDistances, stats: ScenarioStats, max_dist: float) OutcomeOptimality[source]

Converts outcome distances to normalized optimality scores (0-1).

Parameters:
  • dists – Pre-computed distances to solution concept points.

  • stats – Scenario statistics for reference.

  • max_dist – Maximum possible distance for normalization.

Returns:

Optimality scores where 1.0 means at the optimal point.

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, convex_hull: bool = False) ScenarioStats[source]

Computes comprehensive statistics for a negotiation scenario.

Calculates Pareto frontier, Nash points, Kalai points, welfare points, and other solution concepts.

Parameters:
  • ufuns – Utility functions for all negotiators (must share the same outcome space).

  • outcomes – Outcomes to consider. If None, enumerated from the outcome space.

  • eps – Tolerance for floating-point comparisons in solution concept calculations.

  • convex_hull – If True, compute under the P∞ (convex-hull / multiple-negotiations) evaluation model of pareto_frontier_convex_hull: the Pareto frontier is the mixture-undominated subset of the convex hull, and the Nash/Kalai/KS solutions are mixtures over hull vertices (returned as a single utility point with empty *_outcomes). If False (default), the ordinary single-negotiation P model is used. The chosen mode is recorded on the returned ScenarioStats so downstream calc_outcome_distances/calc_outcome_optimality honor it.

Returns:

ScenarioStats containing all computed solution concepts and metrics.

negmas.preferences.calc_session_metrics(agreement_utils: Sequence[float] | None, reserved_values: Sequence[float], *, utility_ranges: Sequence[tuple[float, float]] | None = None, relative_time: float = 0.0, last_step: int = 0, pareto_utils: Sequence[tuple[float, ...]] | None = None) SessionMetrics[source]

Calculate the negotiator-independent SessionMetrics.

Computes every field of SessionMetrics from the realised utilities of all parties (the agreement utilities, or the reservation values when no agreement was reached) plus the per-party reservation values and the mechanism timing. No offer trace is required: every session metric is a property of the outcome and the timing, not of any single negotiator (those live in NegotiatorMetrics).

Parameters:
  • agreement_utils – Per-negotiator utilities at the agreement, or None when no agreement was reached (the realised utility then falls back to reserved_values for every party).

  • reserved_values – Per-negotiator reservation values (already corrected to finite values).

  • utility_ranges – Optional per-negotiator (min, max) achievable utility, used for the scale-free advantage_gap. When omitted, the raw-surplus u - r is used for each party instead.

  • relative_time – The mechanism’s relative time at the end, in [0, 1] (drives relative_rounds / agreement_speed).

  • last_step – The final round index actually reached (drives relative_efficiency).

  • pareto_utils – Optional Pareto-frontier utility tuples, used to normalise surplus_efficiency. When omitted, the utility ranges are used as the denominator fallback; when neither is given surplus_efficiency is nan.

Returns:

A populated SessionMetrics. Metrics whose required inputs were not supplied are left as nan rather than fabricated.

Remarks:
  • No metric clips a paper-defined ratio that may legitimately exceed 1 or go negative; only a genuinely undefined quotient (zero/nan denominator) becomes nan.

negmas.preferences.calc_standard_info(ufuns: tuple[UtilityFunction, ...] | list[UtilityFunction], outcome_space: OutcomeSpace | None = None, outcomes: Sequence[Outcome] | None = None, calc_rational: bool = True) dict[str, Any][source]

Computes standard scenario information metrics.

Calculates basic statistics about a negotiation scenario including: - Number of negotiators - Number of outcomes - Number of issues - Rational fraction (fraction of outcomes with positive utility for all parties) - Opposition level (conflict measure between negotiators)

Parameters:
  • ufuns – Utility functions for all negotiators (must share the same outcome space).

  • outcome_space – The outcome space. If None, inferred from first ufun.

  • outcomes – Outcomes to consider. If None, enumerated from the outcome space.

  • calc_rational – Whether to calculate the rational fraction metric.

Returns:

n_negotiators, n_outcomes, n_issues, rational_fraction, opposition_level

Return type:

Dictionary containing

Examples

>>> from negmas import make_issue, make_os
>>> from negmas.preferences import LinearUtilityFunction
>>> from negmas.preferences.ops import calc_standard_info
>>> issues = [make_issue([0, 1, 2], "x")]
>>> os = make_os(issues)
>>> u1 = LinearUtilityFunction(weights=[1.0], issues=issues)
>>> u2 = LinearUtilityFunction(weights=[0.5], issues=issues)
>>> info = calc_standard_info([u1, u2], outcome_space=os)
>>> info["n_negotiators"]
2
>>> info["n_outcomes"]
3
>>> info["n_issues"]
1
negmas.preferences.compare_ufuns(ufun1: BaseUtilityFunction | None, ufun2: BaseUtilityFunction | None, method: COMPARE_UFUN_METHOD_TYPE = 'kendall', normalize: bool = True, max_samples: int = 100000, outcome_space: OutcomeSpace | None = None, issues: Sequence[Issue] | None = None, outcomes: Sequence[Outcome] | None = None) float[source]

Compare two utility functions using various distance metrics.

This function compares utility functions by sampling outcomes and computing a distance metric between the utility vectors.

Parameters:
  • ufun1 – First utility function to compare

  • ufun2 – Second utility function to compare

  • method – Comparison method to use. Options are: - “kendall”: Kendall’s tau rank correlation coefficient (default) - “kendall_optimality”: half of (Kendall’s tau + 1) which makes it between 0 and 1 - “ndcg”: Normalized Discounted Cumulative Gain score (beteween 0 and 1) - “euclidean”: Normalized Euclidean distance (between 0 and 1) - callable: Custom function taking two vectors and returning a float

  • normalize – If True, normalize both utility functions to [0, 1] range independently before comparison. Default is True.

  • max_samples – Maximum number of outcomes to sample. If the outcome space is smaller, all outcomes will be used. Default is 100,000.

  • outcome_space – The outcome space to sample from

  • issues – Issues to define the outcome space (alternative to outcome_space)

  • outcomes – Explicit list of outcomes to use (alternative to outcome_space)

Returns:

Distance measure between the utility functions. The interpretation

depends on the method: - kendall: Value in [-1, 1], where 1 means perfect agreement,

-1 means perfect disagreement, 0 means no correlation

  • kendall_optimality: Value in [0, 1], where 1 means perfect agreement, 0 means perfect disagreement (= (kendall + 1) / 2)

  • ndcg: Value in [0, 1], where 1 means perfect agreement

  • euclidean: Normalized distance in [0, 1], where 0 means identical, 1 means maximally different

  • callable: Whatever the custom function returns

Return type:

float

Examples

>>> from negmas import make_issue
>>> from negmas.preferences import LinearAdditiveUtilityFunction
>>> issues = [make_issue([1, 2, 3], "price")]
>>> ufun1 = LinearAdditiveUtilityFunction({"price": lambda x: x}, issues=issues)
>>> ufun2 = LinearAdditiveUtilityFunction(
...     {"price": lambda x: -x}, issues=issues
... )
>>> # Kendall correlation (perfect negative correlation)
>>> compare_ufuns(ufun1, ufun2, method="kendall", issues=issues)
-1.0
>>> # Identical ufuns
>>> compare_ufuns(ufun1, ufun1, method="kendall", issues=issues)
1.0
>>> # Kendall optimality (perfect negative correlation)
>>> compare_ufuns(ufun1, ufun2, method="kendall_optimality", issues=issues)
0.0
>>> # Identical ufuns
>>> compare_ufuns(ufun1, ufun1, method="kendall_optimality", issues=issues)
1.0

Notes

  • Utility values are cast to float for comparison

  • When normalize=True, each utility function is normalized independently to [0, 1], guaranteeing that max and min values are respected

  • For euclidean distance, the result is normalized relative to the distance between the first vector and its negation

  • NDCG requires utilities to be non-negative; negative utilities are shifted to start from 0

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.correct_reserved_value(reserved_value: float | None, ufun: BaseUtilityFunction, eps: float | None = None, *, warn: bool = True) tuple[float, bool][source]

Corrects non-finite reserved values to a finite value.

Parameters:
  • reserved_value – The reserved value to check and potentially correct

  • ufun – The utility function whose min() will be used for correction

  • eps – The penalty to subtract from ufun.min(). If None, uses DEFAULT_RESERVED_VALUE_PENALTY

  • warn – Whether to emit a warning when correction is performed

Returns:

  • corrected_value: The corrected reserved value (finite)

  • was_corrected: True if correction was performed, False otherwise

Return type:

A tuple of (corrected_value, was_corrected) where

Examples

>>> from negmas.preferences.crisp.mapping import MappingUtilityFunction
>>> from negmas.outcomes import make_issue, make_os
>>> issues = [make_issue([0, 1, 2], "x")]
>>> os = make_os(issues)
>>> ufun = MappingUtilityFunction(
...     lambda x: x[0], outcome_space=os, reserved_value=0.5
... )
>>> # Normal value - no correction needed
>>> val, corrected = correct_reserved_value(0.5, ufun)
>>> val == 0.5 and not corrected
True
>>> # None value - needs correction
>>> val, corrected = correct_reserved_value(None, ufun, eps=0.0, warn=False)
>>> corrected and val == ufun.min()
True
>>> # Inf value - needs correction with custom epsilon
>>> val, corrected = correct_reserved_value(
...     float("inf"), ufun, eps=0.1, warn=False
... )
>>> corrected and abs(val - (ufun.min() - 0.1)) < 1e-10
True
>>> # None value - needs correction
>>> val, corrected = correct_reserved_value(None, ufun, eps=0.0, warn=False)
>>> corrected and val == ufun.min()
True
>>> # Inf value - needs correction with custom epsilon
>>> val, corrected = correct_reserved_value(
...     float("inf"), ufun, eps=0.1, warn=False
... )
>>> corrected and abs(val - (ufun.min() - 0.1)) < 1e-10
True
>>> # None value - needs correction
>>> val, corrected = correct_reserved_value(None, ufun, eps=0.0, warn=False)
>>> corrected and val == ufun.min()
True
>>> # Inf value - needs correction with custom epsilon
>>> val, corrected = correct_reserved_value(
...     float("inf"), ufun, eps=0.1, warn=False
... )
>>> corrected and abs(val - (ufun.min() - 0.1)) < 1e-10
True
>>> # None value - needs correction
>>> val, corrected = correct_reserved_value(None, ufun, eps=0.0, warn=False)
>>> corrected and val == ufun.min()
True
>>> # Inf value - needs correction with custom epsilon
>>> val, corrected = correct_reserved_value(
...     float("inf"), ufun, eps=0.1, warn=False
... )
>>> corrected and abs(val - (ufun.min() - 0.1)) < 1e-10
True
>>> # None value - needs correction
>>> val, corrected = correct_reserved_value(None, ufun, eps=0.0, warn=False)
>>> corrected and val == ufun.min()
True
>>> # Inf value - needs correction
>>> val, corrected = correct_reserved_value(
...     float("inf"), ufun, eps=0.1, warn=False
... )
>>> corrected and val == ufun.min() - 0.1
True
>>> # None value - needs correction
>>> val, corrected = correct_reserved_value(None, ufun, eps=0.0, warn=False)
>>> corrected and val == ufun.min()
True
>>> # Inf value - needs correction
>>> val, corrected = correct_reserved_value(
...     float("inf"), ufun, eps=0.1, warn=False
... )
>>> corrected and val == ufun.min() - 0.1
True
Remarks:
  • Reserved values that are None, inf, -inf, or NaN are considered non-finite

  • The corrected value is computed as float(ufun.min()) - eps

  • If eps is None, DEFAULT_RESERVED_VALUE_PENALTY from negmas.common is used

  • A NegmasUnexpectedValueWarning is emitted when correction occurs (if warn=True)

negmas.preferences.distance_between(w: tuple[float, ...], n: tuple[float, ...]) float[source]

Computes Euclidean distance between two utility tuples.

negmas.preferences.distance_to(w: tuple[float, ...], p: Iterable[tuple[float, ...]]) float[source]

Computes minimum Euclidean distance from a point to a set of points.

negmas.preferences.dominating_points(utils: NDArray[floating[Any]] | tuple[float, ...], points: NDArray[floating[Any]] | tuple[tuple[float, ...]]) NDArray[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]

Computes ordinal ranks of outcomes based on utility values.

Parameters:
  • ufun – The utility function to use for ranking.

  • outcomes – Outcomes to rank. If empty, uses all outcomes from the ufun’s outcome space.

  • normalize – If True, normalize ranks to [0, 1] range.

Returns:

Array of ranks (higher rank = higher utility). Includes rank for None (disagreement).

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]

Wraps a utility function with time-based discounting.

Applies linear or exponential discounting based on negotiation rounds, relative time, or real time elapsed.

Parameters:
  • ufun – The base utility function to wrap.

  • cost_per_round – Linear cost subtracted per negotiation round.

  • power_per_round – Exponent for the round-based linear discount.

  • discount_per_round – Exponential discount factor per round (0-1).

  • cost_per_relative_time – Linear cost subtracted per unit of relative time.

  • power_per_relative_time – Exponent for the relative-time-based linear discount.

  • discount_per_relative_time – Exponential discount factor per relative time unit.

  • cost_per_real_time – Linear cost subtracted per second of real time.

  • power_per_real_time – Exponent for the real-time-based linear discount.

  • discount_per_real_time – Exponential discount factor per second of real time.

  • dynamic_reservation – Whether to dynamically adjust the reserved value over time.

Returns:

The original ufun if no discounting is specified, otherwise a discounted wrapper.

negmas.preferences.make_fun_from_xml(item) tuple[BaseFun, str][source]

Parse a GENIUS XML evaluator element and return the corresponding value function.

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, normalize_reserved_values: bool = False, reserved_value_penalty: float | 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]

  • outcome_space – The outcome space to normalize over

  • issues – Issues defining the outcome space (alternative to outcome_space)

  • outcomes – Specific outcomes to normalize over (alternative to outcome_space)

  • normalize_reserved_values – If True, corrects non-finite reserved values (None, inf, -inf, NaN)

  • reserved_value_penalty – Penalty to use when correcting reserved values. If None, uses DEFAULT_RESERVED_VALUE_PENALTY

Returns:

A utility function that is guaranteed to be normalized for the set of given outcomes

Return type:

UtilityFunction

Remarks:
  • If normalize_reserved_values is True, any non-finite reserved value will be corrected to ufun.min() - penalty

  • The correction happens before normalization

negmas.preferences.opposition_level(ufuns: Sequence[UtilityFunction], max_utils: float | tuple[float | int, ...] | list[float | int] = 1.0, outcomes: int | Sequence[Outcome] | None = None, outcome_space: OutcomeSpace | 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.

  • outcome_space – The outcome space to use for extracting issues (only used if outcomes and issues are None).

  • 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

Remarks:
  • n_discretization is applied per continuous issue only; a fully-finite outcome space is enumerated exactly and is never affected by it.

  • Outcomes whose utility is non-finite (or raises) for any ufun are skipped, so opponent-model stand-ins can be passed safely.

  • This end-to-end path (ufuns + issues → frontier) is faster than manually enumerating the outcomes and calling pareto_frontier_numpy yourself: ~1.5–2x on discrete spaces and ~100x on continuous spaces. Prefer it when you start from ufuns rather than pre-evaluated points.

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

Remarks:
  • Recommended exact frontier extractor. Vectorized: ~0.0003 s on ~500 two-objective points (~200x faster than pareto_frontier_bf, which gives the identical result). Prefer this whenever you already have the utility points.

negmas.preferences.pareto_frontier_bf(points: ndarray | Iterable[Iterable[float]], eps=-1e-12, sort_by_welfare=True) ndarray[source]

Finds the Pareto frontier using brute-force pairwise comparison.

Parameters:
  • points – Array of utility tuples, one per outcome.

  • eps – Tolerance for dominance comparisons (usually negative).

  • sort_by_welfare – If True, sort results by descending total welfare.

Returns:

Indices of Pareto-optimal points.

Remarks:
  • Exact, but O(n²) pairwise comparison: ~0.06 s on ~500 points (~200x slower than pareto_frontier_numpy, which returns the identical frontier). Only competitive for a few dozen points; prefer pareto_frontier_numpy otherwise.

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:

indices of Pareto optimal outcomes

Warning

  • Effectively unusable — do not use. Despite the “fast algorithm” claim, this does not complete in practical time on more than ~100 points (it hangs). Use pareto_frontier_numpy instead.

negmas.preferences.rational_fraction(ufuns: Sequence[UtilityFunction], outcomes: Sequence[Outcome] | None = None, outcome_space: OutcomeSpace | None = None) float[source]

Calculates the fraction of outcomes that are rational for ALL negotiators.

An outcome is considered rational if all negotiators receive utility strictly greater than their reserved value for that outcome.

Parameters:
  • ufuns – Utility functions for all negotiators.

  • outcomes – Outcomes to consider. If None, enumerated from outcome_space.

  • outcome_space – The outcome space. If None, inferred from first ufun.

Returns:

Float between 0.0 and 1.0 representing the rational fraction.

Raises:

ValueError – If ufuns is empty or if outcome_space cannot be determined.

Examples

>>> from negmas import make_issue, make_os
>>> from negmas.preferences import LinearUtilityFunction
>>> from negmas.preferences.ops import rational_fraction
>>> issues = [make_issue([0, 1, 2], "x")]
>>> os = make_os(issues)
>>> u1 = LinearUtilityFunction(weights=[1.0], issues=issues, reserved_value=0.5)
>>> u2 = LinearUtilityFunction(weights=[0.5], issues=issues, reserved_value=0.3)
>>> frac = rational_fraction([u1, u2], outcome_space=os)
>>> 0.0 <= frac <= 1.0
True
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[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[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)))
... )