Skip to content

tucoopy.geometry.imputation_set

Imputation and pre-imputation sets.

This module provides polyhedral representations of:

  • the pre-imputation set (efficiency only), and
  • the imputation set (efficiency + individual rationality).

The imputation set is an intersection of an affine hyperplane with box constraints, and is therefore polyhedral.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).contains([0.5, 0.5])
True

ImputationProjection dataclass

Output of project_to_imputation.

Attributes:

Name Type Description
x list[float]

Projected allocation (same dimension as the input vector).

feasible bool

False if the imputation set is empty, i.e.

$$ \sum_{i=1}^n v({i}) > v(N).

$$

In this case, x is returned unchanged (a copy of the input).

Examples:

>>> p = ImputationProjection(x=[0.5, 0.5], feasible=True)
>>> p.feasible
True

ImputationSet dataclass

Imputation set wrapper (efficiency + individual rationality).

This wrapper exposes both polyhedral operations and diagnostics specialized for imputation membership.

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required

Examples:

::

>>> class _G:
...     n_players = 2
...     grand_coalition = 3
...     def value(self, S: int) -> float:
...         return {1: 1.0, 2: 2.0, 3: 5.0}.get(S, 0.0)
...
>>> I = ImputationSet(_G())
>>> I.contains([1.0, 4.0])
True
>>> I.explain([0.5, 4.5])[0].startswith("Violates")
True

poly property

poly

Underlying polyhedral representation (efficiency + IR bounds).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).poly.n_vars
2

chebyshev_center

chebyshev_center()

Compute the Chebyshev center (if supported by the backend).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).chebyshev_center()
([0.5, 0.5], 0.0)

check

check(x, *, tol=DEFAULT_GEOMETRY_TOL)

Compute imputation-set diagnostics for \(x\).

Delegates to tucoopy.diagnostics.imputation_diagnostics.imputation_diagnostics.

Parameters:

Name Type Description Default
x list[float]

Allocation vector.

required
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL

Returns:

Type Description
Any

Diagnostics object with fields such as in_set, efficient, sum_x, vN and potential IR violations.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).check([0.5, 0.5]).in_set
True

contains

contains(x, *, tol=DEFAULT_GEOMETRY_TOL)

Test membership via the polyhedral representation.

Parameters:

Name Type Description Default
x list[float]

Allocation vector.

required
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL

Returns:

Type Description
bool

True if x is in the imputation set.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).contains([0.5, 0.5])
True

explain

explain(x, *, tol=DEFAULT_GEOMETRY_TOL)

Produce a short human-readable explanation of membership.

Parameters:

Name Type Description Default
x list[float]

Allocation vector.

required
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL

Returns:

Type Description
list[str]

A list of message lines. Empty list is avoided; when x is in the set, a single affirmative line is returned.

Examples:

::

>>> class _G:
...     n_players = 2
...     grand_coalition = 3
...     def value(self, S: int) -> float:
...         return {1: 1.0, 2: 2.0, 3: 5.0}.get(S, 0.0)
...
>>> ImputationSet(_G()).explain([1.0, 4.0])
['In the imputation set.']

extreme_points

extreme_points(
    *,
    tol=DEFAULT_GEOMETRY_TOL,
    max_dim=DEFAULT_GEOMETRY_MAX_DIM,
)

Enumerate extreme points (when representable).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).extreme_points(max_dim=2)
[[0.0, 1.0], [1.0, 0.0]]

is_empty

is_empty()

Return whether the imputation set is empty.

Notes

The imputation set is empty iff

\[ \sum_{i=1}^n v(\{i\}) > v(N). \]

(subject to numerical tolerance inside the polyhedral backend).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).is_empty()
False

project

project(
    dims,
    *,
    tol=DEFAULT_GEOMETRY_TOL,
    max_dim=DEFAULT_GEOMETRY_MAX_DIM,
)

Project the set onto selected coordinates (returns projected vertices when representable).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).project((0,), max_dim=2)
[[0.0], [1.0]]

sample_point

sample_point()

Try to sample one point from the imputation set.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import ImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> ImputationSet(g).sample_point()
[0.5, 0.5]

