Skip to content

Properties

Creating properties

create_predefined_property

create_predefined_property(
    property_id: str,
    st_method: StatisticalMethod | None = None,
    epsilon: float | None = 0.1,
    kappa: float = 0.05,
    min_samples: int | None = None,
    name: str | None = None,
    *,
    relative_error: bool = False,
    sound: bool = False,
    **kwargs: Any,
) -> Property

Create a ready-made, parameterized property.

Unless an explicit st_method is given, a suitable statistical method is selected automatically from the provided parameters. The available property_id values (also returned by get_predefined_properties) are:

property_id Measures (per episode) Binomial Default bounds Property-specific **kwargs
"return" Acc. discounted reward No (-inf, inf) gamma (default 0.99)
"episode_length" #Steps, incl. truncation No (0, inf)
"goal_reaching_probability" Perc. of runs with return ≥ goal_reward Yes (0, 1) goal_reward (default 1)
"truncation" Perc. of truncated runs Yes (0, 1)
"unsuccesful_termination" Perc. terminated with non-positive return Yes (0, 1)

Any of the defaults above (bounds, gamma, goal_reward, ...) can be overridden via **kwargs.

Parameters:

Name Type Description Default
property_id str

ID of the predefined property (e.g. "return", "episode_length").

required
st_method StatisticalMethod | None

An explicit statistical method. If None, one is selected automatically.

None
epsilon float | None

Half-width of the requested confidence interval. With relative_error=True it is relative to the estimate, otherwise absolute. Pass None to run a fixed number of episodes without a convergence target.

0.1
kappa float

Error probability; the true mean lies within the CI with prob. 1 - kappa.

0.05
min_samples int | None

Minimum number of samples before convergence may be declared.

None
name str | None

Name used when storing results. Defaults to property_id.

None
relative_error bool

Whether epsilon is a relative (True) or absolute (False) error.

False
sound bool

Whether a sound statistical method (guaranteed coverage) must be used.

False
**kwargs Any

Property-specific attributes (e.g. bounds, gamma, goal_reward) that override the predefined defaults.

{}

Returns:

Type Description
Property

The configured Property.

Raises:

Type Description
ValueError

If property_id is not a known predefined property.

Source code in pydsmc/property.py
def create_predefined_property(
    property_id: str,
    st_method: st.StatisticalMethod | None = None,
    epsilon: float | None = 0.1,
    kappa: float = 0.05,
    min_samples: int | None = None,
    name: str | None = None,
    *,
    relative_error: bool = False,
    sound: bool = False,
    **kwargs: Any,
) -> Property:
    """Create a ready-made, parameterized property.

    Unless an explicit `st_method` is given, a suitable statistical method is selected automatically
    from the provided parameters. The available `property_id` values (also returned by
    [`get_predefined_properties`][pydsmc.get_predefined_properties]) are:

    | `property_id`                 | Measures (per episode)                        | Binomial | Default `bounds` | Property-specific `**kwargs` |
    | ----------------------------- | --------------------------------------------- | -------- | ---------------- | ---------------------------- |
    | `"return"`                    | Acc. discounted reward                        | No       | `(-inf, inf)`    | `gamma` (default `0.99`)     |
    | `"episode_length"`            | #Steps, incl. truncation                      | No       | `(0, inf)`       | —                            |
    | `"goal_reaching_probability"` | Perc. of runs with return ≥ `goal_reward` | Yes      | `(0, 1)`         | `goal_reward` (default `1`)  |
    | `"truncation"`                | Perc. of truncated runs                       | Yes      | `(0, 1)`         | —                            |
    | `"unsuccesful_termination"`   | Perc. terminated with non-positive return     | Yes      | `(0, 1)`         | —                            |

    Any of the defaults above (`bounds`, `gamma`, `goal_reward`, ...) can be overridden via `**kwargs`.

    Args:
        property_id: ID of the predefined property (e.g. `"return"`, `"episode_length"`).
        st_method: An explicit statistical method. If `None`, one is selected automatically.
        epsilon: Half-width of the requested confidence interval. With `relative_error=True` it is
            relative to the estimate, otherwise absolute. Pass `None` to run a fixed number of
            episodes without a convergence target.
        kappa: Error probability; the true mean lies within the CI with prob. `1 - kappa`.
        min_samples: Minimum number of samples before convergence may be declared.
        name: Name used when storing results. Defaults to `property_id`.
        relative_error: Whether `epsilon` is a relative (`True`) or absolute (`False`) error.
        sound: Whether a sound statistical method (guaranteed coverage) must be used.
        **kwargs: Property-specific attributes (e.g. `bounds`, `gamma`, `goal_reward`) that override
            the predefined defaults.

    Returns:
        The configured [`Property`][pydsmc.Property].

    Raises:
        ValueError: If `property_id` is not a known predefined property.
    """
    if name is None:
        name = property_id

    if property_id not in __PRE_DEFINED_PROPERTIES:
        raise ValueError(f"Predefined property '{property_id}' not found")

    property_parameters = __PRE_DEFINED_PROPERTIES[property_id] | kwargs
    # determine which statistical method should be used to compute the confidence interval
    if st_method is None:
        st_method = select_statistical_method(
            epsilon=epsilon,
            kappa=kappa,
            relative_error=relative_error,
            min_samples=min_samples,
            sound=sound,
            **property_parameters,
        )
        DSMCLogger.get_logger().debug(
            f"Automatically selected statistical method {st_method.__class__.__name__} for predefined property {name}",
        )

    return Property(
        name=name,
        st_method=st_method,
        **property_parameters,
    )

