Bioprotocols / labop

Laboratory Open Protocol (LabOP) Language
MIT License
40 stars 11 forks source link

Protocol Constraints #97

Open danbryce opened 2 years ago

danbryce commented 2 years ago

Need to support protocol constraints. First use case is for bounding parameters. @danbryce suggested that we extend the UML Constraint for parameters and to attach the constraints to the precondition of the protocol.

jakebeal commented 2 years ago

I think there are at least two ways to approach this, and in thinking about them I believe that it will be important to distinguish between a constraint and a tolerance in our representations.

The distinction between these, in my thinking, is that a constraint ends up being something that is managed by PAML, whereas a tolerance is something that is managed by the execution environment.

As a driving example, consider two protocols that include a fermentation step where the temperature can be anywhere between 20C and 30C.

The incubate primitive in the plate_handling library currently allows one to specify a temperature (25C) but not the tolerance or range.

Ways that we might express these additional relations:

  1. Constraints: A Behavior (Primitive or Protocol) can have associated precondition and postcondition constraints that can be checked by the execution engine before and after the execution of the Behavior. The postcondition constraint can be used for behavior during execution by looking at records (e.g., "all temperature records must be the the range of 20C - 30C, and there must be a record every 5 minutes"). An execution environment can look at the postcondition in order to modulate its behavior. However, because this is supplied to a Behavior and not a CallBehaviorAction, the same postcondition would have to be applied to all uses of incubate. To supply a specific value, like 20C - 30C, we would need to add a postcondition field to CallBehaviorAction (or a parent class such as Action or even ActivityNode). I'm not comfortable they we understand what all the implications of doing that would be.

  2. Inputs: Alternately, we can enhance the incubate primitive with additional inputs that can be used to express tolerances or ranges. Under this model, the incubate primitive would add an optional temperature_tolerance parameter and/or optional temperature_range parameters. Any execution environment implementing incubate (whether humans or machines) would then need to decide what, if anything, to do with these extra parameters, and we will need to add extra parameters individually to each primitive. We can try to be systematic, but inevitably there will be heterogeneity across primitives in various libraries.

  3. Generalize Measure to allow precision and ranges information: Most places where we'd want to express a range or tolerance are related to parameters with type Measure. While our current usage of Measure has exact values, this class could be extended (either in PAML or in OM) to include an optional notion of precision or range in measure, rather than only being exact values. This would then be consistent across every primitive that uses measurements in its arguments. Execution environments would implement by deciding for each primitive what levels of precision they can or wish to support.

Of these three alternatives, I think the third may be the cleanest.