Visual Studio Code を使用して Q# プログラムを送信する方法

Visual Studio Code を使用して Q# プログラムを作成し、実際の量子ハードウェアに送信する方法について説明します。 量子コンピューティング ジョブをスタンドアロンの Q# プログラムとして Azure Quantum に送信し、Q# プロジェクトで Q# と Python を組み合わせて、Jupyter Notebook を実行できます。

Azure Quantum への Q# ジョブの送信

VS Code を使用して、Q# プログラムを実行、デバッグ、および Azure Quantum に送信する方法について説明します。

前提条件

インストールの詳細については、「 VS Code での QDK のインストールを参照してください。

Q# サンプル プログラムを読み込む

  1. VS Code で、[ファイル>新しいテキスト ファイル選択しRandomNum.qsとしてファイルを保存

  2. RandomNum.qsを開き、「sample」と入力し、オプションの一覧から Random Bit sample を選択してファイルを保存します。

    Visual Studio Code の Q# ファイルのスクリーンショット。ファイルにサンプルという単語を書き込む際のコード サンプルの一覧が示されています。

Note

独自の Q# ファイルを開くこともできます。 以前の Q# プログラムを実行してエラーが発生した場合は、「 テストとデバッグを参照してください。

Q# プログラムを実行する

  1. 組み込みシミュレーター上でプログラムをローカルにテスト実行するには、@EntryPoint() の下のコマンドの一覧から [実行] を選択するか、Ctrl+F5 キーを押します。 出力がデバッグ コンソールに表示されます。

  2. Azure Quantum に送信する前にプログラムをデバッグするには、@EntryPoint()の下のコマンドの一覧から Debug をクリックするか、F5 キーを押します。 上部にあるデバッグ コントロールを使用して、コードのステップ オーバー、ステップ イン、ステップ アウトを行います。 Q# プログラムのデバッグの詳細については、「 Testing and debugging」を参照してください。

    実行コマンドとデバッグ コマンドを使用してコード レンズを検索する場所を示す、Visual Studio Code の Q# ファイルのスクリーンショット。

頻度ヒストグラムを視覚化する

頻度ヒストグラムは、量子プログラムを複数回実行して得られた結果の分布("ショット") を表します。 ヒストグラムの各バーは、考えられる結果に対応し、その高さは結果が観察される回数を表します。 頻度ヒストグラムは、これらの結果の確率分布を視覚化するのに役立ちます。

  1. View -> コマンド パレットを選択し「histogram」と入力します。"histogram" と入力すると、Q#: ファイルの実行とヒストグラムの表示 オプションが表示されます。 @EntryPoint()の下のコマンドの一覧から Histogram をクリックすることもできます。 Q# ヒストグラム ウィンドウを開くには、このオプションを選択します。

    ヒストグラム コマンドを使用してコード レンズを検索する場所を示す、Visual Studio Code の Q# ファイルのスクリーンショット。

  2. ショットの数を入力し100 ショットなどのプログラムを実行し、Enter キーを押します。 ヒストグラムが Q# ヒストグラム ウィンドウに表示されます。

  3. 左上の 設定アイコン をクリックしてオプションを表示します。

    設定を表示する方法を示す Visual Studio Code の Q# ヒストグラム ウィンドウのスクリーンショット。

  4. バーをクリックすると、その結果の 時間 が表示されます。 この場合、0 と 1 の 2 つの結果が考えられます。各結果の割合は 50% に近い値です。

    Visual Studio Code の Q# ヒストグラム ウィンドウのスクリーンショット。

ヒント

マウス スクロール ホイールまたはトラックパッド ジェスチャを使用して、ヒストグラムをズームできます。 拡大すると、スクロール中に 'Alt' キーを押してグラフをパンできます。

量子回路を視覚化する

量子回路図は、量子演算を視覚的に表現したものです。 量子プログラムを通る量子ビットの流れを示します。これには、ゲートとそれらに適用される測定値が含まれます。 詳細については、Visual Studio Code の Quantum の回路図を参照してください。

  1. View -> コマンド パレットを選択しQ#: Show circuit オプションを表示する必要がある「circuit」と入力します。 @EntryPoint()以下のコマンドの一覧から Circuit をクリックすることもできます。

    コード レンズ回線コマンドを検索する場所を示す Visual Studio Code の Q# ファイルのスクリーンショット。

  2. この回路は、Q# 回線ウィンドウに表示されます。 この回路図は、|0⟩ 状態に初期化された 1 つの量子ビット レジスタを示しています。 次に、ハダマールゲート Hが量子ビットに適用され、その後に測定演算 が適用されメーターシンボルで表されます。 詳細については、「 Quantum 回線の規則を参照してください。

    ランダム ビット演算の結果の回路図を示す Q# 回線ウィンドウのスクリーンショット。

Azure Quantum に接続してジョブを送信する

VS Code からジョブを直接接続して送信できます。 この例では、Rigetti シミュレーターにジョブを送信します。

  1. View -> コマンド パレットを選択しQ#: Azure Quantum ワークスペースに接続する」と入力します。 Enter キーを押します。

  2. Azure アカウントを選択し、プロンプトに従って、優先するディレクトリ、サブスクリプション、ワークスペースに接続します。

    Note

    接続文字列がある場合は、Connection 文字列を選択し Azure Quantum ワークスペースに対応する接続文字列を貼り付けることができます。 詳細については、「接続文字列を使用して Quantum ワークスペースに接続する」を参照してください。

  3. 接続したら、 Explorer ウィンドウで [Quantum ワークスペース 展開

  4. ワークスペースを展開し、 Rigetti プロバイダーを展開します。

    Note

    Azure Quantum への接続に問題がある場合は、ワークスペース名の横に警告アイコンが表示されます。 ワークスペース名にカーソルを合わせると、エラー情報が表示されます。

  5. targetとして rigetti.sim.qvm を選択します。

    targetとして Rigetti シミュレーターを選択する方法を示す Visual Studio Code のスクリーンショット。

  6. target名の右側にある再生アイコンを選択して、現在の Q# プログラムの送信を開始します。 ポップアップが表示された場合は、 QIR target プロファイルを変更して続行を選択します。

    targetとして Rigetti シミュレーターを実行する方法を示す Visual Studio Code のスクリーンショット。

  7. ジョブを識別する名前を追加します。

  8. ショットの数、またはプログラムが実行される回数を追加します。

  9. Enter キーを押してジョブを送信します。 ジョブの状態が画面の下部に表示されます。

  10. [ジョブ] を展開し、ジョブの上にカーソルを合わせると、ジョブの時刻と状態が表示されます。

  11. 結果を表示するには、ジョブ名の横にあるクラウド アイコンを選択してワークスペース ストレージから結果をダウンロードし、VS Code に表示します。

    量子ジョブの結果をダウンロードして表示する方法を示す Visual Studio Code のスクリーンショット。

Jupyter Notebooks ジョブを Azure Quantum に送信する

VS Code を使用して、Q# Jupyter Notebook を実行、デバッグ、および Azure Quantum に送信する方法について説明します。 この記事の手順は、ローカルの Jupyter サーバー上の Jupyter Notebook または Azure Quantum ポータルのノートブックにも適用されます。

前提条件

インストールの詳細については、「 VS Code での QDK のインストールを参照してください。

  • Azure サブスクリプションの Azure Quantum ワークスペース。 ワークスペースを作成するには、Azure Quantum ワークスペースの作成に関するページを参照してください。

  • Python と Pip がインストールされた Python 環境。

  • Azure Quantum Development KitPython、および Jupyter 拡張機能がインストールされている VS Code。

  • Azure Quantum qsharpqsharp-widgetsazure-quantum パッケージ、および ipykernel パッケージ。

    python -m pip install --upgrade qsharp qsharp-widgets azure-quantum ipykernel
    

ローカル シミュレーターでプログラムを実行してテストする

  1. VS Code で、[表示] > [コマンド パレット] を選択して、[作成: 新しい Jupyter Notebook] を選択します。

  2. 右上の VS Code は、Python のバージョンと、ノートブック用に選択された仮想 Python 環境を検出して表示します。 複数の Python 環境がある場合は、右上のカーネル ピッカーを使用してカーネルを選択する必要があります。 環境が検出されなかった場合は、VS Code の Jupyter Notebooks のセットアップ情報を参照してください。

  3. ノートブックの最初のセルで、次の Python コードを実行して、必要なモジュールをインポートします。

    import qsharp
    import azure.quantum
    
    • qsharp モジュールは、%%qsharpマジック コマンドをアクティブにします。これにより、Q# コードをセルに直接入力できます。
    • azure-quantum モジュールは、Azure Quantum ワークスペースへの接続を提供します。

    Note

    Jupyter Python カーネル ipykernel が検出されない場合、VS Code によってインストールするように求められます。

  4. 別のセルを追加し、ユーザー指定のランダム ビット数を返す次の Q# コードを入力します。

    Note

    マジック コマンド %%qsharpを入力するとすぐに、ノートブック のセルの種類が Python から Q# に変わります。

    %%qsharp
    
    operation Random() : Result {
        use q = Qubit();
        H(q);
        let result = M(q);
        Reset(q);
        return result
    }
    
    operation RandomNBits(N: Int): Result[] {
        mutable results = [];
        for i in 0 .. N - 1 {
            let r = Random();
            set results += [r];
        }
        return results
    }
    
  5. 操作をテストするには、 eval メソッドを使用できます。このメソッドは、ノートブックで以前に定義されている Q# 操作を呼び出すことができます。

    qsharp.eval("RandomNBits(4)")
    
    [Zero, One, One, Zero]
    
  6. ローカル シミュレーターに対してプログラムを実行するには、 run メソッドを使用します。 shotsを指定するか、プログラムを実行する回数を指定すると、シミュレーターは結果を Python リストとして返します。

    qsharp.run("RandomNBits(4)", shots=10)
    
    [[One, One, One, One],
    [Zero, Zero, One, Zero],
    [One, Zero, Zero, One],
    [Zero, One, Zero, Zero],
    [One, Zero, One, One],
    [One, Zero, One, Zero],
    [One, One, One, Zero],
    [One, One, One, One],
    [Zero, Zero, Zero, One],
    [One, Zero, Zero, One]]
    

量子回路を視覚化する

qsharp-widgets パッケージを使用して量子回路を視覚化できます。 このパッケージは、SVG 画像として量子回路図をレンダリングするウィジェットを提供します。 詳細については、「Jupyter Notebook を使用した Quantum の回路図を参照してください。

次のコードを新しいセルに追加して、回線を視覚化します。

from qsharp_widgets import Circuit

Circuit(qsharp.circuit("RandomNBits(4)"))

Q# 操作の回線を視覚化する方法を示す Jupyter Notebook のスクリーンショット。

詳細については、「 Quantum 回線の規則を参照してください。

基本プロファイルを使用してジョブをコンパイルする

ローカル量子シミュレーターでプログラムを実行する場合は、任意の種類の Q# プログラムを送信できます。 ただし、Azure Quantum ハードウェア targets では、すべての Q# プログラムを実行するために必要な完全な機能はまだサポートされていません。 Q# プログラムをコンパイルして Azure Quantum に送信するには、targetハードウェアでサポートされている機能を Q# に伝えるために、target プロファイルを設定する必要があります。 現時点では、基本プロファイルです。 詳細については、「 Profile types in Azure Quantum」を参照してください。

Q# インタープリターを再初期化し、基本プロファイルを使用してプログラムをコンパイルするには:

  1. initメソッドを使用してプロファイルを設定します。

    qsharp.init(target_profile=qsharp.TargetProfile.Base)
    
  2. インタープリターを再初期化したので、新しいプロファイルでコードをもう一度実行する必要があります。

    %%qsharp
    
    operation Random() : Result {
        use q = Qubit();
        H(q);
        let result = M(q);
        Reset(q);
        return result
    }
    
    operation RandomNBits(N: Int): Result[] {
        mutable results = [];
        for i in 0 .. N - 1 {
            let r = Random();
            set results += [r];
        }
        return results
    }
    
  3. 次に、 compile メソッドを使用して、プログラムへのエントリ ポイントである操作または関数を指定します。 これにより、コードが QIR 形式にコンパイルされ、任意の量子ハードウェアに送信できます。

    MyProgram = qsharp.compile("RandomNBits(4)")
    

Azure Quantum に接続してジョブを送信する

プログラムを正しい形式にコンパイルしたら、Azure Quantum に接続する azure.quantum.Workspace オブジェクトを作成します。 接続するには、Azure Quantum ワークスペースのリソース ID を使用します。 リソース ID と場所は、Azure portal のワークスペースの概要ページからコピーできます。

  1. 新しいセルで、Azure Quantum ワークスペースのリソース ID と場所を入力します。

    MyWorkspace = azure.quantum.Workspace(
        resource_id = "MyResourceID",
        location = "MyLocation"
    )
    
  2. get_targetsメソッドを使用して、ワークスペースで使用可能なハードウェア targetsを確認します。

    MyTargets = MyWorkspace.get_targets()
    print("This workspace's targets:")
    MyTargets
    
  3. rigetti.sim.qvmtargetを選択します。

    MyTarget = MyWorkspace.get_targets("rigetti.sim.qvm")
    
  4. 最後に、 submit メソッドを使用して、プログラムとそのパラメーターを送信し、結果を表示します。

    job = MyTarget.submit(MyProgram, "MyQuantumJob", shots=100)
    job.get_results()
    
    {'[0, 1, 1, 1]': 0.08,
     '[1, 1, 0, 0]': 0.1,
     '[0, 0, 1, 0]': 0.04,
     '[0, 1, 0, 0]': 0.05,
     '[1, 0, 1, 0]': 0.05,
     '[1, 0, 0, 0]': 0.07,
     '[0, 1, 0, 1]': 0.07,
     '[1, 0, 1, 1]': 0.07,
     '[0, 0, 0, 0]': 0.08,
     '[1, 1, 1, 0]': 0.05,
     '[0, 0, 0, 1]': 0.1,
     '[0, 0, 1, 1]': 0.04,
     '[0, 1, 1, 0]': 0.09,
     '[1, 0, 0, 1]': 0.04,
     '[1, 1, 1, 1]': 0.05,
     '[1, 1, 0, 1]': 0.02}
    
  5. ジョブのすべてのプロパティに job.detailsでアクセスできます。次に例を示します。

    print(job.details)
    print("\nJob name:", job.details.name)
    print("Job status:", job.details.status)
    print("Job ID:", job.details.id)
    
    {'additional_properties': {'isCancelling': False}, 'id': '0150202e-9638-11ee-be2f-b16153380354', 'name': 'MyQuantumJob', 'provider_id': 'rigetti'...}
    Job name: MyQuantumJob
    Job status: Succeeded
    Job ID: 0150202e-9638-11ee-be2f-b16153380354
    

その他のジョブの詳細

azure.quantum Python パッケージには、より詳細なジョブ データを表示するための追加のメソッドが含まれています。

  • job.get_results_histogram():このメソッドは、各一意の測定の結果とショット数のディクショナリを返します。 たとえば、前のジョブの結果は次のようになります。

    print(job.get_results_histogram()) 
    
    {   
        '[0, 1, 1, 1]' : {'Outcome' : [0, 1, 1, 1], 'Count' : 8},  
        '[1, 1, 0, 0]' : {'Outcome' : [1, 1, 0, 0], 'Count' : 10},
        '[0, 0, 1, 0]' : {'Outcome' : [0, 0, 1, 0], 'Count' : 4},
        '[0, 1, 0, 0]' : {'Outcome' : [0, 1, 0, 0], 'Count' : 5},
        '[1, 0, 1, 0]' : {'Outcome' : [1, 0, 1, 0], 'Count' : 5},  
        '[1, 0, 0, 0]' : {'Outcome' : [1, 0, 0, 0], 'Count' : 7},
        '[0, 1, 0, 1]' : {'Outcome' : [0, 1, 0, 1], 'Count' : 7},
        '[1, 0, 1, 1]' : {'Outcome' : [1, 0, 1, 1], 'Count' : 7},
        '[0, 0, 0, 0]' : {'Outcome' : [0, 0, 0, 0], 'Count' : 8},  
        '[1, 1, 1, 0]' : {'Outcome' : [1, 1, 1, 0], 'Count' : 5},
        '[0, 0, 0, 1]' : {'Outcome' : [0, 0, 0, 1], 'Count' : 10},
        '[0, 0, 1, 1]' : {'Outcome' : [0, 0, 1, 1], 'Count' : 4},
        '[0, 1, 1, 0]' : {'Outcome' : [0, 1, 1, 0], 'Count' : 9},  
        '[1, 0, 0, 1]' : {'Outcome' : [1, 0, 0, 1], 'Count' : 4},
        '[1, 1, 1, 1]' : {'Outcome' : [1, 1, 1, 1], 'Count' : 5},
        '[1, 1, 0, 1]' : {'Outcome' : [1, 1, 0, 1], 'Count' : 2}
    }
    
  • job.get_results_shots() : このメソッドは、各ショット結果の一覧を返します。 たとえば、前のジョブの結果は次のようになります。

    print(job.get_results_shots()) 
    
    [ [0, 1, 1, 1], [1, 0, 1, 1], [0, 0, 1, 1], [1, 1, 0, 1], [1, 0, 0, 0], [1, 0, 1, 1], [1, 1, 0, 1], ...]
    

Q# ジョブを含む Python を Azure Quantum に送信する

VS Code を使用して、Q# 操作を呼び出す Python プログラムを記述し、Python コマンドまたは Azure CLI を使用して Azure に接続し、ジョブを送信する方法について説明します。

前提条件

インストールの詳細については、「 VS Code での QDK のインストールを参照してください。

Q# 操作を作成してインポートする

qsharp パッケージを使用すると、関数と操作を Q# ファイルに格納し、python コードからそれらを呼び出すことができるQ# プロジェクトを作成できます。 これは、入力パラメーターを受け取るプログラムを起動する必要がある場合に特に役立ちます。

  1. Q# プロジェクトを作成する手順に従います

  2. 新しいテキスト ファイルを開き、ユーザー指定のランダム ビット数を返す次の Q# コードを追加し、source.qsとしてプロジェクトの /src ディレクトリにファイルを保存します。

    Note

    この Q# コードには、Q# プログラムのような @EntryPoint 関数はありません (Azure Quantum に Q# ジョブを送信する を参照してください)、Jupyter Notebook とは異なり、名前空間が必要です (Azure Quantum への Jupyter Notebook ジョブの送信 参照)。

    namespace Sample {
    
      operation Random() : Result {
            use q = Qubit();
            H(q);
            let result = M(q);
            Reset(q);
            return result
      }
    
      operation RandomNBits(N: Int): Result[] {
            mutable results = [];
            for i in 0 .. N - 1 {
               let r = Random();
               set results += [r];
            }
            return results
      }
    }
    
  3. ( qsharp.json ファイルを含む) プロジェクト ルート フォルダーで、別のファイルを開き、 randomNum.pyとして保存します。

  4. 次のコードを追加して、 qsharp モジュールと azure.quantum モジュールをインポートします。

    import qsharp
    import azure.quantum
    
  5. 次に、Q# プロジェクトのルート フォルダーを定義するコードを追加し、ローカル シミュレーターで target 操作をテスト実行します。 この操作は、 <namespace>.< によって呼び出されます。operation_name( )>。この場合、返されるランダム ビットの数を渡します。

    qsharp.init(project_root = '../MyProjectRootFolder')
    print(qsharp.eval("Sample.RandomNBits(4)"))
    
    [Zero, One, One, Zero]
    
  6. run メソッドを使用して操作をテストすることもできます。このメソッドは、追加の shots パラメーターを渡し、結果を Python リストで返します。 randomNum.pyで、前の print ステートメントを次のように置き換えます。

    result = qsharp.run("Sample.RandomNBits(4)", shots=10)
    for x in result:
        print(x)
    
    [[One, One, One, One],
    [Zero, Zero, One, Zero],
    [One, Zero, Zero, One],
    [Zero, One, Zero, Zero],
    [One, Zero, One, One],
    [One, Zero, One, Zero],
    [One, One, One, Zero],
    [One, One, One, One],
    [Zero, Zero, Zero, One],
    [One, Zero, Zero, One]]
    

基本プロファイルを使用してジョブをコンパイルする

ローカル量子シミュレーターでプログラムを実行する場合は、任意の種類の Q# プログラムを送信できます。 ただし、Azure Quantum ハードウェア targets では、すべての Q# プログラムを実行するために必要な完全な機能はまだサポートされていません。 Q# プログラムをコンパイルして Azure Quantum に送信するには、 target プロファイルを設定して、 target ハードウェアでサポートされている機能を Q# に通知する必要があります。 現在、これは Base プロファイルまたは Adpative_RI プロファイルです。 詳細については、「 Profile types in Azure Quantum」を参照してください。

Note

VS CodeQ# のみのプログラムの場合、VS Code はBase プロファイルを自動的に設定します。

  1. initメソッドを使用してプロファイルを設定します。

    qsharp.init(project_root = '../MyProjectRootFolder', target_profile=qsharp.TargetProfile.Base)
    

    Note

    qsharp 状態を再初期化するため、RandomNBits操作を見つける場所をコンパイラが認識できるように、project_root パラメーターをもう一度設定する必要があります。 これは、前の手順の手順 5 でも実行できました。

  2. 次に、 compile メソッドを使用して、プログラムへのエントリ ポイントである操作または関数を指定します。 コンパイルされたプログラムは、任意の量子ハードウェアに送信できます。

    MyProgram = qsharp.compile("Sample.RandomNBits(4)")
    

Azure Quantum に接続してジョブを送信する

Azure Quantum に接続し、Python で作成された Workspace オブジェクトを使用してジョブを送信するか、Azure CLI を使用して接続してジョブを送信できます。 Azure CLI を使用するには、コンパイル済みのプログラムをテキスト ファイルとして保存し、CLI コマンドを使用してそのファイルを送信する必要があります。

プログラムを正しい形式にコンパイルしたら、Azure Quantum に接続する azure.quantum.Workspace オブジェクトを作成します。 接続するには、Azure Quantum ワークスペースのリソース ID を使用します。 リソース ID と場所は、Azure portal のワークスペースの概要ページからコピーできます。

  1. 次のコードを randomNum.pyに追加し、Azure Quantum ワークスペースからリソース ID と場所を入力します。

    workspace = azure.quantum.Workspace(
        resource_id = "MyResourceID",
        location = "MyLocation"
    )
    
  2. get_targetsメソッドを使用して、ワークスペースで使用可能なハードウェア targetsを表示します。

    MyTargets = workspace.get_targets()
    print("This workspace's targets:")
    for x in MyTargets:
        print(x)
    
  3. rigetti.sim.qvmtargetを選択します。

    MyTarget = workspace.get_targets("rigetti.sim.qvm")
    
  4. 最後に、 submit メソッドを使用して、そのパラメーターを使用してプログラムを送信します。 ジョブの結果は Python ディクショナリとして返されます。

    job = MyTarget.submit(MyProgram, "MyPythonJob", shots=100)
    results = job.get_results()
    print("\nResults: ", results)
    
  5. 値だけを抽出して表示するには:

    for x in results:
        print(x)
    
    [0, 0, 0, 0]
    0.3
    [1, 0, 0, 0]
    0.1
    [1, 1, 1, 1]
    0.3
    [0, 1, 1, 1]
    0.3
    
  6. ジョブのすべてのプロパティに job.detailsでアクセスできます。次に例を示します。

    print(job.details)
    print("\nJob name:", job.details.name)
    print("Job status:", job.details.status)
    print("Job ID:", job.details.id)
    
    {'additional_properties': {'isCancelling': False}, 'id': '0fc396d2-97dd-11ee-9958-6ca1004ff31f', 'name': 'MyPythonJob', 'provider_id': 'rigetti'...}
    Job name: MyPythonJob
    Job status: Succeeded
    Job ID: fc396d2-97dd-11ee-9958-6ca1004ff31f
    

その他のジョブの詳細

azure.quantum Python パッケージには、より詳細なジョブ データを表示するための追加のメソッドが含まれています。

  • job.get_results_histogram():このメソッドは、各一意の測定の結果とショット数のディクショナリを返します。 たとえば、前のジョブの結果は次のようになります。

    results = job.get_results_histogram()
    for x in results.items():
        print(x)
    
    {   
        '[0, 0, 0, 0]' : {'Outcome' : [0, 0, 0, 0], 'Count' : 30},  
        '[1, 0, 0, 0]' : {'Outcome' : [1, 0, 0, 0], 'Count' : 10},
        '[1, 1, 1, 1]' : {'Outcome' : [1, 1, 1, 1], 'Count' : 30},
        '[0, 1, 1, 1]' : {'Outcome' : [0, 1, 1, 1], 'Count' : 30}
    }
    
  • job.get_results_shots() : このメソッドは、各ショット結果の一覧を返します。 たとえば、前のジョブの結果は次のようになります。

    print(job.get_results_shots()) 
    
    [ [0, 0, 0, 0], [1, 1, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1], [1, 0, 0, 0], [0, 1, 1, 1], [0, 0, 0, 0], ...]