create_custom_property

create_custom_property(
    name: str,
    check_fn: Callable[
        [
            Property,
            list[tuple[Any, Any, Any, bool, bool, dict]],
        ],
        float,
    ],
    st_method: StatisticalMethod | None = None,
    epsilon: float | None = 0.1,
    kappa: float = 0.05,
    bounds: tuple[float | None, float | None] = (-inf, inf),
    min_samples: int | None = None,
    *,
    relative_error: bool = False,
    binomial: bool = False,
    sound: bool = False,
    **kwargs: Any,
) -> Property

Create a custom property from a user-provided checking function.

The check_fn receives the property instance and a trajectory — a list of steps, each a tuple (observation, action, reward, terminated, truncated, info) — and returns a float sample. Unless an explicit st_method is given, a suitable statistical method is selected automatically.

Parameters:

Name Type Description Default
name str

Name used when storing results.

required
check_fn Callable[[Property, list[tuple[Any, Any, Any, bool, bool, dict]]], float]

Callable check_fn(property, trajectory) -> float producing one sample per trajectory. trajectory[-1] is the final step; trajectory[-1][2] is the last reward.

required
st_method StatisticalMethod | None

An explicit statistical method. If None, one is selected automatically.

None
epsilon float | None

Half-width of the requested confidence interval (relative if relative_error, otherwise absolute). Pass None for a fixed-run setting without a convergence target.

0.1
kappa float

Error probability; the true mean lies within the CI with prob. 1 - kappa.

0.05
bounds tuple[float | None, float | None]

The property's (min, max) possible values. Required for sound/bounded methods.

(-inf, inf)
min_samples int | None

Minimum number of samples before convergence may be declared.

None
relative_error bool

Whether epsilon is a relative (True) or absolute (False) error.

False
binomial bool

Whether the property is binomial (a 0/1 indicator, e.g. a probability).

False
sound bool

Whether a sound statistical method (guaranteed coverage) must be used.

False
**kwargs Any

Extra attributes stored on the resulting property.

{}

Returns:

Type Description
Property

The configured Property.