vertices

vertices(
    *,
    tol=DEFAULT_IMPUTATION_SAMPLE_TOL,
    max_players=DEFAULT_GEOMETRY_MAX_PLAYERS,
    max_dim=DEFAULT_GEOMETRY_MAX_DIM,
)

Return the vertices of the imputation set (closed form).

The imputation set is a shifted simplex:

\[ \left\{ x : \sum_{i=1}^n x_i = v(N),\ x_i \ge v(\{i\}) \right\}. \]

Let

\[ l_i = v(\{i\}), \qquad r = v(N) - \sum_{i=1}^n l_i. \]
  • If \(r > 0\), the vertices are \(l + r e_i\) for \(i=0,\ldots,n-1\).
  • If \(r = 0\), the set is the single point \(l\).
  • If \(r < 0\), the set is empty.

Parameters:

Name Type Description Default
tol float

Tolerance used to decide whether r is negative/zero.

DEFAULT_IMPUTATION_SAMPLE_TOL
max_players int

Guardrail: this closed-form enumeration is intended for small n.

DEFAULT_GEOMETRY_MAX_PLAYERS
max_dim int

Present for API consistency with other geometric sets; not used here.

DEFAULT_GEOMETRY_MAX_DIM

Returns:

Type Description
list[list[float]]

Vertices of the imputation set, or [] if empty.

Examples:

3 players, singleton values (1,2,0) and v(N)=10 => r=7, vertices are l+7e_i::

>>> class _G:
...     n_players = 3
...     grand_coalition = 7
...     def value(self, S: int) -> float:
...         return {1: 1.0, 2: 2.0, 4: 0.0, 7: 10.0}.get(S, 0.0)
...
>>> I = ImputationSet(_G())
>>> I.vertices()
[[8.0, 2.0, 0.0], [1.0, 9.0, 0.0], [1.0, 2.0, 7.0]]

PreImputationSet dataclass

Pre-imputation set wrapper.

This is a convenience wrapper around preimputation_polyhedron exposing common geometric operations.

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required

Examples:

::

>>> class _G:
...     n_players = 3
...     grand_coalition = 7
...     def value(self, S: int) -> float:
...         return 10.0 if S == 7 else 0.0
...
>>> P = PreImputationSet(_G())
>>> P.contains([1.0, 2.0, 7.0])
True

poly property

poly

Underlying polyhedral representation (efficiency only).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).poly.n_vars
2

chebyshev_center

chebyshev_center()

Compute the Chebyshev center (if defined by the backend).

Returns:

Type Description
(center, radius) or None

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).chebyshev_center()
([0.5, 0.5], 0.0)

check

check(x, *, tol=DEFAULT_GEOMETRY_TOL)

Run allocation diagnostics for \(x\).

This is a convenience hook that delegates to tucoopy.diagnostics.checks.check_allocation.

Parameters:

Name Type Description Default
x list[float]

Allocation vector.

required
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL

Returns:

Type Description
Any

The diagnostics object returned by check_allocation.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).check([0.5, 0.5]).efficient
True

contains

contains(x, *, tol=DEFAULT_GEOMETRY_TOL)

Test membership in the pre-imputation set.

Parameters:

Name Type Description Default
x list[float]

Allocation vector.

required
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL

Returns:

Type Description
bool

True if sum(x) = v(N) within tolerance.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).contains([0.25, 0.75])
True

extreme_points

extreme_points(
    *,
    tol=DEFAULT_GEOMETRY_TOL,
    max_dim=DEFAULT_GEOMETRY_MAX_DIM,
)

Enumerate extreme points (when the set is bounded in the projected space).

Parameters:

Name Type Description Default
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL
max_dim int

Maximum dimension for vertex enumeration (backend-dependent safeguard).

DEFAULT_GEOMETRY_MAX_DIM

Returns:

Type Description
list[list[float]]

List of vertices/extreme points.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).extreme_points(max_dim=2)
[]

is_empty

is_empty()

Return whether the pre-imputation set is empty.

Notes

