Utilities#

Simplex Utility Module#

This module provides utility functions for setting up and managing simplex domains in influencer games. It includes tools for creating simplex grids, converting between Cartesian and barycentric coordinates, and projecting points onto the simplex.

The module is designed to work with the InflGame.adaptive package and supports creating structured simplex environments for simulations involving agent dynamics and resource distributions.

Vectorized Functions:#

For improved performance with large datasets, this module provides vectorized versions of coordinate conversion functions:

  • xy2ba_vectorized : Convert multiple Cartesian coordinates to barycentric coordinates simultaneously

  • ba2xy_vectorized : Convert multiple barycentric coordinates to Cartesian coordinates simultaneously

  • projection_onto_simplex_vectorized : Project multiple points onto the simplex simultaneously

  • simplex_bin_setup_vectorized : Efficient vectorized bin setup for large simplex grids

The vectorized functions provide 5-10x performance improvements for large datasets while maintaining full numerical accuracy and comprehensive error handling.

Usage:#

The simplex_setup function can be used to create a simplex grid with specified refinement, while the xy2ba and ba2xy functions allow for conversions between Cartesian and barycentric coordinates.

Example:#

import numpy as np
import torch
from InflGame.domains.simplex.simplex_utils import simplex_setup, xy2ba, ba2xy
from InflGame.domains.simplex.simplex_utils import xy2ba_vectorized, ba2xy_vectorized

# Set up the simplex
r2, corners, triangle, trimesh = simplex_setup(refinement=4)

# Single point conversion (backward compatible)
x, y = 0.5, 0.3
barycentric_coords = xy2ba(x, y, corners)
print("Barycentric coordinates:", barycentric_coords)

# Multiple points conversion (vectorized, high performance)
x_coords = torch.tensor([0.1, 0.5, 0.8])
y_coords = torch.tensor([0.2, 0.3, 0.1])
barycentric_batch = xy2ba_vectorized(x_coords, y_coords, corners)
print("Vectorized barycentric shape:", barycentric_batch.shape)  # (3, 3)

# Convert back to Cartesian coordinates
cartesian_batch = ba2xy_vectorized(barycentric_batch, corners)
print("Vectorized Cartesian shape:", cartesian_batch.shape)  # (3, 2)

Functions

InflGame.domains.simplex.simplex_utils.ba2xy(x, corners)#

Converts barycentric coordinates to Cartesian coordinates.

Parameters:
  • x (torch.Tensor) – Array of barycentric coordinates.

  • corners (np.ndarray) – Coordinates of the simplex corners.

Returns:

Cartesian coordinates corresponding to the input barycentric coordinates.

Return type:

torch.Tensor

InflGame.domains.simplex.simplex_utils.ba2xy_vectorized(barycentric_coords, corners)#

Converts multiple barycentric coordinates to Cartesian coordinates using vectorized operations.

This function provides significant performance improvements over single-point conversions when processing large datasets of barycentric coordinate sets.

The Cartesian coordinates are computed using matrix multiplication:

\[\begin{split}\begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} x_1 & x_2 & x_3 \\ y_1 & y_2 & y_3 \end{bmatrix} \begin{bmatrix} \lambda_1 \\ \lambda_2 \\ \lambda_3 \end{bmatrix}\end{split}\]
Parameters:
barycentric_coordstorch.Tensor | np.ndarray

Barycentric coordinates, shape (N, 3) where each row contains [λ₁, λ₂, λ₃].

cornerstorch.Tensor | np.ndarray

Coordinates of the simplex corners, shape (3, 2).

Returns:
torch.Tensor

Cartesian coordinates of shape (N, 2) where each row contains [x, y].

Raises:
TypeError

If input types are not supported.

ValueError

If input dimensions are incompatible or coordinates are invalid.

RuntimeError

If computation fails due to numerical issues.

Examples

>>> import torch
>>> import numpy as np
>>> corners = np.array([[0, 0], [1, 0], [0.5, 0.866]])
>>> barycentric = torch.tensor([[0.33, 0.33, 0.34], [0.5, 0.3, 0.2]])
>>> cartesian = ba2xy_vectorized(barycentric, corners)
>>> print(cartesian.shape)
torch.Size([2, 2])
InflGame.domains.simplex.simplex_utils.projection_onto_simplex(Y)#

Projects a position vector onto the simplex.

Parameters:

Y (torch.Tensor) – Position vector to be projected.

Returns:

Position vector projected onto the simplex.

Return type:

torch.Tensor

InflGame.domains.simplex.simplex_utils.projection_onto_simplex_vectorized(Y)#

Projects multiple position vectors onto the simplex using vectorized operations.

This function efficiently projects multiple points onto the probability simplex (sum of coordinates equals 1, all coordinates non-negative) using the algorithm from Duchi et al. (2008).

The projection solves:

\[\text{minimize} \quad \|y - x\|_2^2 \quad \text{subject to} \quad x \geq 0, \sum_i x_i = 1\]
Parameters:
Ytorch.Tensor | np.ndarray

Position vectors to be projected, shape (N, D) where N is number of points and D is the dimension of the simplex.

Returns:
torch.Tensor

Position vectors projected onto the simplex, shape (N, D).

