3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GQCIRQ: Goで量子回路を描く

Last updated at Posted at 2025-12-20

はじめに

大阪大学で量子コンピューティングのオープンソース・ソフトウェアスタックOQTOPUSの開発をしているmassnです。
OQTOPUSのoqtopus-engineはマイクロサービス内の各モジュールの取り回しの
しやすさからGo言語で実装されています。このプロジェクトでは、直接、量子回路をGoで操作する処理はないですが、慣れ親しんだ言語で量子回路を操作してみたいと思い、Goで量子回路を描画するライブラリ gqcirc を作成しました。内部では量子回路をJSON形式で表現するデータ構造も定義し、様々な環境で量子回路を扱いやすくできればなと思っています。
量子コンピュータのシミュレータと組み合わせた発展的な使い方も最後に紹介いたします。

クイックスタート

まずは用意されたプログラムを実行して簡単な機能を見ていきたいと思います。
https://github.com/massn/gqcirc で公開しているのでまずはgit cloneしてください。

git clone https://github.com/massn/gqcirc.git
cd gqcirc

Draw機能

gqcircでは直線や円、テキストなどの基本的な図形を組み合わせて量子回路を描画しています。内部ではdraw2d というGoのベクターグラフィックスライブラリを利用していますが、特に意識せずに使えます。

JSONで定義された以下のような量子回路のデータ構造