For standard TU games, \(\sum_{i=1}^n x_i = v(N)\)$ with free bounds is non-empty. Emptiness can occur only if the underlying polyhedral machinery considers the constraint system infeasible (e.g. NaNs).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).is_empty()
False

project

project(
    dims,
    *,
    tol=DEFAULT_GEOMETRY_TOL,
    max_dim=DEFAULT_GEOMETRY_MAX_DIM,
)

Project the set onto a subset of coordinates.

Parameters:

Name Type Description Default
dims tuple[int, ...] | list[int]

Indices of coordinates to keep (e.g. (0, 1)).

required
tol float

Numerical tolerance.

DEFAULT_GEOMETRY_TOL
max_dim int

Maximum dimension for vertex enumeration.

DEFAULT_GEOMETRY_MAX_DIM

Returns:

Type Description
list[list[float]]

Vertices of the projected polytope (when representable).

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).project((0,), max_dim=2)
[]

sample_point

sample_point()

Try to sample one point from the set.

Returns:

Type Description
list[float] | None

A feasible point, or None if sampling fails.

Examples:

>>> from tucoopy import Game
>>> from tucoopy.geometry import PreImputationSet
>>> g = Game.from_coalitions(n_players=2, values={0: 0, 3: 1})
>>> PreImputationSet(g).sample_point()
[0.5, 0.5]

imputation_lower_bounds

imputation_lower_bounds(game)

Compute the individual-rationality lower bounds for the imputation set.

In a TU cooperative game with characteristic function \(v\), the imputation set requires individual rationality:

\[ x_i \ge v(\{i\}), \quad i=1,\dots,n. \]

Define the lower bounds

\[ l_i := v(\{i\}). \]

This function returns the vector \(l = (l_1,\dots,l_n)\).

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required

Returns:

Type Description
list[float]

The lower bounds [l_0, ..., l_{n-1}] with l_i = v({i}).

Examples:

Minimal runnable example using a tiny dummy game (3 players)::

>>> class _G:
...     n_players = 3
...     grand_coalition = (1 << 3) - 1
...     def value(self, S: int) -> float:
...         # singleton values: v({0})=1, v({1})=2, v({2})=0.5
...         return {1: 1.0, 2: 2.0, 4: 0.5}.get(S, 0.0)
...
>>> imputation_lower_bounds(_G())
[1.0, 2.0, 0.5]
Notes
  • Coalitions are encoded as bitmasks: {i} is 1 << i.
  • The returned bounds are floats.

imputation_polyhedron

imputation_polyhedron(game)

Return the imputation set as a polyhedral set (H-representation).

The imputation set is the intersection of the efficiency hyperplane with the individual-rationality halfspaces:

\[ \left\{ x : \sum_{i=1}^n x_i = v(N),\ x_i \ge v(\{i\}) \right\}. \]

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required

Returns:

Type Description
PolyhedralSet

H-representation using a single equality constraint and per-player lower bounds.

Examples:

A 2-player game with v(N)=5 and singleton values (1,2)::

>>> class _G:
...     n_players = 2
...     grand_coalition = 3
...     def value(self, S: int) -> float:
...         return {1: 1.0, 2: 2.0, 3: 5.0}.get(S, 0.0)
...
>>> poly = imputation_polyhedron(_G())
>>> poly.contains([1.0, 4.0])
True
>>> poly.contains([0.5, 4.5])  # violates x0 >= 1
False

is_in_imputation_set

is_in_imputation_set(game, x, *, tol=DEFAULT_GEOMETRY_TOL)

Test whether an allocation belongs to the imputation set.

The imputation set for a TU game \(v\) is the set of allocations that are:

  • Efficient (feasible for the grand coalition):
\[ \sum_{i=1}^n x_i = v(N) \]
  • Individually rational:
\[ x_i \ge v(\{i\}), \quad i=1,\dots,n. \]

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required
x list[float]

Allocation vector (length n_players).

required
tol float

Numerical tolerance used in comparisons. Efficiency is checked with abs(sum(x) - v(N)) <= tol and individual rationality with x_i + tol >= v({i}).

DEFAULT_GEOMETRY_TOL

Returns:

Type Description
bool

True if x is efficient and individually rational; otherwise False.

