Example #1
0
def test_process_selectors_numpy_array_invalid_fields(field, np_params_converter):

    with pytest.raises(InvalidConstraintError):
        process_selectors(
            constraints=[{"type": "equality", field: None}],
            params=np.arange(6),
            tree_converter=np_params_converter,
            param_names=list("abcdefg"),
        )
Example #2
0
def test_process_selectors_tree_invalid_fields(
    field, tree_params, tree_params_converter
):
    with pytest.raises(InvalidConstraintError):
        process_selectors(
            constraints=[{"type": "equality", field: None}],
            params=tree_params,
            tree_converter=tree_params_converter,
            param_names=list("abcdefg"),
        )
Example #3
0
def test_process_selectors_differen_length_in_multiple_selectors(np_params_converter):
    constraints = [
        {
            "type": "pairwise_equality",
            "locs": [[1, 4], [0, 3, 5]],
        }
    ]
    with pytest.raises(InvalidConstraintError):
        process_selectors(
            constraints=constraints,
            params=np.arange(6) + 10,
            tree_converter=np_params_converter,
            param_names=list("abcdefg"),
        )
Example #4
0
def test_process_selectors_tree_selector(tree_params, tree_params_converter):
    calculated = process_selectors(
        constraints=[{"type": "equality", "selector": lambda x: x[1]}],
        params=tree_params,
        tree_converter=tree_params_converter,
        param_names=list("abcdefg"),
    )
    aae(calculated[0]["index"], np.array([6]))
Example #5
0
def test_process_selectors_no_constraint(constraints):
    calculated = process_selectors(
        constraints=constraints,
        params=np.arange(5),
        tree_converter=None,
        param_names=list("abcde"),
    )

    assert calculated == []
Example #6
0
def test_process_selectors_numpy_array_loc(np_params_converter):
    calculated = process_selectors(
        constraints=[{"type": "equality", "loc": [1, 4]}],
        params=np.arange(6) + 10,
        tree_converter=np_params_converter,
        param_names=list("abcdefg"),
    )

    aae(calculated[0]["index"], np.array([1, 4]))
Example #7
0
def test_process_selectors_dataframe_loc(df_params, df_params_converter):
    constraints = [{"type": "equality", "loc": ["b", "e"]}]

    calculated = process_selectors(
        constraints=constraints,
        params=df_params,
        tree_converter=df_params_converter,
        param_names=list("abcdefg"),
    )

    aae(calculated[0]["index"], np.array([1, 4]))
Example #8
0
def test_process_selectors_dataframe_locs(df_params, df_params_converter):
    constraints = [{"type": "pairwise_equality", "locs": [["b", "e"], ["a", "d"]]}]

    calculated = process_selectors(
        constraints=constraints,
        params=df_params,
        tree_converter=df_params_converter,
        param_names=list("abcdefg"),
    )

    aae(calculated[0]["indices"][0], np.array([1, 4]))
    aae(calculated[0]["indices"][1], np.array([0, 3]))
Example #9
0
def test_process_selectors_dataframe_query(df_params, df_params_converter):
    q = "name == 'b' | name == 'e'"
    constraints = [{"type": "equality", "query": q}]

    calculated = process_selectors(
        constraints=constraints,
        params=df_params,
        tree_converter=df_params_converter,
        param_names=list("abcdefg"),
    )

    aae(calculated[0]["index"], np.array([1, 4]))
Example #10
0
def test_process_selectors_dataframe_queries(df_params, df_params_converter):
    queries = ["name == 'b' | name == 'e'", "name == 'a' | name == 'd'"]
    constraints = [{"type": "pairwise_equality", "queries": queries}]

    calculated = process_selectors(
        constraints=constraints,
        params=df_params,
        tree_converter=df_params_converter,
        param_names=list("abcdefg"),
    )

    aae(calculated[0]["indices"][0], np.array([1, 4]))
    aae(calculated[0]["indices"][1], np.array([0, 3]))
Example #11
0
def test_process_selectors_tree_selectors(tree_params, tree_params_converter):
    constraints = [
        {
            "type": "pairwise_equality",
            "selectors": [lambda x: x[1], lambda x: x[0][1][0]],
        }
    ]
    calculated = process_selectors(
        constraints=constraints,
        params=tree_params,
        tree_converter=tree_params_converter,
        param_names=list("abcdefg"),
    )
    aae(calculated[0]["indices"][0], np.array([6]))
    aae(calculated[0]["indices"][1], np.array([1]))
Example #12
0
def test_process_selectors_numpy_array_locs(np_params_converter):
    constraints = [
        {
            "type": "pairwise_equality",
            "locs": [[1, 4], [0, 3]],
        }
    ]
    calculated = process_selectors(
        constraints=constraints,
        params=np.arange(6) + 10,
        tree_converter=np_params_converter,
        param_names=list("abcdefg"),
    )

    aae(calculated[0]["indices"][0], np.array([1, 4]))
    aae(calculated[0]["indices"][1], np.array([0, 3]))
