Top View


Author kta-m

StepFunctionsだけで無駄に壮大な4bit加算器を作ったよ

2021/11/04

StepFunctionsで論理回路

先日、なんだか眠れないなーと布団の中でゴロゴロしてたらふと天啓を得ました。 「StepFunctionsで論理回路が作れるぞ」という天啓を。

ということで、そこから起きてNOT, AND, OR回路を作ってみました。ノッてしまって午前3時まで眠れませんでした…。

NOT回路

IMAGE

これがNOT回路です。

IMAGE

定義は以下のようになっています。

{
  "Comment": "This is your state machine",
  "StartAt": "not",
  "States": {
    "0": {
      "Type": "Pass",
      "End": true,
      "Parameters": {
        "bit": 0
      }
    },
    "1": {
      "Type": "Pass",
      "Parameters": {
        "bit": 1
      },
      "End": true
    },
    "Fail": {
      "Type": "Fail"
    },
    "not": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.bit",
          "NumericEquals": 0,
          "Next": "1"
        },
        {
          "Variable": "$.bit",
          "NumericEquals": 1,
          "Next": "0"
        }
      ],
      "Default": "Fail"
    }
  }
}

入力として、以下のようなフォーマットを想定しています。

{
  "bit": <0 or 1>
}

NOTなので、bitを反転したものが出力になります。 例えば0を入れると、次のJSONが出力されます。

{
  "bit": 1
}

組み立てとしては、notと名付けているChoice stateでbitの値を見て、 0なら問答無用で1を出力するPass state, 1なら問答無用で0を出力するPass Stateに送っている形です。

それから、一応0, 1以外が来たらFail stateに送るようにしました。

AND回路

IMAGE

次にAND回路です。

IMAGE

定義は以下のようになっています。

{
  "Comment": "This is your state machine",
  "StartAt": "and",
  "States": {
    "0": {
      "Type": "Pass",
      "Parameters": {
        "bit": 0
      },
      "End": true
    },
    "1": {
      "Type": "Pass",
      "End": true,
      "Parameters": {
        "bit": 1
      }
    },
    "Fail": {
      "Type": "Fail"
    },
    "and": {
      "Type": "Choice",
      "Choices": [
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 1
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 1
            }
          ],
          "Next": "1"
        },
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 1
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 0
            }
          ],
          "Next": "0"
        },
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 0
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 1
            }
          ],
          "Next": "0"
        },
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 0
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 0
            }
          ],
          "Next": "0"
        }
      ],
      "Default": "Fail"
    }
  }
}

入力として、以下のようなフォーマットを想定しています。

[
  { "bit": <0 or 1> },
  { "bit": <0 or 1> }
]

ANDなので、2つのbitのANDが出力になります。 例えば0, 1を入れると、次のJSONが出力されます。

{
  "bit": 0
}

組み立てもNOTとほとんど同じです。 Choice stateで条件分岐して、出力を生成するPass stateに送っています。

OR回路

IMAGE

最後にOR回路です。

IMAGE

定義は以下のようになっています。

{
  "Comment": "This is your state machine",
  "StartAt": "or",
  "States": {
    "0": {
      "Type": "Pass",
      "End": true,
      "Parameters": {
        "bit": 0
      }
    },
    "1": {
      "Type": "Pass",
      "End": true,
      "Parameters": {
        "bit": 1
      }
    },
    "or": {
      "Type": "Choice",
      "Choices": [
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 1
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 1
            }
          ],
          "Next": "1"
        },
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 1
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 0
            }
          ],
          "Next": "1"
        },
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 0
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 1
            }
          ],
          "Next": "1"
        },
        {
          "And": [
            {
              "Variable": "$[0].bit",
              "NumericEquals": 0
            },
            {
              "Variable": "$[1].bit",
              "NumericEquals": 0
            }
          ],
          "Next": "0"
        }
      ],
      "Default": "Fail"
    },
    "Fail": {
      "Type": "Fail"
    }
  }
}

入力として、以下のようなフォーマットを想定しています。

