Example #1
0
def _reduce_matrix(
    model: Model,
    label: str,
    parameters: ParameterGroup,
    result: LabelAndMatrix,
    index: float,
) -> LabelAndMatrix:
    clp_labels = result.clp_label.copy()
    if callable(model.has_matrix_constraints_function) and model.has_matrix_constraints_function():
        clp_label, matrix = model.constrain_matrix_function(
            label, parameters, clp_labels, result.matrix, index
        )
        return LabelAndMatrix(clp_label, matrix)
    return LabelAndMatrix(clp_labels, result.matrix)
def simulate(
    model: Model,
    dataset: str,
    parameters: ParameterGroup,
    axes: Dict[str, np.ndarray] = None,
    clp: Union[np.ndarray, xr.DataArray] = None,
    noise=False,
    noise_std_dev=1.0,
    noise_seed=None,
):
    """Simulates a model.

    Parameters
    ----------
    model :
        The model to simulate.
    parameter :
        The parameters for the simulation.
    dataset :
        Label of the dataset to simulate
    axes :
        A dictionary with axes for simulation.
    clp :
        Conditionally linear parameters. Will be used instead of `model.global_matrix` if given.
    noise :
        Add noise to the simulation.
    noise_std_dev :
        The standard deviation for noise simulation.
    noise_seed :
        The seed for the noise simulation.
    """

    if model.global_matrix is None and clp is None:
        raise ValueError(
            "Cannot simulate models without implementation for global matrix and no clp given."
        )

    filled_dataset = model.dataset[dataset].fill(model, parameters)

    model_dimension = axes[model.model_dimension]
    global_dimension = axes[model.global_dimension]

    dim1 = model_dimension.size
    dim2 = global_dimension.size
    result = xr.DataArray(
        np.empty((dim1, dim2), dtype=np.float64),
        coords=[
            (model.model_dimension, model_dimension),
            (model.global_dimension, global_dimension),
        ],
    )
    result = result.to_dataset(name="data")

    matrix = ([
        model.matrix(dataset_descriptor=filled_dataset,
                     axis=model_dimension,
                     index=index) for index in global_dimension
    ] if model.index_dependent() else model.matrix(
        dataset_descriptor=filled_dataset, axis=model_dimension, index=None))
    if callable(model.constrain_matrix_function):
        matrix = ([
            model.constrain_matrix_function(dataset, parameters, clp, mat,
                                            global_dimension[i])
            for i, (clp, mat) in enumerate(matrix)
        ] if model.index_dependent() else model.constrain_matrix_function(
            dataset, parameters, matrix[0], matrix[1], None))
    matrix = ([
        xr.DataArray(mat,
                     coords=[(model.model_dimension, model_dimension),
                             ("clp_label", clp_label)])
        for clp_label, mat in matrix
    ] if model.index_dependent() else xr.DataArray(
        matrix[1],
        coords=[(model.model_dimension, model_dimension),
                ("clp_label", matrix[0])]))

    if clp is not None:
        if clp.shape[0] != global_dimension.size:
            raise ValueError(
                f"Size of dimension 0 of clp ({clp.shape[0]}) != size of axis"
                f" '{model.global_dimension}' ({global_dimension.size})")
        if isinstance(clp, xr.DataArray):
            if model.global_dimension not in clp.coords:
                raise ValueError(
                    f"Missing coordinate '{model.global_dimension}' in clp.")
            if "clp_label" not in clp.coords:
                raise ValueError("Missing coordinate 'clp_label' in clp.")
        else:
            if "clp_label" not in axes:
                raise ValueError("Missing axis 'clp_label'")
            clp = xr.DataArray(
                clp,
                coords=[
                    (model.global_dimension, global_dimension),
                    ("clp_label", axes["clp_label"]),
                ],
            )
    else:
        clp_labels, clp = model.global_matrix(filled_dataset, global_dimension)
        clp = xr.DataArray(clp,
                           coords=[(model.global_dimension, global_dimension),
                                   ("clp_label", clp_labels)])
    for i in range(dim2):
        index_matrix = matrix[i] if model.index_dependent() else matrix
        result.data[:, i] = np.dot(
            index_matrix,
            clp[i].sel(clp_label=index_matrix.coords["clp_label"]))

    if noise:
        if noise_seed is not None:
            np.random.seed(noise_seed)
        result["data"] = (
            (model.model_dimension, model.global_dimension),
            np.random.normal(result.data, noise_std_dev),
        )

    return result