Raises:
TypeError

If input type is not supported.

ValueError

If input dimensions are invalid.

RuntimeError

If computation fails due to numerical issues.

Examples

>>> import torch
>>> points = torch.tensor([[1.5, -0.5, 0.2], [0.8, 0.3, 0.1]])
>>> projected = projection_onto_simplex_vectorized(points)
>>> print(torch.sum(projected, dim=1))  # Should be close to [1.0, 1.0]
tensor([1.0000, 1.0000])
InflGame.domains.simplex.simplex_utils.simplex_bin_setup(domain_bounds)#

Sets up bins on the simplex by projecting points onto the simplex and adjusting their positions.

Parameters:

domain_bounds (tuple) – A tuple containing domain information, including corners and triangular mesh.

Returns:

A tuple containing: - bin_points (np.ndarray): Points in barycentric coordinates adjusted to lie on the simplex. - bin_points_xy (np.ndarray): Points in Cartesian coordinates.

Return type:

tuple

InflGame.domains.simplex.simplex_utils.simplex_bin_setup_vectorized(domain_bounds, eps=0.001)#

Sets up bins on the simplex using vectorized operations for improved performance.

This function efficiently processes all bin points simultaneously, projecting them onto the simplex and adjusting boundary points to ensure they lie strictly within the simplex interior.

Parameters:
domain_boundstuple

A tuple containing domain information: (r2, corners, triangle, trimesh).

epsfloat, optional

Small value for boundary adjustments, by default 1e-3.

Returns:
tuple[torch.Tensor, torch.Tensor]

A tuple containing: - bin_points : torch.Tensor of shape (N, 3) - barycentric coordinates - bin_points_xy : torch.Tensor of shape (N, 2) - Cartesian coordinates

Raises:
TypeError

If input types are invalid.

ValueError

If domain_bounds structure is invalid or eps is non-positive.

RuntimeError

If computation fails.

Examples

>>> r2, corners, triangle, trimesh = simplex_setup(refinement=3)
>>> domain_bounds = (r2, corners, triangle, trimesh)
>>> bin_points, bin_points_xy = simplex_bin_setup_vectorized(domain_bounds)
>>> print(f"Generated {bin_points.shape[0]} bin points")
InflGame.domains.simplex.simplex_utils.simplex_setup(refinement=4)#

Sets up the simplex by defining its corners and creating a refined triangular grid.

Parameters:

refinement (int) – The level of refinement for the triangular grid. Default is 4.

Returns:

A tuple containing: - r2 (np.ndarray): The third corner of the simplex. - corners (np.ndarray): The coordinates of the simplex corners. - triangle (matplotlib.tri.Triangulation): The initial triangulation of the simplex. - trimesh (matplotlib.tri.Triangulation): The refined triangular grid.

Return type:

tuple

InflGame.domains.simplex.simplex_utils.xy2ba(x, y, corners)#

Converts Cartesian coordinates to barycentric coordinates.

Parameters:
  • x (torch.Tensor) – x-coordinate in Cartesian space.

  • y (torch.Tensor) – y-coordinate in Cartesian space.

  • corners (np.ndarray) – Coordinates of the simplex corners.

Returns:

Barycentric coordinates corresponding to the input Cartesian coordinates.

Return type:

torch.Tensor

InflGame.domains.simplex.simplex_utils.xy2ba_vectorized(x, y, corners)#

Converts multiple Cartesian coordinates to barycentric coordinates using vectorized operations.

This function provides significant performance improvements over single-point conversions when processing large datasets of coordinate pairs.

The barycentric coordinates are computed using the formula:

\[\lambda_1 = \frac{(y_2 - y_3)(x - x_3) + (x_3 - x_2)(y - y_3)}{(y_2 - y_3)(x_1 - x_3) + (x_3 - x_2)(y_1 - y_3)}\]
\[\lambda_2 = \frac{(y_3 - y_1)(x - x_3) + (x_1 - x_3)(y - y_3)}{(y_2 - y_3)(x_1 - x_3) + (x_3 - x_2)(y_1 - y_3)}\]
\[\lambda_3 = 1 - \lambda_1 - \lambda_2\]
Parameters:
xtorch.Tensor | np.ndarray | List[float]

x-coordinates in Cartesian space, shape (N,).

ytorch.Tensor | np.ndarray | List[float]

y-coordinates in Cartesian space, shape (N,).

cornerstorch.Tensor | np.ndarray

Coordinates of the simplex corners, shape (3, 2).

Returns:
torch.Tensor

Barycentric coordinates of shape (N, 3) where each row contains the barycentric coordinates [λ₁, λ₂, λ₃] for the corresponding input point.

Raises:
TypeError

If input types are not supported.

ValueError

If input dimensions are incompatible or contain invalid values.

RuntimeError

If computation fails due to numerical issues.

Examples

>>> import torch
>>> import numpy as np
>>> corners = np.array([[0, 0], [1, 0], [0.5, 0.866]])
>>> x = torch.tensor([0.1, 0.5, 0.8])
>>> y = torch.tensor([0.2, 0.3, 0.1])
>>> barycentric = xy2ba_vectorized(x, y, corners)
>>> print(barycentric.shape)
torch.Size([3, 3])