[
  { "bit": <0 or 1> },
  { "bit": <0 or 1> }
]

ORなので、2つのbitのORが出力になります。 例えば0, 1を入れると、次のJSONが出力されます。

{
  "bit": 1
}

組み立てもNOTとほとんど同じです。 Choice stateで条件分岐して、出力を生成するPass stateに送っています。

ポイント

条件判定の部分で、入力のJSONから値を切り出すためにJsonPathを使っています。 ただし、一般的なJsonPathとは若干仕様が違っていて、機能が制限されていたりします(公式ドキュメント)。

ここでは配列の要素を取得しようとしていたのですが($[0].bit といった部分です)、公式ドキュメントに明確な説明がなく探り当てるのに苦労しました。。

半加算器

NOT, AND, ORができれば次はやっぱり半加算器でしょう。2つのbitを入力して、それらの和と繰り上がりを返すやつです。

回路図で言うとこんな感じ。

IMAGE

IMAGE

StepFunctionsをネストさせてこれを作ってみます。かなり壮大になりましたが、回路図に忠実になっていると思います。

IMAGE

定義は以下のようになっています。

{
  "Comment": "This is your state machine",
  "StartAt": "split_s_c",
  "States": {
    "split_s_c": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "split_s",
          "States": {
            "split_s": {
              "Type": "Parallel",
              "Branches": [
                {
                  "StartAt": "split_s0",
                  "States": {
                    "split_s0": {
                      "Type": "Parallel",
                      "Branches": [
                        {
                          "StartAt": "bitA_s0",
                          "States": {
                            "bitA_s0": {
                              "Type": "Pass",
                              "Parameters": {
                                "bit.$": "$[0].bit"
                              },
                              "End": true
                            }
                          }
                        },
                        {
                          "StartAt": "bitB_s0",
                          "States": {
                            "bitB_s0": {
                              "Type": "Pass",
                              "Next": "NotB_s0",
                              "Parameters": {
                                "bit.$": "$[1].bit"
                              }
                            },
                            "NotB_s0": {
                              "Type": "Task",
                              "Resource": "arn:aws:states:::states:startExecution.sync:2",
                              "Parameters": {
                                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:Not",
                                "Input.$": "$"
                              },
                              "End": true,
                              "OutputPath": "$.Output"
                            }
                          }
                        }
                      ],
                      "Next": "A_And_NotB"
                    },
                    "A_And_NotB": {
                      "Type": "Task",
                      "Resource": "arn:aws:states:::states:startExecution.sync:2",
                      "Parameters": {
                        "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:And",
                        "Input.$": "$"
                      },
                      "End": true,
                      "OutputPath": "$.Output"
                    }
                  }
                },
                {
                  "StartAt": "split_s1",
                  "States": {
                    "split_s1": {
                      "Type": "Parallel",
                      "Branches": [
                        {
                          "StartAt": "bitA_s1",
                          "States": {
                            "bitA_s1": {
                              "Type": "Pass",
                              "Parameters": {
                                "bit.$": "$[0].bit"
                              },
                              "Next": "NotA_s1"
                            },
                            "NotA_s1": {
                              "Type": "Task",
                              "Resource": "arn:aws:states:::states:startExecution.sync:2",
                              "Parameters": {
                                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:Not",
                                "Input.$": "$"
                              },
                              "End": true,
                              "OutputPath": "$.Output"
                            }
                          }
                        },
                        {
                          "StartAt": "bitB_s1",
                          "States": {
                            "bitB_s1": {
                              "Type": "Pass",
                              "Parameters": {
                                "bit.$": "$[1].bit"
                              },
                              "End": true
                            }
                          }
                        }
                      ],
                      "Next": "NotA_And_B"
                    },
                    "NotA_And_B": {
                      "Type": "Task",
                      "Resource": "arn:aws:states:::states:startExecution.sync:2",
                      "Parameters": {
                        "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:And",
                        "Input.$": "$"
                      },
                      "End": true,
                      "OutputPath": "$.Output"
                    }
                  }
                }
              ],
              "Next": "(A_And_NotB)_Or_(NotA_And_B)"
            },
            "(A_And_NotB)_Or_(NotA_And_B)": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:Or",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "split_c",
          "States": {
            "split_c": {
              "Type": "Parallel",
              "Branches": [
                {
                  "StartAt": "bitA_c",
                  "States": {
                    "bitA_c": {
                      "Type": "Pass",
                      "Parameters": {
                        "bit.$": "$[0].bit"
                      },
                      "End": true
                    }
                  }
                },
                {
                  "StartAt": "bitB_c",
                  "States": {
                    "bitB_c": {
                      "Type": "Pass",
                      "Parameters": {
                        "bit.$": "$[1].bit"
                      },
                      "End": true
                    }
                  }
                }
              ],
              "Next": "A_And_B"
            },
            "A_And_B": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:And",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        }
      ],
      "End": true
    }
  }
}

