概要
組合せ論理回路を関数型リアクティブプログラミング(SodiumFRP)の世界でモデル化してみました。
合成性
XOR(排他的論理和)は、数式/MIL記号回路では、次のように表現することができます。
X = (\overline{A \cdot B}) \cdot (A + B)
これを、F#+SodiumFRP で、次のようにコードとして表現できるようにしてみました。自然な形で合成していくことができます。
XOR
let inA = StreamSink.create<Option<bool>> ()
let inB = StreamSink.create<Option<bool>> ()
let outP = (inA, inB) |> AND |> NOT
let outQ = (inA, inB) |> OR
let outX = (outP, outQ) |> AND
コード
open System
open SodiumFRP
let eNOT (a:Option<bool>) =
match a.IsSome with
| true -> Some(not a.Value)
| false -> None
let eAND (a:Option<bool>) (b:Option<bool>) =
match (a.IsSome,b.IsSome) with
| (true ,true ) -> Some ( a.Value && b.Value )
| (true ,false) -> if a.Value = false then Some false else None
| (false,true ) -> if b.Value = false then Some false else None
| (false,false) -> None
let eOR (a:Option<bool>) (b:Option<bool>) =
match (a.IsSome,b.IsSome) with
| (true ,true ) -> Some ( a.Value || b.Value )
| (true ,false) -> if a.Value = true then Some true else None
| (false,true ) -> if b.Value = true then Some true else None
| (false,false) -> None
let eXOR (a:Option<bool>) (b:Option<bool>) =
match (a.IsSome,b.IsSome) with
| (true ,true) -> if a.Value = b.Value then Some false else Some true
| _ -> None
let eNAND a b = eAND a b |> eNOT
let eNOR a b = eOR a b |> eNOT
let NOT a = mapS eNOT a
let AND (a,b) = mergeS eAND (a,b)
let OR (a,b) = mergeS eOR (a,b)
let XOR (a,b) = mergeS eXOR (a,b)
let str (x:Option<bool>) =
match x.IsSome with
| true -> if x.Value then "1" else "0"
| false -> "*"
let twoInputList = [
(Some false, Some false)
(Some false, Some true)
(Some true, Some false)
(Some true, Some true)
(None, Some true)
(None, Some false)
(Some true, None)
(Some false, None)
(None, None)
]
let run21 (i1,i2) o1 (d1,d2) =
let i1' = i1 |> holdS None
let i2' = i2 |> holdS None
let o1' = o1 |> holdS None
Transaction.run( fun () ->
i1 |> sendS d1
i2 |> sendS d2
)
((sampleC i1', sampleC i2'), sampleC o1')
let run22 (i1,i2) (o1,o2) (d1,d2) =
let i1' = i1 |> holdS None
let i2' = i2 |> holdS None
let o1' = o1 |> holdS None
let o2' = o2 |> holdS None
Transaction.run( fun () ->
i1 |> sendS d1
i2 |> sendS d2
)
((sampleC i1', sampleC i2'), (sampleC o1',sampleC o2'))
let logicTest21 (i1,i2) o1 =
let rec testAll testPatterns =
match testPatterns with
| x::xs-> (run21 (i1,i2) o1 x)::(testAll xs)
| [] -> []
testAll twoInputList
let logicTest22 (i1,i2) (o1,o2) =
let rec testAll testPatterns =
match testPatterns with
| x::xs-> (run22 (i1,i2) (o1,o2) x)::(testAll xs)
| [] -> []
testAll twoInputList
let printTestResult21 data =
let print ((i1,i2), o1) =
let s = sprintf " %s %s | %s" (str i1) (str i2) (str o1)
do Console.WriteLine(s)
do Console.WriteLine(" A B | X")
for i in data do
do print <| i
let printTestResult22 data =
let print ((i1,i2), (o1,o2)) =
let s = sprintf " %s %s | %s %s" (str i1) (str i2) (str o1) (str o2)
do Console.WriteLine(s)
do Console.WriteLine(" A B | X Y")
for i in data do
do print <| i
let NL = System.Environment.NewLine
[<EntryPoint>]
let main argv =
let inA = StreamSink.create<Option<bool>> ()
let inB = StreamSink.create<Option<bool>> ()
do Console.WriteLine("AND(論理積)")
let outX = (inA, inB) |> AND
let rAND = logicTest21 (inA,inB) outX
do printTestResult21 rAND
do Console.WriteLine(NL+"OR(論理和)")
let outX = (inA, inB) |> OR
let rOR = logicTest21 (inA,inB) outX
do printTestResult21 rOR
do Console.WriteLine(NL+"XOR -> rXOR_1")
let outX = (inA, inB) |> XOR
let rXOR_1 = logicTest21 (inA,inB) outX
do printTestResult21 rXOR_1
do Console.WriteLine(NL+"XOR(合成版) -> rXOR_2")
let outP = (inA, inB) |> AND |> NOT
let outQ = (inA, inB) |> OR
let outX = (outP, outQ ) |> AND
let rXOR_2 = logicTest21 (inA,inB) outX
do printTestResult21 rXOR_2
do Console.Write(NL+"rXOR_1 と rXOR_2 は等しい? ")
let a = ( rXOR_1 = rXOR_2 )
Console.WriteLine(a)
do Console.WriteLine(NL+"NANDとNOR")
let outX = (inA, inB) |> AND |> NOT
let outY = (inA, inB) |> OR |> NOT
let r = logicTest22 (inA,inB) (outX,outY)
do printTestResult22 r
do Console.ReadKey() |> ignore
0
実行結果
AND(論理積)
A B | X
0 0 | 0
0 1 | 0
1 0 | 0
1 1 | 1
* 1 | *
* 0 | 0
1 * | *
0 * | 0
* * | *
OR(論理和)
A B | X
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 1
* 1 | 1
* 0 | *
1 * | 1
0 * | *
* * | *
XOR -> rXOR_1
A B | X
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 0
* 1 | *
* 0 | *
1 * | *
0 * | *
* * | *
XOR(合成版) -> rXOR_2
A B | X
0 0 | 0
0 1 | 1
1 0 | 1
1 1 | 0
* 1 | *
* 0 | *
1 * | *
0 * | *
* * | *
rXOR_1 と rXOR_2 は等しい? True
NANDとNOR
A B | X Y
0 0 | 1 1
0 1 | 1 0
1 0 | 1 0
1 1 | 0 0
* 1 | * 0
* 0 | 1 *
1 * | * 0
0 * | 1 *
* * | * *
F#では、関数のオーバーロードができず、、、引数違いの関数をうまくまとめられず不細工な感じになってしました。
次は順序回路に発展させていきたいと思います。