Skip to content

Commit

Permalink
Merge pull request #235 from UC-Davis-molecular-computing/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
dave-doty authored Jul 23, 2023
2 parents 892dee4 + ed35f23 commit 3a66f82
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 123 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ In more detail, there are five main types of objects you create to describe your
- `Constraint`: There are several kinds of constraint objects. Not all of them are related in the type hierarchy.

- **"hard" constraints on Domain sequences:**
These are the strictest constraints, which do not even allow certain `Domain` sequences to be considered. They are applied by a `DomainPool` before allowing a sequence to be returned from `DomainPool.generate_sequence()`. These are of two types: `NumpyConstraint` and `SequenceConstraint`. Each of them indicates whether a DNA sequence is allowed or not; for instance a constraint forbidding 4 G's in a row would permit AGGGTT but forbid AGGGGT. The difference between them is that a `NumpyConstraint` operates on many DNA sequences at a time, representing them as a 2D numpy byte array (e.g., a 1000 × 15 array of bytes to represent 1000 sequences, each of length 15), and for operations that numpy is suited for, can evaluate these constraints *much* faster than the equivalent Python code that would loop over each sequence individually. However, if you have a constraint that is not straightforward to express using numpy operations, then a `SequenceConstraint` can be used to express it in plain Python. A `SequenceConstraint` is simply a type alias for a Python function that takes a string as input representing the DNA sequence and returns a Boolean indicating whether the sequence satisfies the constraint. Due to the speed of numpy, it is advised to use `SequenceConstraint`'s only if necessary because it cannot be expressed as a `NumpyConstraint`.
These are the strictest constraints, which do not even allow certain `Domain` sequences to be considered, known as "filters". They are applied by a `DomainPool` before allowing a sequence to be returned from `DomainPool.generate_sequence()`, which is the method called whenever the search algorithm wants to try a new DNA sequence for a `Domain`. These are of two types of filters: `NumpyFilter` and `SequenceFilter`. Each of them indicates whether a DNA sequence is allowed or not; for instance a filter forbidding 4 G's in a row would permit AGGGTT but forbid AGGGGT. The difference between them is that a `NumpyFilter` operates on many DNA sequences at a time, representing them as a 2D numpy byte array (e.g., a 1000 × 15 array of bytes to represent 1000 sequences, each of length 15), and for operations that numpy is suited for, can evaluate these filters *much* faster than the equivalent Python code that would loop over each sequence individually. However, if you have a filter that is not straightforward to express using numpy operations, then a `SequenceFilter` can be used to express it in plain Python. A `SequenceFilter` is simply a type alias for a Python function that takes a string as input representing the DNA sequence and returns a Boolean indicating whether the sequence satisfies the filter. Due to the speed of numpy, it is advised to use `SequenceFilter`'s only if necessary because it cannot be expressed as a `NumpyFilter`.

- **"soft" constraints:** All other constraints are subclasses of the abstract superclass `Constraint`. These constrains are "softer": sequences violating the constraints are allowed to be assigned to `Domain`'s. The sequence design algorithm steadily improves the design by changing sequences until all of these constraints are satisfied. The different subtypes of the base class `Constraint` correspond to different parts of the `Design` that are being evaluated by the `Constraint`. The types are:
- **"soft" constraints:** All other constraints are subclasses of the abstract superclass `Constraint`. These constrains are "softer" than filters as described above: sequences violating the constraints are allowed to be assigned to `Domain`'s. The sequence design algorithm steadily improves the design by changing sequences until all of these constraints are satisfied. The different subtypes of the base class `Constraint` correspond to different parts of the `Design` that are being evaluated by the `Constraint`. The types are:

- `SingularConstraint`: This is an abstract superclass of the following concrete subclasses. The difference with the other abstract superclass `BulkConstraint` is explained in `BulkConstraint` below.

Expand Down Expand Up @@ -175,7 +175,7 @@ In more detail, there are five main types of objects you create to describe your

## Constraint evaluations must be pure functions of their inputs

For all constraints, it is critical that the `evaluate` or `evaluate_bulk` functions be *pure* functions of their inputs: the return value should depend only on the parameters passed to the function. For example, a `StrandPairConstraint` takes two strands as input, and its `(excess, summary)` return values should depend *only* on those two strands. Similarly, a `StrandsConstraint`, whose `evaluate_bulk` function takes a list of strands as input, should return a list of tuples, where each tuple represents a violation of a strand that depends only on that strand. This is required because nuad does an optimization in which constraints are only evaluated if they depend on parts of the design that contain the domain(s) that changed in the current iteration.
For all constraints, it is critical that the `evaluate` or `evaluate_bulk` functions be *pure* functions of their inputs: the return value should depend only on the parameters passed to the function. For example, a `StrandPairConstraint` takes two strands as input, and its `Result` return values should depend *only* on those two strands. Similarly, a `StrandsConstraint`, whose `evaluate_bulk` function takes a list of strands as input, should return a list of tuples, where each tuple represents a violation of a strand that depends only on that strand. This is required because nuad does an optimization in which constraints are only evaluated if they depend on parts of the design that contain the domain(s) that changed in the current iteration.

For example, suppose there are 100 strands, but only 3 strands contain the domain `x`, and `x` is the domain whose DNA sequence is changed in the current search iteration. Then each `StrandConstraint` `s` will be evaluated only on those 3 strands, on the assumption that the other 97 strands would have the same output of the function `s.evaluate` as before.

Expand Down
24 changes: 17 additions & 7 deletions notebooks/Untitled.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,33 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 20,
"id": "cf3567b8-b41b-4ce0-aa83-f8cbd4dd45b3",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"(0.796078431372549, 0.3764705882352941, 0.08235294117647059)"
"<Figure size 1296x576 with 1 Axes>"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"(203/255, 96/255, 21/255)"
"import nuad.np as nn\n",
"import matplotlib.pyplot as plt\n",
"\n",
"s = nn.DNASeqList(length=21, num_random_seqs=10**5)\n",
"energies = s.energies(37)\n",
"# print(f'{min(energies)=}')\n",
"# print(f'{max(energies)=}')\n",
"plt.figure(figsize=(18,8))\n",
"_ = plt.hist(energies, bins=20)"
]
},
{
Expand Down Expand Up @@ -82,7 +92,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
"version": "3.8.16"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion nuad/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version = '0.4.2' # version line; WARNING: do not remove or change this line or comment
version = '0.4.3' # version line; WARNING: do not remove or change this line or comment
Loading

0 comments on commit 3a66f82

Please sign in to comment.