入力として、以下のようなフォーマットを想定しています。

[
  { "bit": <0 or 1> },
  { "bit": <0 or 1> }
]

例えば1, 1を入れると和が0, 繰り上がりが1なので、次のJSONが出力されます。

[
  { "bit": 0 },
  { "bit": 1 }
]

ポイント

Parallel stateの分岐が収束する部分では、分岐の最終出力が配列になってやってきます。 そのため、AND, ORの入力は配列を受け取るようにしています。

また、StepFunctionsのネストもポイントです。 Workflow Studioで、 タスクが完了するまで待機 にチェックを入れておきましょう。

IMAGE

定義でいうと、

"Resource": "arn:aws:states:::states:startExecution.sync:2"

にあたります。 こうしておかないと、非同期実行になるためStepFunctionsの結果を戻してもらえません。

そして、出力にはいろいろな情報が付いてくるので、出力をフィルタリングしてあげましょう。

IMAGE

4bit加算器

ここまで来たら複数ビットの加算器を作りたくなりますね。 4bitの和と最終桁の繰り上がり(桁あふれ)を求めるものを作ってみました。

回路図で言うとこんな感じ。

IMAGE

StepFunctionsだとこうなりました。

IMAGE

とても長いですが、定義は以下のようになります。

{
  "Comment": "This is your state machine",
  "StartAt": "calc_1",
  "States": {
    "calc_1": {
      "Type": "Parallel",
      "Branches": [
        {
          "StartAt": "digit_0",
          "States": {
            "digit_0": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$.numA[0]"
                },
                {
                  "bit.$": "$.numB[0]"
                }
              ],
              "Next": "half_addr_0"
            },
            "half_addr_0": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "digit_1",
          "States": {
            "digit_1": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$.numA[1]"
                },
                {
                  "bit.$": "$.numB[1]"
                }
              ],
              "Next": "half_addr_1"
            },
            "half_addr_1": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "digit_2",
          "States": {
            "digit_2": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$.numA[2]"
                },
                {
                  "bit.$": "$.numB[2]"
                }
              ],
              "Next": "half_addr_2"
            },
            "half_addr_2": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "digit_3",
          "States": {
            "digit_3": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$.numA[3]"
                },
                {
                  "bit.$": "$.numB[3]"
                }
              ],
              "Next": "half_addr_3"
            },
            "half_addr_3": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        }
      ],
      "Next": "calc_2"
    },
    "calc_2": {
      "Type": "Parallel",
      "Next": "calc_3",
      "Branches": [
        {
          "StartAt": "calc2_s0",
          "States": {
            "calc2_s0": {
              "Type": "Pass",
              "Parameters": {
                "bit.$": "$[0][0].bit"
              },
              "End": true
            }
          }
        },
        {
          "StartAt": "calc2_c0_st1",
          "States": {
            "calc2_c0_st1": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$[0][1].bit"
                },
                {
                  "bit.$": "$[1][0].bit"
                }
              ],
              "Next": "half_addr_0_1"
            },
            "half_addr_0_1": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "calc2_ct1",
          "States": {
            "calc2_ct1": {
              "Type": "Pass",
              "End": true,
              "Parameters": {
                "bit.$": "$[1][1].bit"
              }
            }
          }
        },
        {
          "StartAt": "calc2_st2_ct2",
          "States": {
            "calc2_st2_ct2": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[2]"
            }
          }
        },
        {
          "StartAt": "calc2_st3_ct3",
          "States": {
            "calc2_st3_ct3": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[3]"
            }
          }
        }
      ]
    },
    "calc_3": {
      "Type": "Parallel",
      "Next": "calc_4",
      "Branches": [
        {
          "StartAt": "calc3_s0",
          "States": {
            "calc3_s0": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[0]"
            }
          }
        },
        {
          "StartAt": "calc3_s1",
          "States": {
            "calc3_s1": {
              "Type": "Pass",
              "Parameters": {
                "bit.$": "$[1][0].bit"
              },
              "End": true
            }
          }
        },
        {
          "StartAt": "calc3_ct01_ct1",
          "States": {
            "calc3_ct01_ct1": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$[1][1].bit"
                },
                {
                  "bit.$": "$[2].bit"
                }
              ],
              "Next": "or_ct01_ct1"
            },
            "or_ct01_ct1": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:Or",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "calc3_st2_ct2",
          "States": {
            "calc3_st2_ct2": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[3]"
            }
          }
        },
        {
          "StartAt": "calc3_st3_ct3",
          "States": {
            "calc3_st3_ct3": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[4]"
            }
          }
        }
      ]
    },
    "calc_4": {
      "Type": "Parallel",
      "Next": "calc_5",
      "Branches": [
        {
          "StartAt": "calc4_s0",
          "States": {
            "calc4_s0": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[0]"
            }
          }
        },
        {
          "StartAt": "calc4_s1",
          "States": {
            "calc4_s1": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[1]"
            }
          }
        },
        {
          "StartAt": "calc4_c1_st2",
          "States": {
            "calc4_c1_st2": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$[2].bit"
                },
                {
                  "bit.$": "$[3][0].bit"
                }
              ],
              "Next": "half_addr_c1_st2"
            },
            "half_addr_c1_st2": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "calc4_ct2",
          "States": {
            "calc4_ct2": {
              "Type": "Pass",
              "End": true,
              "Parameters": {
                "bit.$": "$[3][1].bit"
              }
            }
          }
        },
        {
          "StartAt": "calc4_st3_ct3",
          "States": {
            "calc4_st3_ct3": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[4]"
            }
          }
        }
      ]
    },
    "calc_5": {
      "Type": "Parallel",
      "Next": "calc_6",
      "Branches": [
        {
          "StartAt": "calc5_s0",
          "States": {
            "calc5_s0": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[0]"
            }
          }
        },
        {
          "StartAt": "calc5_s1",
          "States": {
            "calc5_s1": {
              "Type": "Pass",
              "InputPath": "$[1]",
              "End": true
            }
          }
        },
        {
          "StartAt": "calc5_s2",
          "States": {
            "calc5_s2": {
              "Type": "Pass",
              "End": true,
              "Parameters": {
                "bit.$": "$[2][0].bit"
              }
            }
          }
        },
        {
          "StartAt": "calc5_ct012_ct2",
          "States": {
            "calc5_ct012_ct2": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$[2][1].bit"
                },
                {
                  "bit.$": "$[3].bit"
                }
              ],
              "Next": "or_ct012_ct2"
            },
            "or_ct012_ct2": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:Or",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "calc5_st3_ct3",
          "States": {
            "calc5_st3_ct3": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[4]"
            }
          }
        }
      ]
    },
    "calc_6": {
      "Type": "Parallel",
      "Next": "calc_7",
      "Branches": [
        {
          "StartAt": "calc6_s0",
          "States": {
            "calc6_s0": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[0]"
            }
          }
        },
        {
          "StartAt": "calc6_s1",
          "States": {
            "calc6_s1": {
              "Type": "Pass",
              "InputPath": "$[1]",
              "End": true
            }
          }
        },
        {
          "StartAt": "calc6_s2",
          "States": {
            "calc6_s2": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[2]"
            }
          }
        },
        {
          "StartAt": "calc6_c2_st3",
          "States": {
            "calc6_c2_st3": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$[3].bit"
                },
                {
                  "bit.$": "$[4][0].bit"
                }
              ],
              "Next": "half_addr_c2_st3"
            },
            "half_addr_c2_st3": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:HalfAdder",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        },
        {
          "StartAt": "calc4_ct3",
          "States": {
            "calc4_ct3": {
              "Type": "Pass",
              "End": true,
              "Parameters": {
                "bit.$": "$[4][1].bit"
              }
            }
          }
        }
      ]
    },
    "calc_7": {
      "Type": "Parallel",
      "Next": "result",
      "Branches": [
        {
          "StartAt": "calc7_s0",
          "States": {
            "calc7_s0": {
              "Type": "Pass",
              "End": true,
              "InputPath": "$[0]"
            }
          }
        },
        {
          "StartAt": "calc7_s1",
          "States": {
            "calc7_s1": {
              "Type": "Pass",
              "InputPath": "$[1]",
              "End": true
            }
          }
        },
        {
          "StartAt": "calc7_s2",
          "States": {
            "calc7_s2": {
              "Type": "Pass",
              "InputPath": "$[2]",
              "End": true
            }
          }
        },
        {
          "StartAt": "calc7_s3",
          "States": {
            "calc7_s3": {
              "Type": "Pass",
              "End": true,
              "Parameters": {
                "bit.$": "$[3][0].bit"
              }
            }
          }
        },
        {
          "StartAt": "calc5_ct0123_ct3",
          "States": {
            "calc5_ct0123_ct3": {
              "Type": "Pass",
              "Parameters": [
                {
                  "bit.$": "$[3][1].bit"
                },
                {
                  "bit.$": "$[4].bit"
                }
              ],
              "Next": "or_ct0123_ct3"
            },
            "or_ct0123_ct3": {
              "Type": "Task",
              "Resource": "arn:aws:states:::states:startExecution.sync:2",
              "Parameters": {
                "StateMachineArn": "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:Or",
                "Input.$": "$"
              },
              "End": true,
              "OutputPath": "$.Output"
            }
          }
        }
      ]
    },
    "result": {
      "Type": "Pass",
      "End": true,
      "Parameters": {
        "sum.$": "States.Array($[0].bit, $[1].bit, $[2].bit, $[3].bit)",
        "carry.$": "$[4].bit"
      }
    }
  }
}