def get_converter(
    params,
    constraints,
    lower_bounds,
    upper_bounds,
    func_eval,
    primary_key,
    scaling,
    scaling_options,
    derivative_eval=None,
    soft_lower_bounds=None,
    soft_upper_bounds=None,
    add_soft_bounds=False,
):
    """Get a converter between external and internal params and internal params.

    This combines the following conversions:
    - Flattening parameters provided as pytrees (tree_conversion)
    - Enforcing constraints via reparametrizations (space_conversion)
    - Scaling of the parameter space (scale_conversion)

    The resulting converter can transform parameters, function outputs and derivatives.

    If possible, fast paths for some or all transformations are chosen.

    Args:
        params (pytree): The user provided parameters.
        constraints (list): The user provided constraints.
        lower_bounds (pytree): The user provided lower_bounds
        upper_bounds (pytree): The user provided upper bounds
        func_eval (float, dict or pytree): An evaluation of ``func`` at ``params``.
            Used to deterimine how the function output has to be transformed for the
            optimizer.
        primary_key (str): One of "value", "contributions" and "root_contributions".
            Used to determine how the function and derivative output has to be
            transformed for the optimzer.
        scaling (bool): Whether scaling should be performed.
        scaling_options (dict): User provided scaling options.
        derivative_eval (dict, pytree or None): Evaluation of the derivative of
            func at params. Used for consistency checks.
        soft_lower_bounds (pytree): As lower_bounds
        soft_upper_bounds (pytree): As upper_bounds
        add_soft_bounds (bool): Whether soft bounds should be added to the
            internal_params

    Returns:
        Converter: NamedTuple with methods to convert between internal and external
            parameters, derivatives and function outputs.
        InternalParams: NamedTuple with internal parameter values, lower_bounds and
            upper_bounds.

    """
    fast_path = _is_fast_path(
        params=params,
        constraints=constraints,
        func_eval=func_eval,
        primary_key=primary_key,
        scaling=scaling,
        derivative_eval=derivative_eval,
        add_soft_bounds=add_soft_bounds,
    )
    if fast_path:
        return _get_fast_path_converter(
            params=params,
            lower_bounds=lower_bounds,
            upper_bounds=upper_bounds,
            primary_key=primary_key,
        )

    tree_converter, internal_params = get_tree_converter(
        params=params,
        lower_bounds=lower_bounds,
        upper_bounds=upper_bounds,
        func_eval=func_eval,
        derivative_eval=derivative_eval,
        primary_key=primary_key,
        soft_lower_bounds=soft_lower_bounds,
        soft_upper_bounds=soft_upper_bounds,
        add_soft_bounds=add_soft_bounds,
    )

    flat_constraints = process_selectors(
        constraints=constraints,
        params=params,
        tree_converter=tree_converter,
        param_names=internal_params.names,
    )

    space_converter, internal_params = get_space_converter(
        internal_params=internal_params, internal_constraints=flat_constraints)

    scale_converter, scaled_params = get_scale_converter(
        internal_params=internal_params,
        scaling=scaling,
        scaling_options=scaling_options,
    )

    def _params_to_internal(params):
        x_flat = tree_converter.params_flatten(params)
        x_internal = space_converter.params_to_internal(x_flat)
        x_scaled = scale_converter.params_to_internal(x_internal)
        return x_scaled

    def _params_from_internal(x, return_type="tree"):
        x_unscaled = scale_converter.params_from_internal(x)
        x_external = space_converter.params_from_internal(x_unscaled)

        x_tree = tree_converter.params_unflatten(x_external)
        if return_type == "tree":
            out = x_tree
        elif return_type == "tree_and_flat":
            out = x_tree, x_external
        elif return_type == "flat":
            out = x_external
        else:
            msg = (
                "Invalid return type: {return_type}. Must be one of 'tree', 'flat', "
                "'tree_and_flat'")
            raise ValueError(msg)
        return out

    def _derivative_to_internal(derivative_eval, x, jac_is_flat=False):
        if jac_is_flat:
            jacobian = derivative_eval
        else:
            jacobian = tree_converter.derivative_flatten(derivative_eval)
        x_unscaled = scale_converter.params_from_internal(x)
        jac_with_space_conversion = space_converter.derivative_to_internal(
            jacobian, x_unscaled)
        jac_with_unscaling = scale_converter.derivative_to_internal(
            jac_with_space_conversion)
        return jac_with_unscaling

    def _func_to_internal(func_eval):
        return tree_converter.func_flatten(func_eval)

    internal_params = scaled_params._replace(
        free_mask=internal_params.free_mask)

    converter = Converter(
        params_to_internal=_params_to_internal,
        params_from_internal=_params_from_internal,
        derivative_to_internal=_derivative_to_internal,
        func_to_internal=_func_to_internal,
        has_transforming_constraints=space_converter.
        has_transforming_constraints,
    )

    return converter, internal_params