A cute robot building itself with artificial intelligence, pencil drawing - DALL·E 2

Hierarchical Quantum Circuit Representations

A cute robot building itself with artificial intelligence, pencil drawing - DALL·E 2

Hierarchical Quantum Circuit Representations

A cute robot building itself with artificial intelligence, pencil drawing - DALL·E 3

Outline


HierarQcal
Hierarchical Quantum Circuit Representations
Design and implement hierarchical compute graphs Theoretical framework behind package
This talk
  • Background
  • Overview of Representation
  • Results and usage

Background

Neural Networks


AlexNet


Automation


Manual
$\rightarrow$ Feature Engineering
Automated

Automation


Manual
$\rightarrow$ Architecture Engineering?
Automated

Neural Architecture Search


$^*$Fig: Abstract illustration of Neural Architecture Search methods. A search strategy selects an architecture A from a predefined search space A. The architecture is passed to a performance estimation strategy, which returns the estimated performance of A to the search strategy.

Neural Architecture Search


$^*$Fig: An illustration of different architecture spaces. Each node in the graphs corresponds to a layer in a neural network, e.g., a convolutional or pooling layer. Different layer types are visualized by different colors. An edge from layer $L_i$ to layer $L_j$ denotes that $L_j$ receives the output of $L_i$ as input. Left: an element of a chain-structured space. Right: an element of a more complex search space with additional layer types and multiple branches and skip connections.

Neural Architecture Search


$^*$Fig: An example of a three-level hierarchical architecture representation. The bottom row shows how level-1 primitive operations $o^{(1)}_1$ , $o^{(1)}_2$ , $o^{(1)}_3$ are assembled into a level-2 motif $o^{(2)}_1$ . The top row shows how level-2 motifs $o^{(2)}_1$ , $o^{(2)}_2$ , $o^{(2)}_3$ are then assembled into a level-3 motif $o^{(3)}_1$.
Ansatz Design

Ansatz Design


$^*$Fig: The concept of QCNNs. $a$, Simplified illustration of classical CNNs. A sequence of image-processing layers transforms an input image into a series of feature maps (blue rectangles) and finally into an output probability distribution (purple bars). C, convolution; P, pooling; FC, fully connected. $b$, QCNNs inherit a similar layered structure. Boxes represent unitary gates or measurement with feed-forwarding. c, The QCNN and the MerA share the same circuit structure, but run in reverse directions.

Ansatz Design


$^*$Fig: TTN and MERA classifiers for eight qubits. The quantum circuit is illustrated by the regions outlined in solid lines comprising inputs $\psi$, unitary blocks $\{U_i\}_{i=1}^7$ and $\{D_i\}_{i=1}^4$, and a measurement operator M. The dashed lines represent its conjugate transpose. The solid and dashed regions together describe a tensor network operating on input $\psi_{1-8}$ and evaluating to the expectation value of observable $M$

Representation

Motifs


Motifs


Motifs


Motifs


Motifs


Motifs


Motifs


Motifs


Motifs


Motifs


Motifs


Examples


								
									hierq = Qinit(5)
									hierq = Qinit(5) + Qcycle(stride=1, step=1, offset=0)
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0)
								
							

Examples


								
									hierq = Qinit(5)
									hierq = Qinit(5) + Qcycle(stride=1, step=1, offset=0)
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0)
								
							

Examples


								
									hierq = Qinit(5) + Qcycle(stride=1, step=1, offset=0)
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0)
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0, boundary="open")
								
							

Examples


								
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0)
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=2, step=1, offset=0, boundary="open")
								
							

Examples


								
									hierq = Qinit(8) + Qcycle(stride=1, step=1, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=2, step=1, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=3, step=1, offset=0, boundary="open")
								
							

Examples


								
									hierq = Qinit(8) + Qcycle(stride=2, step=1, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=3, step=1, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=1, step=2, offset=0, boundary="open")
								
							

Examples


								
									hierq = Qinit(8) + Qcycle(stride=3, step=1, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=1, step=2, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=1, step=3, offset=0, boundary="open")
								
							