Examples:

A 2-player dummy game where \(v(\{0\})=1\), \(v(\{1\})=2\), \(v(N)=5\)::

>>> class _G:
...     n_players = 2
...     grand_coalition = 3
...     def value(self, S: int) -> float:
...         return {1: 1.0, 2: 2.0, 3: 5.0}.get(S, 0.0)
...
>>> is_in_imputation_set(_G(), [1.0, 4.0])
True
>>> is_in_imputation_set(_G(), [0.9, 4.1])  # violates x0 >= 1
False
>>> is_in_imputation_set(_G(), [1.0, 3.9])  # not efficient (sum != 5)
False
Notes

This is a lightweight membership check. For richer diagnostics, use ImputationSet.check / ImputationSet.explain.

preimputation_polyhedron

preimputation_polyhedron(game)

Return the pre-imputation set as a polyhedral (affine) set.

The pre-imputation set consists of allocations that satisfy only efficiency:

\[ \sum_{i=1}^n x_i = v(N), \]

with no lower bounds \(x_i \ge v(\{i\})\).

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required

Returns:

Type Description
PolyhedralSet

H-representation of the affine set sum(x)=v(N) with free bounds.

Examples:

For a 3-player game with v(N)=10 , the set is the plane x0+x1+x_2=10::

>>> class _G:
...     n_players = 3
...     grand_coalition = 7
...     def value(self, S: int) -> float:
...         return 10.0 if S == 7 else 0.0
...
>>> poly = preimputation_polyhedron(_G())
>>> poly.contains([3.0, 3.0, 4.0])
True
>>> poly.contains([3.0, 3.0, 3.9])
False

project_to_imputation

project_to_imputation(
    game, x_hat, *, tol=DEFAULT_IMPUTATION_SAMPLE_TOL
)

Compute the Euclidean projection onto the imputation set.

The imputation set is

\[ \mathcal{I}(v) = \left\{ x : \sum_{i=1}^n x_i = v(N),\ x_i \ge v(\{i\}) \right\}. \]

This routine returns the closest point (in Euclidean norm) in $\mathcal{I}(v)to a given vector $\hat{x} \in \mathbb{R}^n.

Algorithm

Let l_i = v({i}) and r = v(N) - sum_i l_i.

  1. Shift: y = x_hat - l.
  2. Project y onto the simplex {z: z>=0, sum(z)=r}.
  3. Shift back: x = l + z.

Parameters:

Name Type Description Default
game GameProtocol

TU game.

required
x_hat list[float]

Arbitrary vector in $\mathbb{R}^n` (must have length n_players).

required
tol float

Numerical tolerance used to decide emptiness / degeneracy of the imputation set.

DEFAULT_IMPUTATION_SAMPLE_TOL

Returns:

Type Description
ImputationProjection

x is the projected allocation. If the imputation set is empty, returns feasible=False and x is a copy of x_hat.

Examples:

2 players, singleton bounds (1,2) and v(N)=5 => imputation is segment between (3,2) and (1,4). Projecting [10, -10] lands at the nearest endpoint::

>>> class _G:
...     n_players = 2
...     grand_coalition = 3
...     def value(self, S: int) -> float:
...         return {1: 1.0, 2: 2.0, 3: 5.0}.get(S, 0.0)
...
>>> proj = project_to_imputation(_G(), [10.0, -10.0])
>>> proj.feasible
True
>>> round(sum(proj.x), 10)
5.0
>>> proj.x[0] >= 1.0 and proj.x[1] >= 2.0
True

Empty imputation set example (sum singletons > v(N))::

>>> class _Bad:
...     n_players = 2
...     grand_coalition = 3
...     def value(self, S: int) -> float:
...         return {1: 5.0, 2: 5.0, 3: 3.0}.get(S, 0.0)
...
>>> proj = project_to_imputation(_Bad(), [0.0, 0.0])
>>> proj.feasible
False
Notes
  • This is a projection in \(\ell_2\). It does not guarantee any game-theoretic property beyond imputation feasibility.
  • If \(r\) is numerically zero, the imputation set collapses to the single point \(l\).