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