Examples


								
									hierq = Qinit(8) + Qcycle(stride=1, step=2, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=1, step=3, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=1, step=3, offset=1, boundary="open")
								
							

Examples


								
									hierq = Qinit(8) + Qcycle(stride=1, step=3, offset=0, boundary="open")
									hierq = Qinit(8) + Qcycle(stride=1, step=3, offset=1, boundary="open")
									hierq = Qinit(8) + Qcycle(1,1,0, mapping = u2)
								
							

Examples


																	
									hierq = Qinit(8) + Qcycle(1,1,0, mapping = u2)
									hierq(backend="qiskit")
									hierq(backend="pennylane")
								
							

Examples


																	
									hierq = Qinit(8) + Qcycle(1,1,0, mapping = u2)
									hierq(backend="qiskit")
									hierq(backend="pennylane")
								
							

Examples


																	
									hierq = Qinit(8) + Qmask("10100000")
									hierq = Qinit(8) + Qmask("1*")
									hierq = Qinit(8) + Qmask("!00")
								
							

Examples


																	
									hierq = Qinit(8) + Qmask("10100000")
									hierq = Qinit(8) + Qmask("1*")
									hierq = Qinit(8) + Qmask("!00")
								
							

Examples


								
									hierq = Qinit(8) + Qmask("1*")
									hierq = Qinit(8) + Qmask("!00")
									hierq = Qinit(8) + Qmask("!*")
								
							

Examples


																	
									hierq = Qinit(8) + Qmask("!00")
									hierq = Qinit(8) + Qmask("!*")
									hierq = Qinit(8) + Qcycle(mapping = u2) + Qmask("*!") + Qcycle(mapping = u2)
								
							

Examples


																
									hierq = Qinit(8) + Qcycle(mapping = u2) + Qmask("*!") + Qcycle(mapping = u2)
								
							

Examples


																
									cycle = Qcycle(mapping = u2)
									hierq = Qinit(8) + cycle + Qmask("*!", mapping=v2) + cycle
								
							

Examples


																
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!", mapping=v2)
									hierq = Qinit(8) + cycle_mask
									hierq = Qinit(8) + cycle_mask * 3
								
							

Examples


																
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!", mapping=v2)
									hierq = Qinit(8) + cycle_mask
									hierq = Qinit(8) + cycle_mask * 3
								
							

Examples


																
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!", mapping=v2)								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*!", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!*", mapping=v2)									
									hierq = Qinit(8) + cycle_mask * 3
								
							

Examples


								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!", mapping=v2)								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*!", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!*", mapping=v2)									
									hierq = Qinit(8) + cycle_mask * 3
								
							

Examples


								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!", mapping=v2)								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*!", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!*", mapping=v2)									
									hierq = Qinit(8) + cycle_mask * 3
								
							

Examples


								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!", mapping=v2)								
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("!*!", mapping=v2)
									cycle_mask = Qcycle(1, 1, 0, mapping=u2) + Qmask("*!*", mapping=v2)									
									hierq = Qinit(8) + cycle_mask * 3
								
							

Results and Usage

Music Genre Classification


Random Search


									
										# Example Search Space
										strides = range(1, 8, 1)
										steps = range(1, 8, 1)
										mappings = [a, b, c, d, e, f, g, h]
										boundaries = ["open", "periodic"]
										patterns = ["10", "01", "*!", "!*", "!*!", "*!*"]

										qcnn = Qinit(8) + (Qcycle(...) + Qmask(...)) * 3
									
								

Music Genre Classification


$^*$Reference Architecture:
Ansatz:

Evolutionary Search

Evolutionary Search


Tournament Selection


Tournament Selection


Mutation
Crossover

Repeat


Quantum Phase Recognition


