Model and result
kd.Model runs a search and returns a kd.ExperimentResult.
import kd
model = kd.Model(algorithm="sga", generations=200, seed=42)
model.fit(kd.load_kdv())
print(model.result_.equation, model.best_score_)
algorithm takes the name of any of the seven algorithms; each one's scope and
parameters are on its own page under Algorithms. Passing
config= supplies that algorithm's settings and becomes the single source for
them, so supplying the same settings as keywords alongside it raises. Which parameters
may change on a resume is covered in
Parameter tiers and resuming, and
what best_score_ measures in
Score conventions and comparability.
Model
High-level facade for PDE discovery (PySR-style API).
Parameters:
-
algorithm(str, default:'sga') –Search algorithm name.
-
generations(int, default:50) –Search-loop length (default 50).
-
population(int, default:20) –SGA population size (number of PDE candidates). SGA-only.
-
depth(int, default:4) –Maximum tree depth per term. SGA-only.
-
width(int, default:5) –Maximum number of terms per PDE. SGA-only.
-
aic_ratio(float, default:1.0) –AIC penalty ratio. SGA-only.
-
derivatives(str, default:'finite_diff') –Derivative provider mode:
"finite_diff"or"autograd"(forwardsuse_autograd=TruetoSGAConfig). -
seed(int, default:0) –Random seed for reproducibility. It threads into every algorithm's default config when
config=is unset; otherwise the config's own seed wins. Passing the facadeseed=together withconfig=is rejected by_validate_config_exclusivity. -
verbose(bool, default:True) –When True, print per-iteration progress to stdout.
-
config(SGAConfig | DLGAConfig | DiscoverConfig | PySRConfig | PySINDyConfig | EqGPTConfig | Llm4edConfig | None, default:None) –Optional pre-built
SGAConfig,DLGAConfig,DiscoverConfig,PySRConfig,EqGPTConfig,Llm4edConfig, orPySINDyConfig. When provided, it is the single source of plugin settings. -
callbacks(list[RunnerCallback] | None, default:None) –Optional list of additional
RunnerCallbackinstances to attach to the runner. The verbose progress printer is appended automatically whenverbose=True. -
surrogate_model(Module | None, default:None) –Optional pre-trained
torch.nn.Moduleforwarded toDLGAPlugin(surrogate_model=...). -
provider(LLMProvider | None, default:None) –Optional pre-built
kd.llm.LLMProviderforwarded toLlm4edPlugin(provider=...). llm4ed-only — passing it with any other algorithm raisesTypeError(silent drop is a bug-attractor). -
checkpoint_dir(str | Path | None, default:None) –Optional directory for periodic checkpoints.
-
checkpoint_every(int, default:10) –Save a per-iteration checkpoint every N iterations (0-indexed: saves at 0, N, 2N, ...; default 10).
-
checkpoint_keep_last(int | None, default:None) –Retention bound on PERIODIC checkpoints.
None(default) keeps every one, so that the evidence trail stays complete; anint >= 1keeps only the N most recent periodic checkpoints, pruning older ones from both the manifest and disk. -
phases_path(str | Path | None, default:None) –Optional
phases.jsonlsink (kd-runphase-v1). -
savgol_window(int, default:0) –Savitzky-Golay smoothing window length.
0(default) disables smoothing. A positive value smooths every field along every grid axis with that window length and polynomial order 3 before the search. -
small_term_rtol(float, default:0.0) –Relative coefficient threshold for the final answer.
0.0(default) keeps the algorithm's answer. A value r in (0, 1) drops every term whose finite coefficient magnitude is below r times the largest finite coefficient magnitude. -
**kwargs(Any, default:{}) –Forwarded to the selected algorithm's config dataclass when the field is not already owned by a facade parameter. Unknown, cross-algorithm, colliding, or JSON-type-invalid fields raise at construction.
best_expr_
property
best_expr_: str
Best discovered expression string (post-fit only).
best_score_
property
best_score_: float
Best score from the last fit (post-fit only).
algorithm_
property
algorithm_: SearchAlgorithm
The fitted SearchAlgorithm plugin instance (post-fit only).
fit
fit(
dataset: PDEDataset | TabularDataset,
resume_from: str | Path | None = None,
*,
sketch: Sketch | None = None,
reseed: bool = False,
verify: VerifyPolicy | None = None,
) -> Model
Run the search and populate post-fit attributes.
Parameters:
-
dataset(PDEDataset | TabularDataset) –A PDE dataset or public
X -> yregression table. -
resume_from(str | Path | None, default:None) –Optional path to a checkpoint file written by a previous run (
checkpoint_*.pt). The checkpoint restores search state (population / controller weights / best). -
sketch(Sketch | None, default:None) –Optional semantic search-space contract for this fit (
kd.Sketch): pinned terms are deducted from the regression target and restored with their exact coefficients, and the run's result carries a soundSketchOutcome(result_.sketch_outcome) whosesolutionis only filled when the discovered law satisfies every sketch clause AND fits the data withinverify(see below). -
reseed(bool, default:False) –Turn the resume into a BRANCH (K4). A plain resume keeps the checkpoint's random streams and continues one trajectory.
-
verify(VerifyPolicy | None, default:None) –Residual gate the sketch exit judges the lifted law with.
Noneresolves tokd.SKETCH_EXIT_VERIFY(nmse_max=0.05), so a sketch fit certifies only a law that also fits the data on the platform's own footing.
Returns:
-
Model–selffor sklearn-style chaining.
Raises:
-
NotImplementedError–If
algorithmis not supported. -
TypeError–If
sketchis neither aSketchnorNone. -
ValueError–If
sketchuses a clause the algorithm's capability declaration does not support, targets a non-evolution dataset, or declares an LHS differing from the dataset's resolved LHS; or if the dataset is missing the required LHS field or axis. -
FileNotFoundError–If
resume_fromdoes not exist. -
IsADirectoryError–If
resume_frompoints at a directory. -
RuntimeError–If a LEGACY
resume_from(no config snapshot) was written by a structurally different config (state_dict shape mismatch on restore); a snapshot-bearing checkpoint hits theValueErrortier gate first.
train_surrogate
train_surrogate(
dataset: PDEDataset | TabularDataset,
) -> tuple[Module, TrainingResult]
Train this instrument's derivative surrogate without running a search.
Returns:
-
tuple[Module, TrainingResult]–(module, training_result); the module is not installed on this facade.
Raises:
-
NotImplementedError–The instrument accepts no injected surrogate (empty
config_artifact_keys), so it trains none; or the dataset's (topology, lhs_order) is one the instrument cannot fit -- the same gatefitruns before its platform build, with the same message. -
TypeError–A tabular dataset (scalar regression has no field surrogate).
-
ValueError–This facade already holds an injected model (
field_model/surrogate_model); training here would retrain and silently discard it. Also sga under the defaultderivatives="finite_diff", which never consults a surrogate.
Result structure
One fit produces one ExperimentResult, and the trailing-underscore attributes
above are shortcuts into it. Its contents fall into four groups, and the entry
below lists every field:
- The answer.
best_expressionandbest_score, withscore_kindandscore_directionstating what that number is and which direction is better. - Fit quality.
final_eval, anEvaluationResultcarrying mse, nmse, r² and the coefficients, alongside theactualandpredictedvalues behind them. - Search progress.
iterations,early_stopped, andrecorder, the per-iteration record thatkd.VizEnginedraws from. - Provenance.
dataset_name,algorithm_nameandconfig, plus themanifestandrun_recordthat seal the run against its inputs.
ExperimentResult
dataclass
Bases: RunResult
Serializable value object for a completed experiment.
has_pareto_front
has_pareto_front() -> bool
Return whether the recorder contains a Pareto expression series.
has_search_trajectory
has_search_trajectory() -> bool
Whether any trajectory column exists, including an incomplete family.
pareto_front
pareto_front() -> list[ParetoEntry]
Return the last complete recorder-backed Pareto front.
save
save(path: Path | str) -> None
Persist the result to disk as RFC 8259 compliant JSON.
search_trajectory
search_trajectory() -> list[
list[SearchTrajectoryCandidate]
]
Return distinct fitted-structure observations by recorded iteration.
to_dict
to_dict() -> dict[str, Any]
Return a JSON-safe (RFC 8259) representation of the result.
Interruption of a running fit
kd.SearchInterrupted is the exception an embedding process raises inside a
running fit to stop it: a signal handler, or a watchdog that enforces a
wall-clock budget. The search stack lets this exception through instead of
recording it as one more invalid candidate, so fit exits with it and the
caller decides what to keep. The signal is scoped to the one search it lands
in; a batch driver treats the interrupted episode as a failed entry and
continues with the next one.
import signal
import kd
def stop(signum, frame):
raise kd.SearchInterrupted("wall-clock budget reached")
signal.signal(signal.SIGTERM, stop)
model = kd.Model(algorithm="sga", generations=200, seed=42)
try:
model.fit(kd.load_kdv())
except kd.SearchInterrupted:
pass # the search stopped where the signal landed