Experiment#
- class Experiment#
A collection of optimization experiment records stored as one OMMX Artifact.
An
Experimentowns experiment-level attachments and a sequence of closedRunrecords. EachRuncan store scalar run parameters, run-level attachments, and zero or moreSolverecords.Newly created experiments are unsealed. Call
commit()to write the experiment into the local registry as an OMMX Artifact. After commit, the same object can be used as a read-only view of the committed artifact.with Experiment(...)commits on normal exit if the experiment is still unsealed. On exception it does not advance the successful Experiment image reference; instead it tries to publish a local checkpoint with status"failed"or"interrupted".Logging APIs store payload bytes in the Local Registry immediately. The final commit writes an Experiment config and manifest that make those payloads reachable as one immutable Artifact. A closed
Runalso publishes a best-effort"draft"checkpoint so a later process can resume from the latest closed Run withExperiment.restore_from_checkpoint(...).Use experiment-level attachments for shared context such as dataset or source-problem metadata. Use
Run.log_parameter(...)for scalar values that should appear inrun_parameters_df(), and use run attachments orRun.log_solve(...)for payloads that belong to a specific run.Example:
from ommx.experiment import Experiment with Experiment.with_temp_local_registry() as exp: ... exp.log_json("dataset", {"name": "demo"}) ... with exp.run() as run: ... run.log_parameter("capacity", 10) ... run.log_json("scenario", {"capacity": 10}) len(exp.runs) 1 len(exp.attachment_names) 1 exp.run_parameters_df().to_dict() {'capacity': {0: 10}}
If the experiment has only one run, open the experiment and the run in one
withstatement. On normal exit, the run is finished first and then the experiment is committed:with Experiment() as exp, exp.run() as run: # doctest: +SKIP ... solution = run.log_solve(adapter, instance, time_limit=10.0) exp.rename("ghcr.io/container/name:latest") # doctest: +SKIP exp.push() # doctest: +SKIP
- __enter__() Experiment#
- __exit__(exc_type: Optional[Any] = None, exc_value: Optional[Any] = None, traceback: Optional[Any] = None) bool#
- __new__(image_name: Optional[str] = None, store_trace: bool = False) Experiment#
Start a new Experiment in the default local registry.
If
image_nameis omitted, OMMX generates an anonymous local Experiment name. Pass an OCI image reference such as"example.com/team/experiment:tag"when the experiment should be loaded later by name. The image reference is a mutable local registry alias for the committed Artifact; the Artifact manifest digest remains the immutable identity of the committed contents.Set
store_trace=Trueto store traces forRuncontext managers created from this Experiment. The Experiment itself does not need to be used as a context manager.
- __repr__() str#
- attachment_media_type(name: str) str#
OCI media type of an experiment-level attachment.
- commit() Artifact#
Commit this unsealed Experiment into the local registry.
All open runs must be closed before committing. The returned
Artifactcan be saved as a.ommxarchive or passed toExperiment.from_artifact. After commit, this object becomes a read-only view of the committed Experiment. A successful commit publishes the requested image reference and removes any local checkpoint for that Experiment when present.
- fork(image_name: Optional[str] = None, store_trace: bool = False) Experiment#
Fork this committed Experiment into a new unsealed child Experiment.
The parent Experiment is not modified. Existing Attachments, Runs, Solves, and Run parameters are carried into the child Experiment. When the child is committed, its Artifact manifest records the parent manifest descriptor as OCI
subject. The child reuses payload blobs already present in the Local Registry; forking creates a new manifest but does not duplicate unchanged Instance, Solution, or Attachment bytes.If
image_nameis omitted, OMMX generates an anonymous local Experiment name for the child. The returned Experiment can be used as a context manager:with parent.fork() as child: with child.run() as run: run.log_parameter("capacity", 56)
Raises an error if this Experiment has not been committed yet.
Set
store_trace=Trueon the returned child to store traces forRuncontext managers created from it. The child Experiment itself does not need to be used as a context manager.
- from_artifact(artifact: Artifact) Experiment#
Interpret an already-open Artifact as a committed Experiment.
This is the usual entry point after importing or receiving an OMMX Artifact handle. The artifact must contain an Experiment config.
- get_attachment(name: str) Any#
Read an experiment-level attachment by name.
The returned Python object is decoded from the attachment media type: JSON attachments become normal Python objects, OMMX instance-like attachments become the corresponding
ommx.v1objects, and unknown media types are returned as rawbytes.
- get_blob(name: str) bytes#
Read raw bytes of an experiment-level attachment by name.
- get_instance(name: str) Instance#
Read an Instance experiment-level attachment by name.
- get_json(name: str) Any#
Read a JSON experiment-level attachment by name.
Raises an error if the attachment exists but its media type is not
application/json.
- get_parametric_instance(name: str) ParametricInstance#
Read a ParametricInstance experiment-level attachment by name.
- get_sample_set(name: str) SampleSet#
Read a SampleSet experiment-level attachment by name.
- get_solution(name: str) Solution#
Read a Solution experiment-level attachment by name.
- get_with_codec(codec: type[AttachmentCodec[T]], name: str) T#
Read an experiment-level attachment by name and decode it with a codec.
The codec class must provide
media_type,encode(value) -> bytes, anddecode(bytes) -> object. This method validates the stored media type against the codec before decoding.
- import_archive(path: str | PathLike | Path) Experiment#
Import an Experiment Artifact from a
.ommxOCI archive file (or an OCI Image Layout directory).The archive is imported into the default Local Registry, matching
Artifact.import_archive(), and then interpreted as an Experiment. The imported artifact must contain an Experiment config.
- load(image_name: str) Experiment#
Load a committed Experiment Artifact by image reference.
If the image is not found in the default Local Registry, OMMX tries to pull it from the remote registry, matching
Artifact.load(). The loaded artifact must contain an Experiment config. UseExperiment(...)to create a new unsealed experiment.
- log_attachment(name: str, media_type: str, bytes: bytes) None#
Attach arbitrary bytes with an explicit OCI media type in the experiment space.
The
nameis stored as attachment metadata and is intended for humans. The bytes are stored as a layer in the committed artifact.
- log_file(name: str, path: str | PathLike | Path, media_type: Optional[str] = None, filename: Optional[str] = None) None#
Attach an existing filesystem file in the experiment space.
The file bytes are copied into the Local Registry immediately. If
media_typeis omitted, the Rust SDK infers it from file contents and unknown types fall back toapplication/octet-stream. The original source path is not stored; only a basename for later export is stored as attachment metadata.
- log_instance(name: str, instance: Instance) None#
Attach an Instance in the experiment space.
- log_json(name: str, value: Any) None#
Attach a JSON-serializable value in the experiment space.
The value is encoded with Python's
json.dumpsand stored with media typeapplication/json.
- log_parametric_instance(name: str, pi: ParametricInstance) None#
Attach an ParametricInstance in the experiment space.
- log_sample_set(name: str, sample_set: SampleSet) None#
Attach a SampleSet in the experiment space.
- log_solution(name: str, solution: Solution) None#
Attach a Solution in the experiment space.
- log_with_codec(codec: type[AttachmentCodec[T]], name: str, value: T) None#
Encode a Python object with an attachment codec and attach it in the experiment space.
The codec class must provide
media_type,encode(value) -> bytes, anddecode(bytes) -> object. OMMX owns only this protocol; concrete codecs should live in the package that owns the payload type.
- push() None#
Push this committed Experiment Artifact to its remote registry.
Use
rename(...)first when an anonymous or local-only experiment should be published under a remote container image reference.Raises an error if the Experiment has not been committed yet.
- rename(image_name: str) None#
Rename this Experiment to another local registry image reference.
Before commit, this changes the image reference that
commit()will publish. After commit, it publishes the same Artifact manifest underimage_nameand updates this handle to use the new name. The previous name remains as an alias in the Local Registry.
- restore_from_checkpoint(image_name: str) Experiment#
Restore an unsealed Experiment from its checkpoint.
Pass the original requested Experiment image name, not the generated checkpoint ref. This accepts checkpoint statuses such as
draft,failed, orinterrupted, and returns a new unsealed Experiment whose image name is the original requested Experiment image name recorded in the checkpoint metadata. Checkpoint Artifact handles and checkpoint image names are not part of the public API.
- run() Run#
Start a new Run in this unsealed Experiment.
The returned
Runmust be closed beforecommit(). Use it as a context manager to close it automatically on normal or exceptional exit:with experiment.run() as run: run.log_parameter("capacity", 47)
Closing a Run records its status as
"finished","failed", or"interrupted"and publishes a best-effort draft checkpoint for the parent Experiment. Payloads written by an open Run before it is closed are stored in the Local Registry but are not recoverable through a checkpoint until the Run is closed.
- run_parameters_df() DataFrame#
Wide DataFrame of run parameters, indexed by
run_id.Run parameters are scalar values logged with
Run.log_parameter. Closed runs with no parameters are still present as index rows. Adapter options recorded byRun.log_solveare solve metadata and do not appear in this table.
- save(path: str | PathLike | Path) None#
Save this committed Experiment Artifact as a
.ommxOCI archive file atpath.The archive is an exchange-format export of the registry-resident Experiment Artifact. Loading the archive back via
Experiment.import_archive()reimports it into the SQLite Local Registry under the same image name.Raises an error if the Experiment has not been committed yet.
- with_temp_local_registry(image_name: Optional[str] = None, store_trace: bool = False) Experiment#
Start a new Experiment backed by a temporary Local Registry.
The temporary registry is kept alive by the returned Experiment and by Artifacts / loaded Experiments derived from it. This is useful for examples and tests because it does not write entries into the process-wide default local registry.
Set
store_trace=Trueto store traces forRuncontext managers created from this Experiment. The Experiment itself does not need to be used as a context manager.
- write_attachment(name: str, path: str | PathLike | Path, overwrite: bool = False) Path#
Write an experiment-level attachment to a filesystem path.
If
pathnames an existing directory, the attachment filename stored bylog_fileis used inside that directory. Otherwisepathis treated as the destination file path.
- property artifact: Artifact#
Read-only property.
Committed OMMX Artifact for this Experiment.
Raises an error if the Experiment has not been committed yet.
- property attachment_names: list[str]#
Read-only property.
Names of experiment-level attachments.
- property image_name: str#
Read-only property.
OCI image reference used to store this Experiment in a local registry.