Cluster-Ising Hamiltonian: \[ \begin{align} H & = -J\sum_{i=1}^{N-2} Z_iX_{i+1}Z_{i+2} - h_1\sum_{i=1}^{N} X_i - h_2\sum_{i=1}^{N-1} X_iX_{i+1}.\nonumber \end{align} \]
  • Given an unknown ground state $\ket{\psi_g}$, what is the phase?
    • Paramagnetic
    • $\mathbb{Z_2}\times\mathbb{Z_2}$ Symmetry-Protected Topological (SPT)
    • Antiferromagnetic

Quantum Phase Recognition


									
											u0 = Qinit(4) + Qpermute(share_weights=False, mapping=Ugm)
											u1 = Qcycle(1,3,2, mapping=u0, boundary="open", edge_order=[1,3,2,4])
											u2 = sum([Qcycle(1,3,offset, mapping=Ugm, boundary="open") for offset in range(3)])
											u3 = Qmask("101",1,3,0, mapping=Vgm, boundary="open")
											u4 = Qcycle(1, mapping=Ugm, boundary="open")
											motif = Qinit(15) + u1 + u2 + u3 + u4
										
									

Quantum Phase Recognition


Reference1
$\rightarrow$
Found2

Quantum Phase Recognition


Found:

What's next?


Compute Graph Design
  • Quantum Circuits
  • Classical Circuits
  • Tensor Networks
  • Neural Networks
Exponentiation modulo $N$
Addition
																	
									def or(bits, symbols=None, state=None):
										b1, b2 = state[bits[0]], state[bits[1]]
										state[bits[0]] = b1 or b2
										return state				
									
								
																			
										tensors = [np.array([1, 0])] * 5     
										hierq = (Qinit(5, tensors=tensors)   
													 + mask_anc   
													 + U_psi + grover)  
										psi = hierq()			
									
								
?
Paper
Hierarqcal
Slides

Programming

Shor's Algorithm


  • Modular Exponentiation
  • Quantum Fourier Transform

Shor's Algorithm


  • Modular Exponentiation
    • Ctrl-Mult modulo $N$
  • Quantum Fourier Transform

Shor's Algorithm


  • Modular Exponentiation
    • Ctrl-Mult modulo $N$
      • Addition modulo $N$
  • Quantum Fourier Transform

Shor's Algorithm


  • Modular Exponentiation
    • Ctrl-Mult modulo $N$
      • Addition modulo $N$
        • Addition
  • Quantum Fourier Transform

Shor's Algorithm


  • Modular Exponentiation
    • Ctrl-Mult modulo $N$
      • Addition modulo $N$
        • Addition
          • Carry
          • xor
  • Quantum Fourier Transform

Shor's Algorithm


  • Modular Exponentiation
    • Ctrl-Mult modulo $N$
      • Addition modulo $N$
        • Addition
          • Carry
            • cnot
            • Toffoli
          • xor
            • cnot
  • Quantum Fourier Transform

Shor circuit


									
										# ====== Motifs level 1
										carry_motif = (
											Qinit(4)
											+ Qmotif(E=[(1, 2, 3)], mapping=toffoli)
											+ Qmotif(E=[(1, 2)], mapping=cnot)
											+ Qmotif(E=[(0, 2, 3)], mapping=toffoli)
										)
		
										# Turn carry into a function to be able to reverse it easily
										carry = lambda r: carry_motif if r == 1 else carry_motif.reverse()
										plot_circuit(carry(1))
										plot_circuit(carry(-1))
									
								

Shor circuit


									
										# ====== Motifs level 1
										carry_motif = (
											Qinit(4)
											+ Qmotif(E=[(1, 2, 3)], mapping=toffoli)
											+ Qmotif(E=[(1, 2)], mapping=cnot)
											+ Qmotif(E=[(0, 2, 3)], mapping=toffoli)
										)
		
										# Turn carry into a function to be able to reverse it easily
										carry = lambda r: carry_motif if r == 1 else carry_motif.reverse()
										plot_circuit(carry(1))
										plot_circuit(carry(-1))
									
								

Shor circuit


									
										# ====== Motifs level 1
										sum = lambda r=1: Qinit(3, name=f"sum") + Qpivot(
											"*1", merge_within="01", mapping=cnot, edge_order=[-1 * r]
										)

										plot_circuit(sum(1))
										plot_circuit(sum(-1))
									
								

