Repository navigation
Expand file tree
/
Copy pathStateMachine.fs
More file actions
56 lines (46 loc) · 1.72 KB
/
Copy pathStateMachine.fs
File metadata and controls
56 lines (46 loc) · 1.72 KB
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
module FP.Task04.StateMachine
open System.Text
open Printf
type StateMachine<'state, 'model> = {
CurrentState : 'state
Model : 'model
Permits : ('state * 'state * ('model -> bool) * ('model -> 'model)) list
IgnoredPermits : ('state * 'state * ('model -> bool) * ('model -> 'model)) list
} with
member this.AsDot() =
let sb = StringBuilder()
bprintf sb "digraph sm {\n"
this.Permits |> List.iter (fun (a, b, _, _) ->
bprintf sb " %A -> %A\n" a b
)
this.IgnoredPermits |> List.iter (fun (a, b, _, _) ->
bprintf sb " %A -> %A [style=dotted]\n" a b
)
bprintf sb "}\n"
sb.ToString()
let iterate sm =
let permit =
sm.Permits
|> Seq.tryFind (fun (a, _, predicate, _) -> sm.CurrentState = a && predicate sm.Model)
match permit with
| None -> sm
| Some(_, b, predicate, action) ->
{ sm with CurrentState = b
Model = action sm.Model }
let iterateTimes sm times =
if times < 0 || times > 10000 then invalidArg "times" "Число шагов: от 0 до 10000."
if times = 0 then [] else
[2..times]
|> List.fold (fun s _ -> iterate s.Head :: s) [iterate sm]
|> List.rev
let pTrue _ = true
let iterateUntilStatesBounded maxSteps states sm =
if maxSteps < 1 || maxSteps > 10000 then invalidArg "maxSteps" "Лимит шагов: от 1 до 10000."
List.unfold (fun (current, steps) ->
if List.contains current.CurrentState states then None
elif steps >= maxSteps then invalidOp "Автомат не достиг конечного состояния в пределах лимита."
else
let next = iterate current
Some(next, (next, steps + 1))
) (sm, 0)
let iterateUntilStates states sm = iterateUntilStatesBounded 10000 states sm