polystep 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. polystep/__init__.py +176 -0
  2. polystep/_compiled.py +334 -0
  3. polystep/_step_blockwise.py +994 -0
  4. polystep/_step_momentum.py +128 -0
  5. polystep/_step_monolithic.py +1070 -0
  6. polystep/adaptive_subspace.py +762 -0
  7. polystep/api.py +307 -0
  8. polystep/ask_tell.py +164 -0
  9. polystep/benchmarks/__init__.py +62 -0
  10. polystep/benchmarks/baselines.py +604 -0
  11. polystep/benchmarks/rl/__init__.py +13 -0
  12. polystep/benchmarks/rl/cartpole.py +260 -0
  13. polystep/benchmarks/rl/gym_evaluator.py +304 -0
  14. polystep/benchmarks/rl/metrics.py +53 -0
  15. polystep/benchmarks/rl/policies.py +133 -0
  16. polystep/benchmarks/utils.py +1262 -0
  17. polystep/blockwise.py +549 -0
  18. polystep/cma.py +400 -0
  19. polystep/cma_subspace.py +404 -0
  20. polystep/cost_nn.py +633 -0
  21. polystep/costs.py +86 -0
  22. polystep/dynamics.py +138 -0
  23. polystep/epsilon.py +217 -0
  24. polystep/geometry.py +410 -0
  25. polystep/hybrid_subspace.py +1335 -0
  26. polystep/layers/__init__.py +16 -0
  27. polystep/layers/attention.py +243 -0
  28. polystep/layers/rnn.py +276 -0
  29. polystep/objectives/__init__.py +25 -0
  30. polystep/objectives/base.py +77 -0
  31. polystep/objectives/synthetic.py +232 -0
  32. polystep/optimizer.py +1405 -0
  33. polystep/projection/__init__.py +5 -0
  34. polystep/projection/sparse.py +291 -0
  35. polystep/py.typed +0 -0
  36. polystep/quadratic_model.py +285 -0
  37. polystep/solver.py +654 -0
  38. polystep/solvers/__init__.py +34 -0
  39. polystep/solvers/_prelude.py +129 -0
  40. polystep/solvers/base.py +77 -0
  41. polystep/solvers/greedy.py +159 -0
  42. polystep/solvers/kl_softmax.py +200 -0
  43. polystep/solvers/sinkhorn.py +522 -0
  44. polystep/solvers/softmax.py +151 -0
  45. polystep/solvers/tempered_softmax.py +97 -0
  46. polystep/subspace.py +694 -0
  47. polystep/transform.py +365 -0
  48. polystep-0.7.0.dist-info/METADATA +285 -0
  49. polystep-0.7.0.dist-info/RECORD +52 -0
  50. polystep-0.7.0.dist-info/WHEEL +5 -0
  51. polystep-0.7.0.dist-info/licenses/LICENSE +191 -0
  52. polystep-0.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,97 @@
1
+ """TemperedSoftmaxSolver: softmax weighting with a fixed temperature.
2
+
3
+ Like ``SoftmaxSolver`` but uses a separate temperature parameter ``tau``
4
+ instead of the optimizer's epsilon schedule. This decouples the softmax
5
+ sharpness from the entropic regularization so the ablation can sweep
6
+ tau independently.
7
+ """
8
+
9
+ from dataclasses import dataclass
10
+ from typing import Optional, Union
11
+
12
+ import torch
13
+
14
+ from ..costs import scale_cost_matrix
15
+ from ._prelude import align_marginal, recenter_cost, sanitize_cost, validate_positive
16
+ from .base import SolverResult
17
+
18
+
19
+ @dataclass
20
+ class TemperedSoftmaxSolver:
21
+ """Softmax solver with a fixed temperature independent of epsilon.
22
+
23
+ Computes transport weights via ``softmax(-C / tau)`` where ``tau`` is
24
+ set once at construction and NOT overridden by the optimizer's per-step
25
+ epsilon. The ``epsilon`` attribute is accepted for API compatibility
26
+ but ignored in ``solve()``.
27
+
28
+ Attributes:
29
+ epsilon: Accepted for API compatibility; overridden per-step by the
30
+ optimizer but NOT used in the softmax computation.
31
+ tau: Fixed temperature for the softmax. Lower tau = sharper weights.
32
+ compile: Accepted for API compatibility; unused.
33
+ """
34
+
35
+ epsilon: float = 0.1
36
+ tau: float = 1.0
37
+ compile: bool = False
38
+
39
+ def solve(
40
+ self,
41
+ cost_matrix: torch.Tensor,
42
+ a: Optional[torch.Tensor] = None,
43
+ b: Optional[torch.Tensor] = None,
44
+ init_f: Optional[torch.Tensor] = None,
45
+ init_g: Optional[torch.Tensor] = None,
46
+ scale_cost: Optional[Union[str, float]] = None,
47
+ ) -> SolverResult:
48
+ """Compute softmax weights using fixed temperature tau.
49
+
50
+ Args:
51
+ cost_matrix: Cost matrix C of shape (P, V).
52
+ a: Source marginal of shape (P,). Defaults to uniform 1/P.
53
+ b: Target marginal (accepted but ignored).
54
+ init_f: Warm-start dual potential (accepted but ignored).
55
+ init_g: Warm-start dual potential (accepted but ignored).
56
+ scale_cost: Cost scaling: 'mean', 'max_cost', or float divisor.
57
+
58
+ Returns:
59
+ SolverResult with transport matrix, cost, and metadata.
60
+
61
+ Raises:
62
+ ValueError: If tau <= 0.
63
+ """
64
+ validate_positive(
65
+ self.tau,
66
+ "tau",
67
+ "tau is the temperature in softmax(-C/tau).",
68
+ )
69
+
70
+ P, V = cost_matrix.shape
71
+ cost_matrix = sanitize_cost(cost_matrix) # FP32 promote + finite costs
72
+ device, dtype = cost_matrix.device, cost_matrix.dtype
73
+ a = align_marginal(a, P, device, dtype)
74
+
75
+ C = scale_cost_matrix(cost_matrix, scale_cost)
76
+ # softmax is shift-invariant; recentering keeps min(C)=0 so -C/tau cannot
77
+ # form a +inf logit at tiny tau.
78
+ C, cost_shift = recenter_cost(C)
79
+
80
+ # Use fixed tau (NOT self.epsilon) for the softmax. Pin inside an
81
+ # autocast-disabled FP32 region so an outer mixed-precision context
82
+ # can't downcast -C/tau before softmax subtracts the row max.
83
+ with torch.amp.autocast("cuda", enabled=False), torch.amp.autocast("cpu", enabled=False):
84
+ W = torch.softmax(-C / self.tau, dim=-1)
85
+ transport = W * a.unsqueeze(-1)
86
+ # Undo the recenter shift so the reported cost is <C_scaled, transport>.
87
+ ent_cost = ((C * transport).sum() + cost_shift * a.sum()).item()
88
+
89
+ return SolverResult(
90
+ matrix=transport,
91
+ cost=ent_cost,
92
+ f=None,
93
+ g=None,
94
+ converged=True,
95
+ n_iters=1,
96
+ ent_reg_cost=ent_cost,
97
+ )