Shor circuit


									
										# ====== Motifs level 1
										sum = lambda r=1: Qinit(3, name=f"sum") + Qpivot(
											"*1", merge_within="01", mapping=cnot, edge_order=[-1 * r]
										)

										plot_circuit(sum(1))
										plot_circuit(sum(-1))
									
								

Shor circuit


									
										# ====== Motifs level 2
										carry_sum_motif = (
											lambda r=1: Qinit(4, name=f"crs")
											+ Qpivot("1*", merge_within="1111", mapping=carry(-r))
											+ Qpivot("1*", merge_within="111", mapping=sum(r))
										)
		
										carry_sum = lambda r=1: carry_sum_motif(1) if r == 1 else carry_sum_motif(-1).reverse()

										plot_circuit(carry_sum(1))
										plot_circuit(carry_sum(-1))
									
								

Shor circuit


									
										# ====== Motifs level 2
										carry_sum_motif = (
											lambda r=1: Qinit(4, name=f"crs")
											+ Qpivot("1*", merge_within="1111", mapping=carry(-r))
											+ Qpivot("1*", merge_within="111", mapping=sum(r))
										)
		
										carry_sum = lambda r=1: carry_sum_motif(1) if r == 1 else carry_sum_motif(-1).reverse()

										plot_circuit(carry_sum(1))
										plot_circuit(carry_sum(-1))
									
								

Shor circuit


									
										cnot_sum_motif = (
											lambda r=1: Qinit(3, name=f"cns")
											+ Qpivot("*1", merge_within="11", mapping=cnot)
											+ Qpivot("*1", merge_within="111", mapping=sum(r))
										)
		
										cnot_sum = lambda r=1: cnot_sum_motif(1) if r == 1 else cnot_sum_motif(-1).reverse()

										plot_circuit(cnot_sum(1))
										plot_circuit(cnot_sum(-1))
									
								

Shor circuit


									
										cnot_sum_motif = (
											lambda r=1: Qinit(3, name=f"cns")
											+ Qpivot("*1", merge_within="11", mapping=cnot)
											+ Qpivot("*1", merge_within="111", mapping=sum(r))
										)
		
										cnot_sum = lambda r=1: cnot_sum_motif(1) if r == 1 else cnot_sum_motif(-1).reverse()

										plot_circuit(cnot_sum(1))
										plot_circuit(cnot_sum(-1))
									
								

Shor circuit


									
										# ====== Motifs level 3
										carry_layer = lambda r=1: Qcycle(
											1,
											3,
											0,
											mapping=carry(r),
											boundary="open",
											edge_order=[r],
										)
										plot_circuit(carry_layer_1)
									
								

Shor circuit


									
										cnot_sum_pivot = lambda r: Qpivot("*10", merge_within="111", mapping=cnot_sum(r))

										plot_circuit(Qinit(6) + cnot_sum_pivot(1))
										plot_circuit(Qinit(8) + cnot_sum_pivot(1))
									
								

Shor circuit


									
										cnot_sum_pivot = lambda r: Qpivot("*10", merge_within="111", mapping=cnot_sum(r))

										plot_circuit(Qinit(6) + cnot_sum_pivot(1))
										plot_circuit(Qinit(8) + cnot_sum_pivot(1))
									
								

Shor circuit


									
										carry_sum_layer = lambda r: (
											Qmask("*111")
											+ Qcycle(1,	3, 0,
												boundary="open",
												mapping=carry_sum(r),
												edge_order=[-r],
											)
											+ Qunmask("previous")
										)		
										plot_circuit(Qinit(10) + carry_sum_layer(1))
									
								

Shor circuit


									
										addition = carry_layer(1) + cnot_sum_pivot(1) + carry_sum_layer(1)
										subtraction = carry_sum_layer(-1) + cnot_sum_pivot(-1) + carry_layer(-1)
		
										plot_circuit(Qinit(11) + addition)
										plot_circuit(Qinit(11) + subtraction)
										plot_circuit(Qinit(13) + addition)
										plot_circuit(Qinit(13) + subtraction)
									
								

