并行计算NFA转换

时间:2016-04-26 15:59:46

标签: parallel-processing f# finite-automata

我用F#编写了这段代码:

type NondeterministicFiniteAutomaton = {
    initialState: string
    finalStates: string List
    transitions: Map<string * char, string List>
}

let private nextState (symbol:char) (state:string) (transitions:Map<string * char, string List>) =
    transitions |> Map.tryFind (state, symbol)

let rec private haltState (input:string) (index:int) (state:string) (transitions:Map<string * char, string List>) =
    match index with
    | x when x = input.Length -> state
    | _ ->
        match nextState input.[index] state transitions with
        | x when x.IsNone -> null
        | x -> haltState input (index+1) x.Value transitions

在最后一行中,x.Value将返回我的自动机可以输入的状态列表,例如["s1"; "s2"; "s3"]。对于此列表中的每个状态,我想并行调用haltState,从而并行计算每个可能的路径。

  • 如何并行调用它们?
  • 完成后如何“加入”它们?

1 个答案:

答案 0 :(得分:4)

我建议先写完整的顺序版。然后你可以看到添加并行性是否对你将要进行的计算有意义。

至于加入结果,即使在顺序版本中,您也需要这样做。您的haltState函数返回单个字符串,但如果这是NFA,则它可能以多个不同的状态结束。所以你可以改变它以返回一系列可能的结果:

let rec private haltState (input:string) (index:int) (state:string) (transitions:Map<string * char, string List>) =
    match index with
    | x when x = input.Length -> Seq.singleton x
    | _ ->
        match nextState input.[index] state transitions with
        | None -> Seq.empty
        | Some states -> 
            states |> Seq.collect (fun state -> 
              haltState input (index+1) state transitions)

返回一个序列,它使用Seq.collect连接为多个可能状态生成的序列。请注意,我还在选项值上使用了更多惯用模式匹配。

您可以使用Array.Parallel.map对此进行并行化,但我怀疑这会使处理速度更快 - 开销可能会更大。

let rec private haltState (input:string) (index:int) (state:string) (transitions:Map<string * char, string List>) =
    match index with
    | x when x = input.Length -> [| state |]
    | _ ->
        match nextState input.[index] state transitions with
        | None -> [| |]
        | Some states -> 
            states
            |> Array.ofSeq
            |> Array.Parallel.collect (fun state -> haltState input (index+1) state transitions)