Source code in pydsmc/property.py
def create_custom_property(
    name: str,
    check_fn: Callable[[Property, list[tuple[Any, Any, Any, bool, bool, dict]]], float],
    st_method: st.StatisticalMethod | None = None,
    epsilon: float | None = 0.1,
    kappa: float = 0.05,
    bounds: tuple[float | None, float | None] = (-np.inf, np.inf),
    min_samples: int | None = None,
    *,
    relative_error: bool = False,
    binomial: bool = False,
    sound: bool = False,
    **kwargs: Any,
) -> Property:
    """Create a custom property from a user-provided checking function.

    The `check_fn` receives the property instance and a trajectory — a list of steps, each a tuple
    `(observation, action, reward, terminated, truncated, info)` — and returns a `float` sample.
    Unless an explicit `st_method` is given, a suitable statistical method is selected automatically.

    Args:
        name: Name used when storing results.
        check_fn: Callable `check_fn(property, trajectory) -> float` producing one sample per
            trajectory. `trajectory[-1]` is the final step; `trajectory[-1][2]` is the last reward.
        st_method: An explicit statistical method. If `None`, one is selected automatically.
        epsilon: Half-width of the requested confidence interval (relative if `relative_error`,
            otherwise absolute). Pass `None` for a fixed-run setting without a convergence target.
        kappa: Error probability; the true mean lies within the CI with prob. `1 - kappa`.
        bounds: The property's `(min, max)` possible values. Required for sound/bounded methods.
        min_samples: Minimum number of samples before convergence may be declared.
        relative_error: Whether `epsilon` is a relative (`True`) or absolute (`False`) error.
        binomial: Whether the property is binomial (a 0/1 indicator, e.g. a probability).
        sound: Whether a sound statistical method (guaranteed coverage) must be used.
        **kwargs: Extra attributes stored on the resulting property.

    Returns:
        The configured [`Property`][pydsmc.Property].
    """
    # determine which statistical method should be used to compute the confidence interval
    if st_method is None:
        st_method = select_statistical_method(
            epsilon=epsilon,
            kappa=kappa,
            relative_error=relative_error,
            bounds=bounds,
            binomial=binomial,
            min_samples=min_samples,
            sound=sound,
        )
        DSMCLogger.get_logger().debug(
            f"Automatically selected statistical method {st_method.__class__.__name__} for custom property {name}",
        )

    return Property(
        name=name,
        st_method=st_method,
        check_fn=check_fn,
        **kwargs,
    )

get_predefined_properties

get_predefined_properties() -> list[str]

List the IDs of all available predefined properties.

The returned IDs (e.g. "return", "episode_length", "goal_reaching_probability", "truncation", "unsuccesful_termination") can be passed as property_id to create_predefined_property.

Returns:

Type Description
list[str]

The list of predefined property IDs.

Source code in pydsmc/property.py
def get_predefined_properties() -> list[str]:
    """List the IDs of all available predefined properties.

    The returned IDs (e.g. `"return"`, `"episode_length"`,  `"goal_reaching_probability"`,
    `"truncation"`, `"unsuccesful_termination"`) can be passed as `property_id` to
    [`create_predefined_property`][pydsmc.create_predefined_property].

    Returns:
        The list of predefined property IDs.
    """
    return list(__PRE_DEFINED_PROPERTIES.keys())

The Property class

Property

Property(
    name: str,
    st_method: StatisticalMethod,
    check_fn: Callable[
        [
            Property,
            list[tuple[Any, Any, Any, bool, bool, dict]],
        ],
        float,
    ],
    *,
    max_episodes_zero_variance: int = 1000,
    **kwargs,
)

A trajectory-based quantity to estimate, together with its statistical method.

A property maps each trajectory to a single float sample via its check_fn; PyDSMC then estimates the mean of that value with a confidence interval using the associated statistical method. Prefer the factory functions create_predefined_property and create_custom_property over constructing this class directly.

Parameters such as epsilon, kappa, bounds, binomial, and relative_error are exposed as read-only properties that delegate to the underlying statistical method.

Attributes:

Name Type Description
mean float

The mean of the property, estimated from the collected samples.

variance float

The variance of the property, estimated from the collected samples.

