Constraints

Constraints are a fundamental component in non-trivial fitting operations. They can also be used to affirm the minimum/maximum of a parameter or tie parameters together in a model.

Anatomy of a constraint

A constraint is a rule which is applied to a dependent variable. This rule can consist of a logical operation, relation to one or more independent variables or an arbitrary function.

Constraints on Parameters

easyCore.Objects.Base.Parameter has the properties builtin_constraints and user_constraints. These are dictionaries which correspond to constraints which are intrinsic and extrinsic to the Parameter. This means that on the value change of the Parameter firstly the builtin_constraints are evaluated, followed by the user_constraints.

Constraints on Fitting

easyCore.Fitting.Fitting.Fitter has the ability to evaluate user supplied constraints which effect the value of both fixed and non-fixed parameters. A good example of one such use case would be the ratio between two parameters, where you would create a easyCore.Fitting.Constraints.ObjConstraint.

Using constraints

A constraint can be used in one of three ways; Assignment to a parameter, assignment to fitting or on demand. The first two are covered and on demand is shown below.

from easyCore.Fitting.Constraints import NumericConstraint
from easyCore.Objects.Base import Parameter
# Create an `a < 1` constraint
a = Parameter('a', 0.5)
constraint = NumericConstraint(a, '<=', 1)
# Evaluate the constraint on demand
a.value = 5.0
constraint()
# A will now equal 1

Constraint Reference

Examples using Constraints

Constraints example

Constraints example

Built-in constraints

These are the built in constraints which you can use

class easyCore.Fitting.Constraints.SelfConstraint(dependent_obj, operator, value)[source]

A SelfConstraint is a constraint which tests a logical constraint on a property of itself, similar to a NumericConstraint. i.e. a > a.min.

Parameters:
  • dependent_obj (TypeVar(V, bound= Descriptor)) – Dependent Parameter

  • operator (str) – Relation to between the parameter and the values. e.g. =, <, >

  • value (str) – Name of attribute to be compared against

Example:

from easyCore.Fitting.Constraints import SelfConstraint
from easyCore.Objects.Base import Parameter
# Create an `a < a.max` constraint
a = Parameter('a', 0.2, max=1)
constraint = SelfConstraint(a, '<=', 'max')
a.user_constraints['MAX'] = constraint
# This works
a.value = 0.85
# This triggers the constraint
a.value = 2.0
# `a` is set to the maximum of the constraint (`a = 1`)
property enabled: bool

Is the current constraint enabled.

Return type:

bool

Returns:

Logical answer to if the constraint is enabled.

class easyCore.Fitting.Constraints.NumericConstraint(dependent_obj, operator, value)[source]

A NumericConstraint is a constraint whereby a dependent parameters value is something of an independent parameters value. I.e. a < 1, a > 5

Parameters:
  • dependent_obj (TypeVar(V, bound= Descriptor)) – Dependent Parameter

  • operator (str) – Relation to between the parameter and the values. e.g. =, <, >

  • value (Number) – What the parameters value should be compared against.

Example:

from easyCore.Fitting.Constraints import NumericConstraint
from easyCore.Objects.Base import Parameter
# Create an `a < 1` constraint
a = Parameter('a', 0.2)
constraint = NumericConstraint(a, '<=', 1)
a.user_constraints['LEQ_1'] = constraint
# This works
a.value = 0.85
# This triggers the constraint
a.value = 2.0
# `a` is set to the maximum of the constraint (`a = 1`)
property enabled: bool

Is the current constraint enabled.

Return type:

bool

Returns:

Logical answer to if the constraint is enabled.

class easyCore.Fitting.Constraints.ObjConstraint(dependent_obj, operator, independent_obj)[source]

A ObjConstraint is a constraint whereby a dependent parameter is something of an independent parameter value. E.g. a (Dependent Parameter) < b (Independent Parameter)

Parameters:
  • dependent_obj (TypeVar(V, bound= Descriptor)) – Dependent Parameter

  • operator (str) – Relation to between the independent parameter and dependent parameter. e.g. 2 *, 1 +

  • independent_obj (TypeVar(V, bound= Descriptor)) – Independent Parameter

Example:

from easyCore.Fitting.Constraints import ObjConstraint
from easyCore.Objects.Base import Parameter
# Create an `a = 2 * b` constraint
a = Parameter('a', 0.2)
b = Parameter('b', 1)

