-
Notifications
You must be signed in to change notification settings - Fork 201
/
product.tla
205 lines (181 loc) · 6.73 KB
/
product.tla
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
---------------------------- MODULE product ----------------------------
\* Now that we can cycle properly and also count...
\* let's look at the actual "product" of the process.
\* This requires more variables, for a hi-res view.
EXTENDS Naturals, Sequences \* imports
CONSTANTS DNA, PRIMER \* starting stock of key things
VARIABLES tee,
stage,
cycle,
primer,
(* and single-stranded templates *)
longTemplate,
shortTemplate,
tinyTemplate,
(* and the hybrids *)
longHybrid,
shortHybrid,
tinyHybrid,
(* and double strands *)
longLongDouble,
shortLongDouble,
tinyShortDouble,
(* and the product *)
product \* a tinyTiny double, if you prefer
(* list of state variables *)
vars == <<tee, \* temperature
stage, \* a history, if you think about it
cycle, \* we can count
primer,
(* and single-stranded templates *)
longTemplate,
shortTemplate,
tinyTemplate,
(* and the hybrids *)
longHybrid,
shortHybrid,
tinyHybrid,
(* and doubles *)
longLongDouble,
shortLongDouble,
tinyShortDouble,
(* and the product *)
product
>>
(* more variable lists, for convenience *)
templates == <<longTemplate,
shortTemplate,
tinyTemplate>>
hybrids == <<longHybrid,
shortHybrid,
tinyHybrid>>
doubles == <<longLongDouble,
shortLongDouble,
tinyShortDouble,
product>>
(* helper functions *)
natMin(i,j) == IF i < j THEN i ELSE j \* min of two nats
RECURSIVE sumList(_) \* sum of a list
sumList(s) == IF s = <<>> THEN 0 ELSE Head(s) + sumList(Tail(s))
(* actions *)
heat == /\ tee = "Hot" \* current temperature is "Hot"
/\ tee' = "TooHot" \* heat up to "TooHot"
/\ primer' = primer + sumList(hybrids) \* recover primers from hybrids
(* double strands denature *)
/\ longLongDouble' = 0
/\ shortLongDouble' = 0
/\ tinyShortDouble' = 0
/\ product' = 0
(* hybrids denature *)
/\ longHybrid' = 0
/\ shortHybrid' = 0
/\ tinyHybrid' = 0
(* templates absorb all this*)
/\ longTemplate' = longTemplate + longHybrid + shortLongDouble + 2 * longLongDouble \* only place they come from
/\ shortTemplate' = shortTemplate + shortHybrid + shortLongDouble + tinyShortDouble
/\ tinyTemplate' = tinyTemplate + tinyHybrid + tinyShortDouble + 2 * product
(* stage and cycle*)
/\ (stage = "init" \/ stage = "extended")
/\ stage' = "denatured"
/\ UNCHANGED cycle
cool == /\ tee = "TooHot" \* when you just denatured
/\ tee' = "Hot" \* cool off to "Hot"
/\ stage = "denatured"
/\ stage' = "ready"
/\ UNCHANGED <<cycle, primer>>
/\ UNCHANGED doubles
/\ UNCHANGED templates
/\ UNCHANGED hybrids
anneal == /\ tee = "Hot" \* too hot to anneal primers
/\ tee' = "Warm" \* "Warm" is just right
(* template/primer annealing *)
/\ \E k \in 1..natMin(primer, sumList(templates)) :
/\ primer' = primer - k \* k consumed
(* choose templates to anneal with primer *)
/\ \E tup \in ((0..longTemplate) \X (0..shortTemplate) \X (0..tinyTemplate)):
/\ sumList(tup) = k
/\ longTemplate' = longTemplate - tup[1]
/\ longHybrid' = longHybrid + tup[1]
/\ shortTemplate' = shortTemplate - tup[2]
/\ shortHybrid' = shortHybrid + tup[2]
/\ tinyTemplate' = tinyTemplate - tup[3]
/\ tinyHybrid' = tinyHybrid + tup[3]
/\ stage = "ready"
/\ stage' = "annealed"
/\ UNCHANGED cycle \* dna can reanneal; we neglect that
/\ UNCHANGED doubles
extend == /\ tee = "Warm" \* too cool for extension
/\ tee' = "Hot" \* "Hot" is just right
(* any not annealed remained *)
/\ UNCHANGED primer
/\ UNCHANGED templates
(* update doubles *)
/\ UNCHANGED longLongDouble
/\ shortLongDouble' = shortLongDouble + longHybrid
/\ tinyShortDouble' = tinyShortDouble + shortHybrid
/\ product' = product + tinyHybrid \* the only place you get hybrid from
(* hybrids consumed *)
/\ longHybrid' = 0
/\ shortHybrid' = 0
/\ tinyHybrid' = 0
(* stage and cycle *)
/\ stage = "annealed"
/\ stage' = "extended"
/\ cycle' = cycle + 1 \* only place this changes
(* initial state *)
Init == /\ tee = "Hot" \* not really all that hot
/\ primer = PRIMER \* we have consumed no primers
/\ longLongDouble = DNA \* subtle but important change
(* and single-stranded templates *)
/\ longTemplate = 0
/\ shortTemplate = 0
/\ tinyTemplate = 0
(* and the hybrids *)
/\ longHybrid = 0
/\ shortHybrid = 0
/\ tinyHybrid = 0
(* other doubles *)
/\ shortLongDouble = 0
/\ tinyShortDouble = 0
/\ product = 0
(* stage & cycle *)
/\ stage = "init"
/\ cycle = 0 \* no cycles completed
(* gathering up actions *)
Next == \/ heat
\/ cool
\/ anneal
\/ extend
(* system spec *)
Spec == /\ Init
/\ [][Next]_vars
/\ WF_vars(anneal)
/\ WF_vars(heat)
/\ WF_vars(cool)
/\ WF_vars(extend)
(* type invariant *)
TypeOK ==
/\ tee \in {"Warm", "Hot", "TooHot"}
/\ primer \in Nat
/\ stage \in {"init","ready","annealed","extended","denatured"}
/\ cycle \in Nat
/\ longTemplate \in Nat
/\ shortTemplate \in Nat
/\ tinyTemplate \in Nat
/\ longHybrid \in Nat
/\ shortHybrid \in Nat
/\ tinyHybrid \in Nat
/\ longLongDouble \in Nat
/\ shortLongDouble \in Nat
/\ tinyShortDouble \in Nat
/\ product \in Nat
(* safety *)
thirdCycleProduct == ((cycle < 3) => (product = 0))
(* refinement *)
stagesInstance == INSTANCE stages WITH
template <- sumList(templates),
hybrid <- sumList(hybrids),
dna <- sumList(doubles)
stagesSpec == stagesInstance!Spec
primerDepleted == stagesInstance!primerDepleted
=============================================================================