@@ -17,49 +17,51 @@ type internal AISearcher(oracle: Oracle, aiAgentTrainingOptions: Option<AIAgentT
17
17
| None -> 0 u< step>
18
18
| Some options -> options.stepsToPlay
19
19
20
- let mutable lastCollectedStatistics =
21
- Statistics ()
20
+ let mutable lastCollectedStatistics = Statistics()
22
21
let mutable defaultSearcherSteps = 0 u< step>
23
- let mutable ( gameState : Option < GameState >) =
24
- None
25
- let mutable useDefaultSearcher =
26
- stepsToSwitchToAI > 0 u< step>
22
+ let mutable ( gameState : Option < GameState >) = None
23
+ let mutable useDefaultSearcher = stepsToSwitchToAI > 0 u< step>
27
24
let mutable afterFirstAIPeek = false
28
- let mutable incorrectPredictedStateId =
29
- false
25
+ let mutable incorrectPredictedStateId = false
26
+
30
27
let defaultSearcher =
31
28
match aiAgentTrainingOptions with
32
- | None -> BFSSearcher () :> IForwardSearcher
29
+ | None -> BFSSearcher() :> IForwardSearcher
33
30
| Some options ->
34
31
match options.defaultSearchStrategy with
35
- | BFSMode -> BFSSearcher () :> IForwardSearcher
36
- | DFSMode -> DFSSearcher () :> IForwardSearcher
32
+ | BFSMode -> BFSSearcher() :> IForwardSearcher
33
+ | DFSMode -> DFSSearcher() :> IForwardSearcher
37
34
| x -> failwithf $" Unexpected default searcher {x}. DFS and BFS supported for now."
35
+
38
36
let mutable stepsPlayed = 0 u< step>
37
+
39
38
let isInAIMode () =
40
39
( not useDefaultSearcher) && afterFirstAIPeek
41
- let q = ResizeArray<_> ()
42
- let availableStates = HashSet<_> ()
40
+
41
+ let q = ResizeArray<_>()
42
+ let availableStates = HashSet<_>()
43
+
43
44
let updateGameState ( delta : GameState ) =
44
45
match gameState with
45
46
| None -> gameState <- Some delta
46
47
| Some s ->
47
- let updatedBasicBlocks =
48
- delta.GraphVertices |> Array.map ( fun b -> b.Id) |> HashSet
49
- let updatedStates =
50
- delta.States |> Array.map ( fun s -> s.Id) |> HashSet
48
+ let updatedBasicBlocks = delta.GraphVertices |> Array.map ( fun b -> b.Id) |> HashSet
49
+ let updatedStates = delta.States |> Array.map ( fun s -> s.Id) |> HashSet
50
+
51
51
let vertices =
52
52
s.GraphVertices
53
53
|> Array.filter ( fun v -> updatedBasicBlocks.Contains v.Id |> not )
54
54
|> ResizeArray<_>
55
+
55
56
vertices.AddRange delta.GraphVertices
57
+
56
58
let edges =
57
59
s.Map
58
60
|> Array.filter ( fun e -> updatedBasicBlocks.Contains e.VertexFrom |> not )
59
61
|> ResizeArray<_>
62
+
60
63
edges.AddRange delta.Map
61
- let activeStates =
62
- vertices |> Seq.collect ( fun v -> v.States) |> HashSet
64
+ let activeStates = vertices |> Seq.collect ( fun v -> v.States) |> HashSet
63
65
64
66
let states =
65
67
let part1 =
@@ -69,82 +71,93 @@ type internal AISearcher(oracle: Oracle, aiAgentTrainingOptions: Option<AIAgentT
69
71
70
72
part1.AddRange delta.States
71
73
72
- part1.ToArray ()
74
+ part1.ToArray()
73
75
|> Array.map ( fun s ->
74
- State (
76
+ State(
75
77
s.Id,
76
78
s.Position,
77
- s.PathConditionSize ,
79
+ s.PathCondition ,
78
80
s.VisitedAgainVertices,
79
81
s.VisitedNotCoveredVerticesInZone,
80
82
s.VisitedNotCoveredVerticesOutOfZone,
81
83
s.StepWhenMovedLastTime,
82
84
s.InstructionsVisitedInCurrentBlock,
83
85
s.History,
84
86
s.Children |> Array.filter activeStates.Contains
85
- )
86
- )
87
+ ))
88
+
89
+ let pathConditionVertices =
90
+ ResizeArray< PathConditionVertex> s.PathConditionVertices
91
+
92
+ pathConditionVertices.AddRange delta.PathConditionVertices
87
93
88
- gameState <- Some <| GameState ( vertices.ToArray (), states, edges.ToArray ())
94
+ gameState <-
95
+ Some
96
+ <| GameState( vertices.ToArray(), states, pathConditionVertices.ToArray(), edges.ToArray())
89
97
90
98
91
99
let init states =
92
100
q.AddRange states
93
101
defaultSearcher.Init q
94
102
states |> Seq.iter ( availableStates.Add >> ignore)
103
+
95
104
let reset () =
96
- defaultSearcher.Reset ()
105
+ defaultSearcher.Reset()
97
106
defaultSearcherSteps <- 0 u< step>
98
- lastCollectedStatistics <- Statistics ()
107
+ lastCollectedStatistics <- Statistics()
99
108
gameState <- None
100
109
afterFirstAIPeek <- false
101
110
incorrectPredictedStateId <- false
102
111
useDefaultSearcher <- stepsToSwitchToAI > 0 u< step>
103
- q.Clear ()
104
- availableStates.Clear ()
105
- let update ( parent , newSates ) =
112
+ q.Clear()
113
+ availableStates.Clear()
114
+
115
+ let update ( parent , newStates ) =
106
116
if useDefaultSearcher then
107
- defaultSearcher.Update ( parent, newSates)
108
- newSates |> Seq.iter ( availableStates.Add >> ignore)
117
+ defaultSearcher.Update( parent, newStates)
118
+
119
+ newStates |> Seq.iter ( availableStates.Add >> ignore)
120
+
109
121
let remove state =
110
122
if useDefaultSearcher then
111
123
defaultSearcher.Remove state
124
+
112
125
let removed = availableStates.Remove state
113
126
assert removed
127
+
114
128
for bb in state._ history do
115
129
bb.Key.AssociatedStates.Remove state |> ignore
116
130
117
- let inTrainMode =
118
- aiAgentTrainingOptions.IsSome
131
+ let inTrainMode = aiAgentTrainingOptions.IsSome
119
132
120
133
let pick selector =
121
134
if useDefaultSearcher then
122
135
defaultSearcherSteps <- defaultSearcherSteps + 1 u< step>
136
+
123
137
if Seq.length availableStates > 0 then
124
- let gameStateDelta =
125
- collectGameStateDelta ()
138
+ let gameStateDelta = collectGameStateDelta ()
126
139
updateGameState gameStateDelta
127
- let statistics =
128
- computeStatistics gameState.Value
129
- Application.applicationGraphDelta.Clear ()
140
+ let statistics = computeStatistics gameState.Value
141
+ Application.applicationGraphDelta.Clear()
130
142
lastCollectedStatistics <- statistics
131
143
useDefaultSearcher <- defaultSearcherSteps < stepsToSwitchToAI
132
- defaultSearcher.Pick ()
144
+
145
+ defaultSearcher.Pick()
133
146
elif Seq.length availableStates = 0 then
134
147
None
135
148
elif Seq.length availableStates = 1 then
136
- Some ( Seq.head availableStates)
149
+ Some( Seq.head availableStates)
137
150
else
138
- let gameStateDelta =
139
- collectGameStateDelta ()
151
+ let gameStateDelta = collectGameStateDelta ()
140
152
updateGameState gameStateDelta
141
- let statistics =
142
- computeStatistics gameState.Value
153
+ let statistics = computeStatistics gameState.Value
154
+
143
155
if isInAIMode () then
144
- let reward =
145
- computeReward lastCollectedStatistics statistics
146
- oracle.Feedback ( Feedback.MoveReward reward)
147
- Application.applicationGraphDelta.Clear ()
156
+ let reward = computeReward lastCollectedStatistics statistics
157
+ oracle.Feedback( Feedback.MoveReward reward)
158
+
159
+ Application.applicationGraphDelta.Clear()
160
+
148
161
if inTrainMode && stepsToPlay = stepsPlayed then
149
162
None
150
163
else
@@ -153,17 +166,18 @@ type internal AISearcher(oracle: Oracle, aiAgentTrainingOptions: Option<AIAgentT
153
166
gameStateDelta
154
167
else
155
168
gameState.Value
169
+
156
170
let stateId = oracle.Predict toPredict
157
171
afterFirstAIPeek <- true
158
- let state =
159
- availableStates |> Seq.tryFind ( fun s -> s.internalId = stateId)
172
+ let state = availableStates |> Seq.tryFind ( fun s -> s.internalId = stateId)
160
173
lastCollectedStatistics <- statistics
161
174
stepsPlayed <- stepsPlayed + 1 u< step>
175
+
162
176
match state with
163
177
| Some state -> Some state
164
178
| None ->
165
179
incorrectPredictedStateId <- true
166
- oracle.Feedback ( Feedback.IncorrectPredictedStateId stateId)
180
+ oracle.Feedback( Feedback.IncorrectPredictedStateId stateId)
167
181
None
168
182
169
183
new ( pathToONNX: string, useGPU: bool, optimize: bool) =
@@ -174,40 +188,36 @@ type internal AISearcher(oracle: Oracle, aiAgentTrainingOptions: Option<AIAgentT
174
188
let createOracle ( pathToONNX : string ) =
175
189
let sessionOptions =
176
190
if useGPU then
177
- SessionOptions.MakeSessionOptionWithCudaProvider ( 0 )
191
+ SessionOptions.MakeSessionOptionWithCudaProvider( 0 )
178
192
else
179
- new SessionOptions ()
193
+ new SessionOptions()
180
194
181
195
if optimize then
182
196
sessionOptions.ExecutionMode <- ExecutionMode.ORT_ PARALLEL
183
197
sessionOptions.GraphOptimizationLevel <- GraphOptimizationLevel.ORT_ ENABLE_ ALL
184
198
else
185
199
sessionOptions.GraphOptimizationLevel <- GraphOptimizationLevel.ORT_ ENABLE_ BASIC
186
200
187
- let session =
188
- new InferenceSession ( pathToONNX, sessionOptions)
189
- let runOptions = new RunOptions ()
201
+ let session = new InferenceSession( pathToONNX, sessionOptions)
202
+ let runOptions = new RunOptions()
190
203
let feedback ( x : Feedback ) = ()
191
204
192
205
let predict ( gameState : GameState ) =
193
- let stateIds =
194
- Dictionary< uint< stateId>, int> ()
195
- let verticesIds =
196
- Dictionary< uint< basicBlockGlobalId>, int> ()
206
+ let stateIds = Dictionary< uint< stateId>, int>()
207
+ let verticesIds = Dictionary< uint< basicBlockGlobalId>, int>()
197
208
198
209
let networkInput =
199
- let res = Dictionary<_, _> ()
210
+ let res = Dictionary<_, _>()
211
+
200
212
let gameVertices =
201
- let shape =
202
- [|
203
- int64 gameState.GraphVertices.Length
204
- numOfVertexAttributes
205
- |]
213
+ let shape = [| int64 gameState.GraphVertices.Length; numOfVertexAttributes |]
214
+
206
215
let attributes =
207
216
Array.zeroCreate ( gameState.GraphVertices.Length * numOfVertexAttributes)
217
+
208
218
for i in 0 .. gameState.GraphVertices.Length - 1 do
209
219
let v = gameState.GraphVertices.[ i]
210
- verticesIds.Add ( v.Id, i)
220
+ verticesIds.Add( v.Id, i)
211
221
let j = i * numOfVertexAttributes
212
222
attributes.[ j] <- float32 <| if v.InCoverageZone then 1 u else 0 u
213
223
attributes.[ j + 1 ] <- float32 <| v.BasicBlockSize
@@ -216,111 +226,97 @@ type internal AISearcher(oracle: Oracle, aiAgentTrainingOptions: Option<AIAgentT
216
226
attributes.[ j + 4 ] <- float32 <| if v.TouchedByState then 1 u else 0 u
217
227
attributes.[ j + 5 ] <- float32 <| if v.ContainsCall then 1 u else 0 u
218
228
attributes.[ j + 6 ] <- float32 <| if v.ContainsThrow then 1 u else 0 u
219
- OrtValue.CreateTensorValueFromMemory ( attributes, shape)
229
+
230
+ OrtValue.CreateTensorValueFromMemory( attributes, shape)
220
231
221
232
let states , numOfParentOfEdges , numOfHistoryEdges =
222
233
let mutable numOfParentOfEdges = 0
223
234
let mutable numOfHistoryEdges = 0
224
- let shape =
225
- [|
226
- int64 gameState.States.Length
227
- numOfStateAttributes
228
- |]
229
- let attributes =
230
- Array.zeroCreate ( gameState.States.Length * numOfStateAttributes)
235
+ let shape = [| int64 gameState.States.Length; numOfStateAttributes |]
236
+ let attributes = Array.zeroCreate ( gameState.States.Length * numOfStateAttributes)
237
+
231
238
for i in 0 .. gameState.States.Length - 1 do
232
239
let v = gameState.States.[ i]
233
240
numOfHistoryEdges <- numOfHistoryEdges + v.History.Length
234
241
numOfParentOfEdges <- numOfParentOfEdges + v.Children.Length
235
- stateIds.Add ( v.Id, i)
242
+ stateIds.Add( v.Id, i)
236
243
let j = i * numOfStateAttributes
237
244
attributes.[ j] <- float32 v.Position
238
- attributes.[ j + 1 ] <- float32 v.PathConditionSize
245
+ // TODO: Support path condition
246
+ // attributes.[j + 1] <- float32 v.PathConditionSize
239
247
attributes.[ j + 2 ] <- float32 v.VisitedAgainVertices
240
248
attributes.[ j + 3 ] <- float32 v.VisitedNotCoveredVerticesInZone
241
249
attributes.[ j + 4 ] <- float32 v.VisitedNotCoveredVerticesOutOfZone
242
250
attributes.[ j + 5 ] <- float32 v.StepWhenMovedLastTime
243
251
attributes.[ j + 6 ] <- float32 v.InstructionsVisitedInCurrentBlock
244
- OrtValue.CreateTensorValueFromMemory ( attributes, shape), numOfParentOfEdges, numOfHistoryEdges
252
+
253
+ OrtValue.CreateTensorValueFromMemory( attributes, shape), numOfParentOfEdges, numOfHistoryEdges
245
254
246
255
let vertexToVertexEdgesIndex , vertexToVertexEdgesAttributes =
247
- let shapeOfIndex =
248
- [| 2 L ; gameState.Map.Length |]
249
- let shapeOfAttributes =
250
- [| int64 gameState.Map.Length |]
251
- let index =
252
- Array.zeroCreate ( 2 * gameState.Map.Length)
253
- let attributes =
254
- Array.zeroCreate gameState.Map.Length
256
+ let shapeOfIndex = [| 2 L; gameState.Map.Length |]
257
+ let shapeOfAttributes = [| int64 gameState.Map.Length |]
258
+ let index = Array.zeroCreate ( 2 * gameState.Map.Length)
259
+ let attributes = Array.zeroCreate gameState.Map.Length
260
+
255
261
gameState.Map
256
262
|> Array.iteri ( fun i e ->
257
263
index[ i] <- int64 verticesIds[ e.VertexFrom]
258
264
index[ gameState.Map.Length + i] <- int64 verticesIds[ e.VertexTo]
259
- attributes[ i] <- int64 e.Label.Token
260
- )
265
+ attributes[ i] <- int64 e.Label.Token)
261
266
262
- OrtValue.CreateTensorValueFromMemory ( index, shapeOfIndex),
263
- OrtValue.CreateTensorValueFromMemory ( attributes, shapeOfAttributes)
267
+ OrtValue.CreateTensorValueFromMemory( index, shapeOfIndex),
268
+ OrtValue.CreateTensorValueFromMemory( attributes, shapeOfAttributes)
264
269
265
270
let historyEdgesIndex_vertexToState , historyEdgesAttributes , parentOfEdges =
266
- let shapeOfParentOf =
267
- [| 2 L ; numOfParentOfEdges |]
268
- let parentOf =
269
- Array.zeroCreate ( 2 * numOfParentOfEdges)
270
- let shapeOfHistory =
271
- [| 2 L ; numOfHistoryEdges |]
272
- let historyIndex_vertexToState =
273
- Array.zeroCreate ( 2 * numOfHistoryEdges)
271
+ let shapeOfParentOf = [| 2 L; numOfParentOfEdges |]
272
+ let parentOf = Array.zeroCreate ( 2 * numOfParentOfEdges)
273
+ let shapeOfHistory = [| 2 L; numOfHistoryEdges |]
274
+ let historyIndex_vertexToState = Array.zeroCreate ( 2 * numOfHistoryEdges)
275
+
274
276
let shapeOfHistoryAttributes =
275
- [|
276
- int64 numOfHistoryEdges
277
- int64 numOfHistoryEdgeAttributes
278
- |]
279
- let historyAttributes =
280
- Array.zeroCreate ( 2 * numOfHistoryEdges)
277
+ [| int64 numOfHistoryEdges; int64 numOfHistoryEdgeAttributes |]
278
+
279
+ let historyAttributes = Array.zeroCreate ( 2 * numOfHistoryEdges)
281
280
let mutable firstFreePositionInParentsOf = 0
282
- let mutable firstFreePositionInHistoryIndex =
283
- 0
284
- let mutable firstFreePositionInHistoryAttributes =
285
- 0
281
+ let mutable firstFreePositionInHistoryIndex = 0
282
+ let mutable firstFreePositionInHistoryAttributes = 0
283
+
286
284
gameState.States
287
285
|> Array.iter ( fun state ->
288
286
state.Children
289
287
|> Array.iteri ( fun i children ->
290
288
let j = firstFreePositionInParentsOf + i
291
289
parentOf[ j] <- int64 stateIds[ state.Id]
292
- parentOf[ numOfParentOfEdges + j] <- int64 stateIds[ children]
293
- )
290
+ parentOf[ numOfParentOfEdges + j] <- int64 stateIds[ children])
291
+
294
292
firstFreePositionInParentsOf <- firstFreePositionInParentsOf + state.Children.Length
293
+
295
294
state.History
296
295
|> Array.iteri ( fun i historyElem ->
297
296
let j = firstFreePositionInHistoryIndex + i
298
297
historyIndex_ vertexToState[ j] <- int64 verticesIds[ historyElem.GraphVertexId]
299
298
historyIndex_ vertexToState[ numOfHistoryEdges + j] <- int64 stateIds[ state.Id]
300
299
301
- let j =
302
- firstFreePositionInHistoryAttributes + numOfHistoryEdgeAttributes * i
300
+ let j = firstFreePositionInHistoryAttributes + numOfHistoryEdgeAttributes * i
303
301
historyAttributes[ j] <- int64 historyElem.NumOfVisits
304
- historyAttributes[ j + 1 ] <- int64 historyElem.StepWhenVisitedLastTime
305
- )
302
+ historyAttributes[ j + 1 ] <- int64 historyElem.StepWhenVisitedLastTime)
303
+
306
304
firstFreePositionInHistoryIndex <- firstFreePositionInHistoryIndex + state.History.Length
305
+
307
306
firstFreePositionInHistoryAttributes <-
308
307
firstFreePositionInHistoryAttributes
309
- + numOfHistoryEdgeAttributes * state.History.Length
310
- )
308
+ + numOfHistoryEdgeAttributes * state.History.Length)
311
309
312
- OrtValue.CreateTensorValueFromMemory ( historyIndex_ vertexToState, shapeOfHistory),
313
- OrtValue.CreateTensorValueFromMemory ( historyAttributes, shapeOfHistoryAttributes),
314
- OrtValue.CreateTensorValueFromMemory ( parentOf, shapeOfParentOf)
310
+ OrtValue.CreateTensorValueFromMemory( historyIndex_ vertexToState, shapeOfHistory),
311
+ OrtValue.CreateTensorValueFromMemory( historyAttributes, shapeOfHistoryAttributes),
312
+ OrtValue.CreateTensorValueFromMemory( parentOf, shapeOfParentOf)
315
313
316
314
let statePosition_stateToVertex , statePosition_vertexToState =
317
- let data_stateToVertex =
318
- Array.zeroCreate ( 2 * gameState.States.Length)
319
- let data_vertexToState =
320
- Array.zeroCreate ( 2 * gameState.States.Length)
321
- let shape =
322
- [| 2 L ; gameState.States.Length |]
315
+ let data_stateToVertex = Array.zeroCreate ( 2 * gameState.States.Length)
316
+ let data_vertexToState = Array.zeroCreate ( 2 * gameState.States.Length)
317
+ let shape = [| 2 L; gameState.States.Length |]
323
318
let mutable firstFreePosition = 0
319
+
324
320
gameState.GraphVertices
325
321
|> Array.iter ( fun v ->
326
322
v.States
@@ -332,46 +328,43 @@ type internal AISearcher(oracle: Oracle, aiAgentTrainingOptions: Option<AIAgentT
332
328
data_ stateToVertex[ stateIds.Count + j] <- vertexIndex
333
329
334
330
data_ vertexToState[ j] <- vertexIndex
335
- data_ vertexToState[ stateIds.Count + j] <- stateIndex
336
- )
337
- firstFreePosition <- firstFreePosition + v.States.Length
338
- )
339
- OrtValue.CreateTensorValueFromMemory ( data_ stateToVertex, shape),
340
- OrtValue.CreateTensorValueFromMemory ( data_ vertexToState, shape)
331
+ data_ vertexToState[ stateIds.Count + j] <- stateIndex)
332
+
333
+ firstFreePosition <- firstFreePosition + v.States.Length)
334
+
335
+ OrtValue.CreateTensorValueFromMemory( data_ stateToVertex, shape),
336
+ OrtValue.CreateTensorValueFromMemory( data_ vertexToState, shape)
341
337
342
- res.Add ( " game_vertex" , gameVertices)
343
- res.Add ( " state_vertex" , states)
338
+ res.Add( " game_vertex" , gameVertices)
339
+ res.Add( " state_vertex" , states)
344
340
345
- res.Add ( " gamevertex_to_gamevertex_index" , vertexToVertexEdgesIndex)
346
- res.Add ( " gamevertex_to_gamevertex_type" , vertexToVertexEdgesAttributes)
341
+ res.Add( " gamevertex_to_gamevertex_index" , vertexToVertexEdgesIndex)
342
+ res.Add( " gamevertex_to_gamevertex_type" , vertexToVertexEdgesAttributes)
347
343
348
- res.Add ( " gamevertex_history_statevertex_index" , historyEdgesIndex_ vertexToState)
349
- res.Add ( " gamevertex_history_statevertex_attrs" , historyEdgesAttributes)
344
+ res.Add( " gamevertex_history_statevertex_index" , historyEdgesIndex_ vertexToState)
345
+ res.Add( " gamevertex_history_statevertex_attrs" , historyEdgesAttributes)
350
346
351
- res.Add ( " gamevertex_in_statevertex" , statePosition_ vertexToState)
352
- res.Add ( " statevertex_parentof_statevertex" , parentOfEdges)
347
+ res.Add( " gamevertex_in_statevertex" , statePosition_ vertexToState)
348
+ res.Add( " statevertex_parentof_statevertex" , parentOfEdges)
353
349
354
350
res
355
351
356
- let output =
357
- session.Run ( runOptions, networkInput, session.OutputNames)
358
- let weighedStates =
359
- output[ 0 ]. GetTensorDataAsSpan< float32>() .ToArray ()
352
+ let output = session.Run( runOptions, networkInput, session.OutputNames)
353
+ let weighedStates = output[ 0 ]. GetTensorDataAsSpan< float32>() .ToArray()
360
354
361
- let id =
362
- weighedStates |> Array.mapi ( fun i v -> i, v) |> Array.maxBy snd |> fst
355
+ let id = weighedStates |> Array.mapi ( fun i v -> i, v) |> Array.maxBy snd |> fst
363
356
stateIds |> Seq.find ( fun kvp -> kvp.Value = id) |> ( fun x -> x.Key)
364
357
365
- Oracle ( predict, feedback)
358
+ Oracle( predict, feedback)
366
359
367
- AISearcher ( createOracle pathToONNX, None)
360
+ AISearcher( createOracle pathToONNX, None)
368
361
369
362
interface IForwardSearcher with
370
363
override x.Init states = init states
371
- override x.Pick () = pick ( always true )
364
+ override x.Pick () = pick ( always true )
372
365
override x.Pick selector = pick selector
373
- override x.Update ( parent , newStates ) = update ( parent, newStates)
374
- override x.States () = availableStates
375
- override x.Reset () = reset ()
366
+ override x.Update ( parent , newStates ) = update ( parent, newStates)
367
+ override x.States () = availableStates
368
+ override x.Reset () = reset ()
376
369
override x.Remove cilState = remove cilState
377
370
override x.StatesCount = availableStates.Count
0 commit comments