constraint = ObjConstraint(a, '2*', b)
b.user_constraints['SET_A'] = constraint
b.value = 1
# This triggers the constraint
a.value # Should equal 2
property enabled: bool

Is the current constraint enabled.

Return type:

bool

Returns:

Logical answer to if the constraint is enabled.

class easyCore.Fitting.Constraints.FunctionalConstraint(dependent_obj, func, independent_objs=None)[source]

Functional constraints do not depend on other parameters and as such can be more complex.

Parameters:
  • dependent_obj (TypeVar(V, bound= Descriptor)) – Dependent Parameter

  • func (Callable) – Function to be evaluated in the form f(value, *args, **kwargs)

Example:

import numpy as np
from easyCore.Fitting.Constraints import FunctionalConstraint
from easyCore.Objects.Base import Parameter

a = Parameter('a', 0.2, max=1)
constraint = FunctionalConstraint(a, np.abs)

a.user_constraints['abs'] = constraint

# This triggers the constraint
a.value = 0.85 # `a` is set to 0.85
# This triggers the constraint
a.value = -0.5 # `a` is set to 0.5
property enabled: bool

Is the current constraint enabled.

Return type:

bool

Returns:

Logical answer to if the constraint is enabled.

class easyCore.Fitting.Constraints.MultiObjConstraint(independent_objs, operator, dependent_obj, value)[source]

A MultiObjConstraint is similar to easyCore.Fitting.Constraints.ObjConstraint except that it relates to one or more independent objects.

E.g. * a (Dependent Parameter) + b (Independent Parameter) = 1 * a (Dependent Parameter) + b (Independent Parameter) - 2*c (Independent Parameter) = 0

Parameters:
  • independent_objs (List[TypeVar(V, bound= Descriptor)]) – List of Independent Parameters

  • operator (List[str]) – List of operators operating on the Independent Parameters

  • dependent_obj (TypeVar(V, bound= Descriptor)) – Dependent Parameter

  • value (Number) – Value of the expression

Example:

a + b = 1

from easyCore.Fitting.Constraints import MultiObjConstraint
from easyCore.Objects.Base import Parameter
# Create an `a + b = 1` constraint
a = Parameter('a', 0.2)
b = Parameter('b', 0.3)

constraint = MultiObjConstraint([b], ['+'], a, 1)
b.user_constraints['SET_A'] = constraint
b.value = 0.4
# This triggers the constraint
a.value # Should equal 0.6

a + b - 2c = 0

from easyCore.Fitting.Constraints import MultiObjConstraint
from easyCore.Objects.Base import Parameter
# Create an `a + b - 2c = 0` constraint
a = Parameter('a', 0.5)
b = Parameter('b', 0.3)
c = Parameter('c', 0.1)

constraint = MultiObjConstraint([b, c], ['+', '-2*'], a, 0)
b.user_constraints['SET_A'] = constraint
c.user_constraints['SET_A'] = constraint
b.value = 0.4
# This triggers the constraint. Or it could be triggered by changing the value of c
a.value # Should equal 0.2

Note

This constraint is evaluated as dependent = value - SUM(operator_i independent_i)

property enabled: bool

Is the current constraint enabled.

Return type:

bool

Returns:

Logical answer to if the constraint is enabled.

User created constraints

You can also make your own constraints by subclassing the easyCore.Fitting.Constraints.ConstraintBase class. For this at a minimum the abstract methods _parse_operator and __repr__ need to be written.

class easyCore.Fitting.Constraints.ConstraintBase(dependent_obj, independent_obj=None, operator=None, value=None)[source]

A base class used to describe a constraint to be applied to easyCore base objects.

abstract __repr__()[source]

Return repr(self).

abstract _parse_operator(obj, *args, **kwargs)[source]

Abstract method which contains the constraint logic

Parameters:

obj (TypeVar(V, bound= Descriptor)) – The object/objects which the constraint will use

Return type:

Number

Returns:

A numeric result of the constraint logic

property enabled: bool

Is the current constraint enabled.

Return type:

bool

Returns:

Logical answer to if the constraint is enabled.

get_key(obj)[source]

Get the unique key of a easyCore object

Parameters:

obj – easyCore object

Return type:

int

Returns:

key for easyCore object

get_obj(key)[source]

Get an easyCore object from its unique key

Parameters:

key (int) – an easyCore objects unique key

Return type:

TypeVar(V, bound= Descriptor)

Returns:

easyCore object