{
  "width": 4,
  "inits": ["0", "1", "+", "0"],
  "ops": [
    {
      "type": "gate",
      "target_qubit": 0,
      "name": "h"
    },
    {
      "type": "gate",
      "target_qubit": 1,
      "name": "x"
    },
...
}

を描画するには、

cd example/draw
go run main.go

を実行してみてください。同一ディレクトリに draw.svg という名前で量子回路が描画されたSVGファイルが生成されます。

draw.png

taskというタスクランナーを導入されていれば、同様の処理がトップディレクトリから

task draw

で実行できます。

描画の設定は Config struct と DiagramConfig struct で行えます。

type Config struct {
  FontPath string
  OutputSVGPath string
}

type DiagramConfig struct {
  Margin float64
  LineSpacing float64
  TimeSpacing float64
  GateBlockSize float64
  FontName string
  FontSize int
  ShowBarriers bool
  BarrierLineOffset float64
  CxRadius float64
  MeasureRadius float64
  MeasureCenterOffsetY float64
  MeasureZeroOffset float64
  MeasurePointerOffset float64
  MeasurePointerLength float64
  Scale float64
}

DiagramConfig struct の各フィールドを調整することで、量子回路の見た目を変更できます。基本的にはデフォルトの設定で、 Config.OutputSVGPath を設定して保存先を変更するだけで十分です。

Marshal機能

次は、Goのデータ構造をJSON形式に変換する機能を見てみましょう。
元になるGoのデータ構造は以下のようになっています。

&gqcirc.QC{
	Width: 4,
	Ops: []gqcirc.Op{
		&gqcirc.Gate{
			TargetQubit: uint32Ptr(0),
			Name:        "h",
		},
		&gqcirc.Gate{
			TargetQubit: uint32Ptr(1),
			Name:        "x",
		},
		&gqcirc.Gate{
			TargetQubit: uint32Ptr(0),
			Name:        "z",
		},
...

これをJSON形式に変換するには、

cd gqcirc/example/marshal
go run main.go

を実行してみてください。標準出力にJSON形式で量子回路が出力されます。

{
  "width": 4,
  "ops": [
    {
      "type": "gate",
      "target_qubit": 0,
      "name": "h"
    },
    {
      "type": "gate",
      "target_qubit": 1,
      "name": "x"
    },
    {
      "type": "gate",
      "target_qubit": 0,
      "name": "z"
    },
...

taskで実行する場合は、

task marshal

を実行してください。

量子回路のデータ構造

ライブラリ内部での量子回路の表現方法について説明します。

QC

gqcirc/qc.go に量子回路を表現するためのstruct QC が定義されています。

type QC struct {
	Width uint32   `json:"width"`
	Inits []string `json:"inits,omitempty"`
	Ops   Ops      `json:"ops"`
}
  • Width: 量子ビット数
  • Inits: 量子ビットの初期状態
    • 01+-i-i などの任意の文字列を指定できます。描画されるとブラケット内に配置されます。
  • Ops: 量子ゲートや測定、バリアなどの操作のリスト
    • Op のスライスで定義されています。Op については次のセクションで説明します。

Op

Op は量子回路上の操作を表現するためのinterfaceです。以下のstructで実装されています。

Gate

量子ゲートを表現するためのstructです。

type Gate struct {
	OpType        string    `json:"type" mapstructure:"type"`
	ControlQubits []*uint32 `json:"control_qubits,omitempty" mapstructure:"control_qubits"`
	TargetQubit   *uint32   `json:"target_qubit" mapstructure:"target_qubit"`
	Name          string    `json:"name" mapstructure:"name"`
}
  • OpType: SetType() を使うことで常に "gate" が指定されます。
  • ControlQubits: 制御量子ビットのインデックスのスライス。
  • TargetQubit: ターゲット量子ビットのインデックス。制御量子ビットがない場合は、操作対象の量子ビットになります。
  • Name: 任意の量子ゲートの名前。例えば、hxcx など。

Measure

量子ビットの測定を表現するためのstructです。

type Measure struct {
	OpType      string  `json:"type" mapstructure:"type"`
	TargetQubit *uint32 `json:"target_qubit" mapstructure:"target_qubit"`
}
  • OpType: SetType() を使うことで常に "measure" が指定されます。
  • TargetQubit: 測定対象の量子ビットのインデックス。

Barrier

量子ビット間のバリアを表現するためのstructです。

type Barrier struct {
	OpType string `json:"type" mapstructure:"type"`
}
  • OpType: SetType() を使うことで常に "barrier" が指定されます。

量子ゲートの並べ方について

Op のスライスは、量子回路の上の量子ビットから Op が順番に適用されるように並べられています。
しかし、量子計算上の意味が同じでも、量子ゲートを縦一列に並べたいことがあります。

例えば、以下のような量子回路を考えます。

{
  "width": 3,
  "inits": ["0", "1", "+", "0"],
  "ops": [
    "type": "gate",
    "target_qubit": 0,
    "name": "A1"
  },
  {
    "type": "gate",
    "target_qubit": 1,
    "name": "A2"
  },
  {
    "type": "gate",
    "target_qubit": 0,
    "name": "B1"
  },
  {
    "type": "gate",
    "target_qubit": 1,
    "name": "B2"
  },
  {
    "type": "gate",
    "target_qubit": 2,
    "name": "C"
  }
]

bar_test.png

このとき、CB1B2 の下に揃えたいことがあります。
そのときは BarrierA1A2 の後ろに置くと、それ以降の量子ゲートは次の列に並ばせることができます。

{
  "width": 3,
  "inits": ["0", "1", "+", "0"],
  "ops": [
    "type": "gate",
    "target_qubit": 0,
    "name": "A1"
  },
  {
    "type": "gate",
    "target_qubit": 1,
    "name": "A2"
  },
  {
    "type": "gate",
    "target_qubit": 0,
    "name": "B1"
  },
  {
    "type": "gate",
    "target_qubit": 1,
    "name": "B2"
  },
  {
    "type": "barrier",
  },
  {
    "type": "gate",
    "target_qubit": 2,
    "name": "C"
  }
]


bar_test2.png

BarrierをConfigを使って見えないようにするとすっきりします。

conf.ShowBarriers = false

bar_test3.png

発展:量子計算と同時に量子回路描画

Goの量子計算シミュレータにqというライブラリがあります。
このライブラリとgqcircを組み合わせて、量子計算の結果を量子回路として描画する例を紹介します。
gacirc/example/q というディレクトリにサンプルコードを用意しています。

import (
	"fmt"

	"github.com/itsubaki/q"
	"github.com/massn/gqcirc"
)
...

type QCembed struct {
	*gqcirc.QC
	*q.Q
}

以上のようにq.Qgqcirc.QCを埋め込んだ構造体を定義します。
各量子ゲートを以下のように定義してやる必要があるので少し面倒くさもありますが、最初だけなので。

func (qce *QCembed) H(qb ...q.Qubit) *QCembed {
	for _, v := range qb {
		qce.Q.H(v)
		qce.QC.Ops = append(qce.QC.Ops, &gqcirc.Gate{
			Name:        "H",
			TargetQubit: uint32Ptr(uint32(v.Index())),
		})
	}
	return qce
}

おわりに

量子回路をGoで描画するライブラリ gqcirc を紹介しました。
この名前はGeneral/Go Quantum Circuitの略となっていて、様々な環境で量子回路を取り扱いやすくなることも目指しています。
量子回路の表現としてはOpenQASMが有名ですが、JSON形式で量子回路を表現することで、より柔軟に量子回路を取り扱えるようになることを期待しています。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?