Degrees of freedom (DOFs)
+++++++++++++++++++++++++
Continuous degrees of freedom
-----------------------------
A degree of freedom is a variable that affects our optimization objective. We can define a simple DOF as
.. code-block:: python
from blop import DOF
dof = DOF(name="x1", description="my first DOF", search_domain=(lower, upper))
This will instantiate a bunch of stuff under the hood, so that our agent knows how to move things and where to search.
Typically, this will correspond to a real, physical device available in Python. In that case, we can pass the DOF an ophyd device in place of a name
.. code-block:: python
from blop import DOF
dof = DOF(device=my_ophyd_device, description="a real piece of hardware", search_domain=(lower, upper))
In this case, the agent will control the device as it sees fit, moving it between the search bounds.
Sometimes, a DOF may be something we can't directly control (e.g. a changing synchrotron current or a changing sample temperature) but want our agent to be aware of.
In this case, we can define a read-only DOF as
.. code-block:: python
from blop import DOF
dof = DOF(device=a_read_only_ophyd_device, description="a thermometer or something", read_only=True, trust_domain=(lower, upper))
and the agent will use the received values to model its objective, but won't try to move it.
We can also pass a set of ``trust_domain``, so that our agent will ignore experiments where the DOF value jumps outside of the interval.
Discrete degrees of freedom
---------------------------
In addition to degrees of freedom that vary continuously between a lower and upper bound, we can define discrete degrees of freedom.
One kind is a binary degree of freedom, where the input can take one of two values, e.g.
.. code-block:: python
discrete_dof = DOF(name="x1", description="A discrete DOF", type="discrete", search_domain={"in", "out"})
Another is an ordinal degree of freedom, which takes more than two discrete values but has some ordering, e.g.
.. code-block:: python
ordinal_dof = DOF(name="x1", description="An ordinal DOF", type="ordinal", search_domain={"low", "medium", "high"})
The last is a categorical degree of freedom, which can take many different discrete values with no ordering, e.g.
.. code-block:: python
categorical_dof = DOF(name="x1", description="A categorical DOF", type="categorical", search_domain={"banana", "mango", "papaya"})