ポイント

残念ながら、StepFunctionsでは各ステートの入力は1つだけです。回路図のように、複数のステートの任意の出力を同時に入力として扱うようなことはできません。そこで、Parallel stateを使って複数入力を擬似的に実現しています。

StepFunctionのワークフローに寄せる形で書くと以下のような形です。見た目は変わっていますがやっていることは同じです。

IMAGE

動かしてみよう!!

さて、ついに動かすときがやってきました。 以下のJSONを入力してみます。ビットの順序が逆転しますが、0101(5) + 1110(14)をしています。

{
  "numA": [1, 0, 1, 0],
  "numB": [0, 1, 1, 1]
}

結果は…

IMAGE

{
  "sum": [1, 1, 0, 0],
  "carry": 1
}

ということで、桁あふれまで一緒にしてあげると、10011(19)ということで、正しく計算できています!! ここまで計算するのに48,515[msec]かかってる…壮大だ!

時間がかかっている要因としては、やはりStepFunctionsをネストしているところで完了待ちをしているところが大きいです。 例として4つの半加算器の完了待ちの部分を出して見ましたが、半加算器の中でもStepFunctionsのネストで完了待ちをしている部分があり、、それはまぁ時間がかかりますよね。

IMAGE

まとめ

今回は秋の夜長にStepFunctionsで遊んでみました。 いざやってみると、意外と詰まるところや知らないところが出てきて、やっぱり触ってなんぼだなと改めて感じました。

こんな遊び記事がお好みの方は以下も一緒にどうぞ!

kta-m

kta-m

先進技術部門 IoTチーム チームリーダー