Utils¶
This section contains the API documentation for utility functions and helpers.
General Utilities¶
The utils module contains general-purpose utility functions.
- skagent.utils.apply_fun_to_vals(fun, vals)¶
Applies a function to the arguments defined in vals. This is equivalent to fun(**vals), except that vals may contain keys that are not named arguments of fun.
- Parameters:
fun (callable)
vals (dict)
- skagent.utils.compute_gradients_for_tensors(tensors_dict, wrt, create_graph=False)¶
Compute gradients for a dictionary of tensors with respect to variables.
This function computes gradients using PyTorch’s autograd. It is used by the gradient methods on BellmanPeriod (
grad_reward_function,grad_transition_function, andgrad_pre_state_function).For batched inputs, this computes the diagonal of the Jacobian: for each batch element i, we compute ∂target[i]/∂var[i]. The implementation uses
grad(target.sum(), var), which yields the correct diagonal whenever target[i] depends only on var[i] (sample-independence). This assumption holds when each batch element is computed independently, which is the case for element-wise reward and transition functions in this library.For scalar inputs,
.sum()is a no-op, so the same code path handles both cases without branching.- Parameters:
tensors_dict (
dict[str,Tensor]) – Dictionary mapping symbol names to tensors to compute gradients for.wrt (
dict[str,Tensor]) – Dictionary of variables to compute gradients with respect to. Keys are variable names, values are tensors withrequires_grad=True.create_graph (
bool) – If True, the graph of the derivative is constructed, allowing higher-order derivatives and end-to-end training. Default: False.
- Returns:
Nested dictionary of gradients for each tensor symbol and variable:
{tensor_sym: {var_name: gradient}}. A variable with no computational graph path to the target receives a zero tensor, which is the value of the partial derivative under structural independence.- Return type:
- Raises:
ValueError – If a
wrttensor does not haverequires_grad=True.
- skagent.utils.compute_parameter_difference(params1, params2)¶
Compute the L2 norm of the difference between two parameter vectors.
- skagent.utils.create_vectorized_function_wrapper_with_mapping(lambda_func, param_to_column)¶
Create a vectorized wrapper that automatically maps lambda parameters to correct tensor columns based on a parameter-to-column mapping.
- Parameters:
lambda_func – Original lambda function
param_to_column – A mapping from parameter names to columns of a tensor
- skagent.utils.extract_parameters(network)¶
Extract all parameters from a PyTorch network into a flat tensor.
- skagent.utils.fischer_burmeister(a, h, eps=1e-12)¶
Compute the Fischer-Burmeister function for smooth complementarity.
The Fischer-Burmeister function replaces the complementarity conditions \(a \geq 0,\; h \geq 0,\; ah = 0\) with the equivalent smooth equation:
\[\text{FB}(a, h) = a + h - \sqrt{a^2 + h^2} = 0\]This is differentiable everywhere, unlike \(\min(a, h) = 0\).
Following Maliar et al. (2021, JME) equation (25).
- Parameters:
a (
Tensor) – First argument (e.g., slack variable \(1 - c/w\)).h (
Tensor) – Second argument (e.g., unit-free Lagrange multiplier).eps (
float) – Regularization constant added inside the square root to keep the gradient finite at the origin. At the defaulteps=1e-12,FB(0, 0) = -sqrt(eps) ≈ -1e-6rather than exactly zero. This is below typical convergence tolerances but should be accounted for in tests or with very tight tolerances.
- Returns:
Fischer-Burmeister residual. Approximately zero when the complementarity conditions are satisfied.
- Return type:
- skagent.utils.reconcile(vec_a, vec_b)¶
Returns a new vector with the values of vec_b but with the object type and shape of vec_a.
Example Usage¶
Calling a Function from a Dictionary of Values¶
apply_fun_to_vals calls a function using only the entries of a dictionary that
match the function’s named arguments, ignoring the rest:
from skagent.utils import apply_fun_to_vals
def transition(a, b):
return a + b
# The extra key "c" is ignored
apply_fun_to_vals(transition, {"a": 1.0, "b": 2.0, "c": 99.0}) # 3.0
Smooth Complementarity Conditions¶
fischer_burmeister replaces the complementarity conditions
\(a \geq 0,\; h \geq 0,\; ah = 0\) with a single smooth equation, which is useful
for occasionally binding constraints in loss functions:
import torch
from skagent.utils import fischer_burmeister
a = torch.tensor([0.0, 1.0, 3.0])
h = torch.tensor([2.0, 0.0, 4.0])
fischer_burmeister(a, h) # tensor([0., 0., 2.])
Note
Grid construction tools (Grid, make_grid, cartesian_product) live in
skagent.grid and are documented on the Algorithms page.