Shor circuit


									
										addition = carry_layer(1) + cnot_sum_pivot(1) + carry_sum_layer(1)
										subtraction = carry_sum_layer(-1) + cnot_sum_pivot(-1) + carry_layer(-1)
		
										plot_circuit(Qinit(11) + addition)
										plot_circuit(Qinit(11) + subtraction)
										plot_circuit(Qinit(13) + addition)
										plot_circuit(Qinit(13) + subtraction)
									
								

Shor circuit


									
										addition = carry_layer(1) + cnot_sum_pivot(1) + carry_sum_layer(1)
										subtraction = carry_sum_layer(-1) + cnot_sum_pivot(-1) + carry_layer(-1)
		
										plot_circuit(Qinit(11) + addition)
										plot_circuit(Qinit(11) + subtraction)
										plot_circuit(Qinit(13) + addition)
										plot_circuit(Qinit(13) + subtraction)
									
								

Shor circuit


									
										addition = carry_layer(1) + cnot_sum_pivot(1) + carry_sum_layer(1)
										subtraction = carry_sum_layer(-1) + cnot_sum_pivot(-1) + carry_layer(-1)
		
										plot_circuit(Qinit(11) + addition)
										plot_circuit(Qinit(11) + subtraction)
										plot_circuit(Qinit(13) + addition)
										plot_circuit(Qinit(13) + subtraction)
									
								

Shor circuit


									
										exp_mod_n = tuple()
										for k in range(n):
											exp_mod_n += (
												Qpivot(mapping=ctrl_mult(a ** (2**k), N, n, ctrl=k, divide=False))
												+ swap_bx
												+ Qpivot(mapping=ctrl_mult(a ** (2**k), N, n, ctrl=k, divide=True))
											)
										
										hierq = Qinit(nq, tensors=tensors) + exp_mod_n
									
								
Quantum Fourier Transform

Quantum Fourier Transform


									
										# QFT circuit
										n = 4
										qft = (
											Qpivot(mapping=Qunitary("h()^0"))
											+ Qpivot(
												mapping=Qunitary("cp(x)^01"),
												share_weights=False,
												symbol_fn=lambda x, ns, ne: np.pi * 2 ** (-ne),
											)
											+ Qmask("1*")
										) * n
										qft_n = Qinit(n) + qft
										
										circuit_qft = qft_n(backend="qiskit", barriers=False)
										circuit_qft.draw("mpl")
									
								
Classical Adder

Classical Adder


									
									def half_adder(bits, symbols=None, state=None):
										b1, b2 = state[bits[0]], state[bits[1]]
										xor = b1 ^ b2
										carry = b1 and b2
										state[bits[0]] = carry
										state[bits[1]] = xor
										return state
									
									def or_top(bits, symbols=None, state=None):
										b1, b2 = state[bits[0]], state[bits[1]]
										state[bits[0]] = b1 or b2
										return state				
									
								

Classical Adder


									
									def half_adder(bits, symbols=None, state=None):
										b1, b2 = state[bits[0]], state[bits[1]]
										xor = b1 ^ b2
										carry = b1 and b2
										state[bits[0]] = carry
										state[bits[1]] = xor
										return state
									
									def or_top(bits, symbols=None, state=None):
										b1, b2 = state[bits[0]], state[bits[1]]
										state[bits[0]] = b1 or b2
										return state				
									
								

Classical Adder


															
								# program
								full_adder = (
									Qinit(3)
									+ Qcycle(mapping=half_adder, boundary="open")
									+ Qpivot(global_pattern="1*", merge_within="11"
												,mapping=or_top)
								)
								addition = (
									Qinit(n)
									+ Qpivot("*1", "11", mapping=half_adder)
									+ Qcycle(step=2,
											 edge_order=[-1],
											 mapping=full_adder,
											 boundary="open")
								)