std float

The standard deviation of the property, estimated from the collected samples.

num_episodes int

The number of episodes (samples) collected for this property.

epsilon float | None

The properties requested half-width of the confidence interval.

kappa float

The properties confidence level.

binomial bool

Whether the property is binomial (a 0/1 indicator, e.g. a probability).

bounds tuple[float | None, float | None]

The properties bounds, i.e. the minimum and maximum possible values of the property.

relative_error bool

Whether the property uses relative error for its confidence interval.

fallbacked StatisticalMethod | None

If the property has been switched to a fallback statistical method, this is the previous method. Otherwise None. On setup, the property will reset to its original statistical method if it was previously fallbacked.

Source code in pydsmc/property.py
def __init__(
    self,
    name: str,
    st_method: st.StatisticalMethod,
    check_fn: Callable[[Property, list[tuple[Any, Any, Any, bool, bool, dict]]], float],
    *,
    max_episodes_zero_variance: int = 1000,  # TODO: Good default?
    **kwargs,
):
    # Attributes defining the property
    self.name = name
    self.st_method = st_method
    self.fallbacked = None
    # TODO: If we are doing it like this. no need for the s argument in check_fn.
    # 'self' is already available via closure
    self.check_fn = lambda s, t: check_fn(s, [StepWrapper(step) for step in t])
    self.max_episodes_zero_variance = max_episodes_zero_variance

    # Internals
    self.set_property_id()
    self.save_full_results = False
    self.results_lock = threading.Lock()

    # Store all additional keyword arguments as attributes of our new custom property
    for key, value in kwargs.items():
        # Ignore existing attributes, like the ones defined by the st_method (e.g. epsilon, kappa, ...)
        if not hasattr(self, key):
            setattr(self, key, value)

get_interval

get_interval() -> tuple[bool, tuple[float, float] | None]

Get the current confidence interval and whether it has converged.

Returns:

Type Description
tuple[bool, tuple[float, float] | None]

A tuple (converged, interval) where converged is a boolean indicating whether the confidence interval has converged, and interval is a tuple (lower_bound, upper_bound) representing the current confidence interval, or None if no interval can be constructed yet.

Source code in pydsmc/property.py
def get_interval(self) -> tuple[bool, tuple[float, float] | None]:
    """Get the current confidence interval and whether it has converged.

    Returns:
        A tuple `(converged, interval)` where `converged` is a boolean indicating whether the
            confidence interval has converged, and `interval` is a tuple `(lower_bound, upper_bound)`
            representing the current confidence interval, or `None` if no interval can be constructed yet.
    """
    if (
        self.max_episodes_zero_variance > 0
        and self.st_method.count > self.max_episodes_zero_variance
        and self.st_method.mean == 0.0
        and self.st_method.variance == 0.0
    ):
        return True, (0.0, 0.0)

    return self.st_method.get_interval()

get_log_line

get_log_line() -> dict[str, Any]

Get a dictionary containing the current state and information of the property.

This dictionary has the same format as the one saved to results.jsonl.

Returns:

Type Description
dict[str, Any]

A dictionary containing the current state and information of the property (name, property_id, total_episodes, mean, variance, std, confidence_interval, intv_converged).

Source code in pydsmc/property.py
def get_log_line(self) -> dict[str, Any]:
    """Get a dictionary containing the current state and information of the property.

    This dictionary has the same format as the one saved to results.jsonl.

    Returns:
        A dictionary containing the current state and information of the property (`name`, `property_id`, `total_episodes`, `mean`, `variance`, `std`, `confidence_interval`, `intv_converged`).
    """
    results: dict[str, Any] = {}
    results["name"] = self.name
    results["property_id"] = self.property_id
    results["total_episodes"] = self.num_episodes
    results["mean"] = self.mean
    results["variance"] = self.variance
    results["std"] = self.std
    converged, intv = self.get_interval()
    results["confidence_interval"] = intv
    results["intv_converged"] = bool(converged)

    return results