PINC¶
Conventional soft-IC PINN-for-control (PINC) surrogate: generic MLP with an autograd derivative.
PINC ¶
PINC(n_state: int, n_cond: int, hidden_size: int = 64, hidden_layer: int = 2, act: type = nn.Tanh, ic_mode: str = 'soft', hard_ic_style: str = 'subtract', t_zero: float = -1.0, derivative_mode: str = 'forward')
Bases: Module
Continuous-time PINN-for-control surrogate: a generic MLP over [x_k | cond | t].
The conventional PINC architecture (Antonelo et al., 2021): a feed-forward network maps the
initial state, conditioning, and normalized time directly to the state,
x(t) = NN([x_k, cond, t]). It is the deliberate foil to
:class:~tsfast.pinn.ddpinn.DampedAnsatzPINN and shares its I/O contract — same normalized
[-1, 1] coordinates, same row layout [x_k (n_state) | cond (n_cond) | t (1)], same
forward(X, derivative_flag) signature — so it rides the same collocation sampler, residual,
and :class:~tsfast.pinn.ddpinn.DDPINNRollout unchanged. It differs in exactly two ways:
- The initial condition is, by default (
ic_mode="soft"), not exact — there is no ansatz pinningx(t_zero) = x_k; it is enforced softly by :class:PINCLearnervia a penalty term. Withic_mode="hard"it is made exact by construction —x(t) = x_k + NN([feat, t]) − NN([feat, t_zero])— the DD-PINN's trick on a generic basis, which needs no IC loss (train it with the base :class:SurrogatePINNLearner). The soft/hard pair isolates the "exact IC by construction" advantage; hard-vs-DD-PINN isolates the basis. - The time-derivative comes from autograd, not a closed form —
derivative_flag=Truedifferentiates the network output w.r.t. the time channel. (The hard-IC offset terms are constant int, so they do not changedx/dt.)
The derivative is computed by forward-mode AD by default: since time is a single scalar input
and the state is the (multi-channel) output, one dual forward pass gives dx/dt for all
channels at cost O(1) in the output dimension, versus the O(n_state) backward passes
reverse mode needs. The two modes are numerically identical (and both support the training
double-backward); reverse is roughly break-even at n_state = 2 and forward pulls ahead as the
state grows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_state
|
int
|
state dimension; |
required |
n_cond
|
int
|
conditioning channels (control + collocation vars) between |
required |
hidden_size
|
int
|
width of the MLP. |
64
|
hidden_layer
|
int
|
number of hidden layers in the MLP. |
2
|
act
|
type
|
activation function class; defaults to |
Tanh
|
ic_mode
|
str
|
|
'soft'
|
hard_ic_style
|
str
|
how the hard IC is constructed ( |
'subtract'
|
t_zero
|
float
|
normalized-time value mapped to physical |
-1.0
|
derivative_mode
|
str
|
|
'forward'
|
Source code in tsfast/pinn/pinc.py
PINCLearner ¶
Bases: SurrogatePINNLearner
Physics-only trainer for a :class:PINC, adding the soft initial-condition penalty.
Extends :class:~tsfast.pinn.ddpinn.SurrogatePINNLearner with the IC term the DD-PINN gets for
free by construction. Each collocation point's (x_k, cond) is re-evaluated at the time origin
and penalized toward x_k, so the total objective is::
loss = residual(x_phys, cond_phys, dxdt_phys) + ic_weight · ‖NN([x_k, cond, t_zero]) − x_k‖²
The residual is the physical-unit ODE residual (unchanged from the base learner); the IC term is
in normalized coordinates (the model's native space). They therefore live in different units, so
ic_weight is a genuine tuning knob — the price of the soft IC, which the hard-IC DD-PINN
avoids entirely. Everything else (collocation sampler, scalers, chain-rule factor, rollout) is
inherited unchanged, keeping the PINC and DD-PINN arms comparable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ic_weight
|
float
|
weight on the soft initial-condition penalty (relative to the physical residual). |
1.0
|
t_zero
|
float
|
normalized-time value mapped to physical |
-1.0
|
Source code in tsfast/pinn/pinc.py
physics_loss ¶
ODE residual plus the soft IC penalty on a batch of normalized collocation points.