# Non-qiskit imports
import math
import numpy as np
import matplotlib.pyplot as plt
# Imports from Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.library import GroverOperator, MCMT, ZGate, XGate
from qiskit.visualization import plot_histogram
from qiskit.quantum_info import Statevector
# Imports from Qiskit Simulator
from qiskit_aer import AerSimulator
from qiskit import transpile
Grover’s Search Algorithm
Clasical Search for Unsorted Data
# Create a graph which shows the difference between O(N) and O(sqrt(N))
# compitational efficiency which searching through large lists
# Create a variable for the size of the list, holding data from 10^1 to
# 10^10. There are 50 total points
= np.logspace(1, 10, 50)
x
# Classical scaling for an unsorted search algorithm is O(N)
= x
classical # Quantum scaling for an unsorted search algorithm is O(sqrt(N))
= np.sqrt(x)
quantum
# Plot the computational efficiencies, format the graph, add labels and a legend
=2, color="darkred", label="Classical")
plt.plot(x,classical, linewidth=2, color="darkblue", linestyle="--", label="Quantum")
plt.plot(x,quantum, linewidth="serif")
plt.xticks(fontfamily="serif")
plt.yticks(fontfamily"Number of Elements in List", fontsize=14, fontfamily="serif")
plt.xlabel("Computational Efficiency", fontsize=14, fontfamily="serif")
plt.ylabel(={'family':"serif", 'size':12})
plt.legend(prop
# Save the image
"grover_comp_eff.png", dpi=1000) plt.savefig(
##############################
## LINEAR SEARCH VERSION 1 ##
##############################
def linear_search_version_1 (my_list, element):
"""
Brute force search of an element in a list. The list
does not have to be sorted
Inputs:
my_list (a list)
element (int/float/string): the element to be found in the list
Returns
i (an int): returns the index where the element was found, returns
-1 if the element was not found
"""
= len(my_list)
length for i in range(length):
if my_list[i] == element:
return i
return -1
##############################
## MAKE SEARCH LIST ##
##############################
def make_search_list (length, max_val, ensured_val):
"""
Creates a list of integers of a given length between zero and one less than
the maximum value passed. Then, it ensures that a given value is randomly placed
in the list
Inputs:
length (an int): the length of the list
max_val (an int): the maximum value (+1) to include in the list of integers
ensured_val (int/float): the value to make sure is in the list
Returns:
my_list(a numpy array): a list of integers with the wanted element randomly placed
in the list
"""
= np.random.randint(0, max_val, length)
my_list = np.random.randint(length)
random_index = ensured_val
my_list[random_index] return my_list
## Create unsorted list to search through
= int(1e5)
n = make_search_list(n, n, 3)
my_list
print((my_list==3).sum()) # Print the number of occurrences of the wanted element
2
%%time
# Perform a linea search on the list
print(linear_search_version_1(my_list, 3)) # Does not have to be sorted for linear search
5371
CPU times: user 3.58 ms, sys: 171 µs, total: 3.76 ms
Wall time: 1.34 ms
##############################
## LINEAR SEARCH VERSION 2 ##
##############################
def linear_search_version_2 (my_list, element):
"""
Brute force search of an element in a list. The list
does not have to be sorted. Return a list where the element
is 1 if it is in the same location as the wanted element, 0 if not
Inputs:
my_list (a list)
element (int/float/string): the element to be found in the list
Returns:
results (a list): if the wanted element is found at a given index, then
the element at the same index in results is 1. Otherwise, results has
a zero at the element
"""
= len(my_list)
length = np.zeros(length)
results for i in range(length):
if my_list[i] == element:
= 1
results[i] return results
## Create a test list
= int(1e5)
n = make_search_list(n, n, 3)
my_list
print((my_list==3).sum()) # Print the number of occurrences of the wanted element
1
%%time
# Plot the results
= linear_search_version_2(my_list, 3) # Does not have to be sorted for linear search
results range(n), results) plt.plot(
CPU times: user 115 ms, sys: 6.06 ms, total: 121 ms
Wall time: 50 ms
Two Qubit Example
This code is modified from the archived Qiskit textbook. The original algorithm, as proposed by Grover, can be found in this paper.
# Define a two qubit quantum circuit
= 2
n = QuantumRegister(n)
q = ClassicalRegister(n)
c = QuantumCircuit(q,c)
grover_circuit
# Add Hadamard gates to both bits
range(n))
grover_circuit.h(
grover_circuit.barrier()
# The oracle is simply a controlled Z gate as
# this will add a phase of pi (phase = e^(i\pi))
# to the wanted state only (wanted state is |11>)
0,1) # Oracle
grover_circuit.cz(
grover_circuit.barrier()
# Now add the amplification operator for a two
# qubit system
# Hadamard gates to all qubits
0,1])
grover_circuit.h([# NOT gates to all qubits
0,1])
grover_circuit.x([# Controlled Z where the last qubit is the target,
# the first qubit is the control
0,1)
grover_circuit.cz(# NOT gates to all qubits
0,1])
grover_circuit.x([# Hadamard gates to all qubits
0,1])
grover_circuit.h([
grover_circuit.barrier()
# Measure the state of the qubits
range(n), range(n))
grover_circuit.measure(
# Draw the circuit
="mpl") grover_circuit.draw(output
# Simulate the circuit with no need to transpile since there are no combination
# gates, the only result should be the desired state
= AerSimulator()
simulator = simulator.run(grover_circuit).result().get_counts()
results plot_histogram(results)
General Case
This code is modified from this project created by Qiskit. Additional code is modified from the archived Qiskit textbook.
Note that Qiskit has many built-in Grover’s algorithm functions. Here we will be creating our own oracle but will use Qiskit’s amplification code.
All Individual Gates
Here we will build the Grover’s algorithm oracle and amplification circuits using base gates
def grover_oracle(qc, num_qubits, marked_states):
"""
Create a Grover's algorithm oracle for the general case of finding some number
of marked strings from a list of all possible binary strings fo a given length.
Inputs:
qc (a qiskit circuit): The qiskit circuit to add the oracle to
num_qubits (an int): The number of qubits in the circuit
marked_states (a list): the states to mark for the grover's Algorithm to find
"""
# Create a barrier to mark the start of the algorithm
qc.barrier()
# Mark each target state in the input list
for target in marked_states:
# Flip target bit-string to match Qiskit bit-ordering
= target[::-1]
rev_target
# Find the indices of all the '0' elements in bit-string
# NOT gate will be placed at these values
# NOTE ERRORS OUT IF NO 0 STATES FOUND IN STATE FIX THIS
= [ind for ind in range(num_qubits) if rev_target.startswith("0", ind)]
zero_inds
# Add a multi-controlled Z-gate with pre- and post-applied X-gates (open-controls)
# where the target bit-string has a '0' entry (i.e. we want all qubits to be 1 before the
# controlled Z gate is applied)
# Try/Except statement handles the case when one of the marked strings does not contain
# any zeros
try:
qc.x(zero_inds)except:
None
# Create a multi-controlled Z-gate where the very last qubit is the target qubit
# and all other qubits are the control qubits
- 1, 1), inplace=True)
qc.compose(MCMT(ZGate(), num_qubits
try:
qc.x(zero_inds)except:
None
# Create a barrier to separate the circuit to mark each of the desired states
qc.barrier()
def grover_amplification(qc, num_qubits):
"""
Create a Grover's algorithm amplitude amplification for the general case of finding
some number of marked strings from a list of all possible binary strings fo a given
length.
Inputs:
qc (a qiskit circuit): The qiskit circuit to add the oracle to
num_qubits (an int): The number of qubits in the circuit
"""
# Create a barrier to mark the start of the amplitude amplification algorithm
qc.barrier()
# Hadamard gates and then NOT gates for all qubits
# followed by barier to separate the next part of the algorithm
range(num_qubits))
qc.h(range(num_qubits))
qc.x(
qc.barrier()
# multi-controlled Z gate where the last qubit is the target and all other
# qubits are the control
- 1, 1), inplace=True)
qc.compose(MCMT(ZGate(), num_qubits
# barier to separate the next part of the algorithm
# Hadamard gates and then NOT gates for all qubits
qc.barrier()range(num_qubits))
qc.x(range(num_qubits))
qc.h(
# Barrier to mark the end of the amplitude amplification algorithm
qc.barrier()
# Create a list of marked states to find in the list
# all strings in the list must be the same length
= ["111"]
marked_states
# Create a circuit where there are the same number of qubits
# as there are numbers in the marked states
= len(marked_states[0])
n = QuantumRegister(n)
q = ClassicalRegister(n)
c = QuantumCircuit(q,c)
grover_circuit
# Add an initial set of Hadamard gates to out everything into
# a superposition
range(n))
grover_circuit.h(
# Find the optimal number of iterations for the Grover's algorithm
# based on the number of states to find and the number of qubits in
# the system. Floor to make it an integer
= math.floor(
optimal_num_iterations / (4 * math.asin(math.sqrt(len(marked_states) / 2**n)))
math.pi
)# Print the optimal number of iterations
print("Optimal Number of Iterations:", optimal_num_iterations)
# For the optimal number of iterations, add the oracle gates to the
# circuit, followed by the amplifcation gates
for i in range(optimal_num_iterations):
grover_oracle(grover_circuit, n, marked_states)
grover_amplification(grover_circuit, n)
# Print the statevector of the circuit at the given moment
= Statevector(grover_circuit)
statevector = 'latex'))
display(statevector.draw(output
# Measure the circuit
range(n), range(n))
grover_circuit.measure(
# Draw the circuit
="mpl") grover_circuit.draw(output
Optimal Number of Iterations: 2
\[-0.0883883476 |000\rangle-0.0883883476 |001\rangle-0.0883883476 |010\rangle-0.0883883476 |011\rangle-0.0883883476 |100\rangle-0.0883883476 |101\rangle-0.0883883476 |110\rangle+0.9722718241 |111\rangle\]
# Simulate the circuit, no need to transpile since just base gates are used
= AerSimulator()
simulator = simulator.run(grover_circuit).result().get_counts()
results plot_histogram(results)
Custom Gates
To make the circuit smaller, especially since we could possible iterate through the algorithm many times, Qiskit allows us to create custom gates.
def grover_oracle_gate(num_qubits, marked_states):
"""
Create a Grover's algorithm oracle for the general case of finding some number
of marked strings from a list of all possible binary strings fo a given length.
Inputs:
num_qubits (an int): The number of qubits in the circuit
marked_states (a list): the states to mark for the grover's Algorithm to find
Returns:
qc (a qiskit quantum circuit): the Grover's oracle as a single gate
"""
# Create a quantum circuit to hold the oracle gates
# Use the name keyword to set the name of the compound gate that will
# eventually be returned
= QuantumCircuit(num_qubits, name="Oracle")
qc
# Mark each target state in the input list
for target in marked_states:
# Flip target bit-string to match Qiskit bit-ordering
= target[::-1]
rev_target
# Find the indices of all the '0' elements in bit-string
# NOT gate will be placed at these values
# NOTE ERRORS OUT IF NO 0 STATES FOUND IN STATE FIX THIS
= [ind for ind in range(num_qubits) if rev_target.startswith("0", ind)]
zero_inds
# Add a multi-controlled Z-gate with pre- and post-applied X-gates (open-controls)
# where the target bit-string has a '0' entry
# Try/Except statement handles the case when one of the marked strings does not contain
# any zeros
try:
qc.x(zero_inds)except:
None
# Create a multi-controlled Z-gate where the very last qubit is the target qubit
# and all other qubits are the control qubits
- 1, 1), inplace=True)
qc.compose(MCMT(ZGate(), num_qubits
try:
qc.x(zero_inds)except:
None
# Once all of the individual gates are added to the circuit, make the entire
# circuit into a single gate
= qc.to_gate()
qc
# Return the compound gate
return qc
def grover_amplification_gate(num_qubits):
= QuantumCircuit(n, name="Amplify")
qc range(num_qubits))
qc.h(range(num_qubits))
qc.x(- 1, 1), inplace=True)
qc.compose(MCMT(ZGate(), num_qubits range(num_qubits))
qc.x(range(num_qubits))
qc.h(
qc.barrier()return qc
= ["01"]
marked_states
= len(marked_states[0])
n print(n)
= QuantumRegister(n)
q = ClassicalRegister(n)
c = QuantumCircuit(q,c)
grover_circuit
range(n))
grover_circuit.h(
= math.floor(
optimal_num_iterations / (4 * math.asin(math.sqrt(len(marked_states) / 2**n)))
math.pi
)print(optimal_num_iterations)
= grover_oracle_gate(n, marked_states)
oracle_gate = grover_amplification_gate(n)
amplification_gate
for i in range(optimal_num_iterations):
range(n))
grover_circuit.append(oracle_gate, range(n))
grover_circuit.append(amplification_gate,
range(n), range(n))
grover_circuit.measure(="mpl") grover_circuit.draw(output
2
1
= AerSimulator()
simulator = transpile(grover_circuit, simulator)
grover_circuit = simulator.run(grover_circuit).result().get_counts()
results plot_histogram(results)
= sorted(results, key=results.get, reverse=True)
sorted_results print(marked_states)
print(sorted_results[:len(marked_states)])
['0111', '1001']
['0111', '1001']
Qiskit Built-In Functions (Amplification Only)
def grover_oracle_qiskit(marked_states):
"""Build a Grover oracle for multiple marked states
Here we assume all input marked states have the same number of bits
Parameters:
marked_states (str or list): Marked states of oracle
Returns:
QuantumCircuit: Quantum circuit representing Grover oracle
"""
if not isinstance(marked_states, list):
= [marked_states]
marked_states # Compute the number of qubits in circuit
= len(marked_states[0])
num_qubits
= QuantumCircuit(num_qubits)
qc # Mark each target state in the input list
for target in marked_states:
# Flip target bit-string to match Qiskit bit-ordering
= target[::-1]
rev_target # Find the indices of all the '0' elements in bit-string
= [ind for ind in range(num_qubits) if rev_target.startswith("0", ind)]
zero_inds # Add a multi-controlled Z-gate with pre- and post-applied X-gates (open-controls)
# where the target bit-string has a '0' entry
qc.x(zero_inds)- 1, 1), inplace=True)
qc.compose(MCMT(ZGate(), num_qubits
qc.x(zero_inds)return qc
= ["01111", "10000"]
marked_states
= grover_oracle_qiskit(marked_states)
oracle = GroverOperator(oracle)
grover_op ="mpl")
grover_op.decompose().draw(output
# Note that in our implementations we took advantage of the
# fact that Z = HXH to replace the single Hadamard, multi-control NOT gate
# single Hadamard circuit with just a multicontrol Z circuit
= math.floor(
optimal_num_iterations / (4 * math.asin(math.sqrt(len(marked_states) / 2**grover_op.num_qubits)))
math.pi
)
= QuantumCircuit(grover_op.num_qubits)
qc # Create even superposition of all basis states
range(grover_op.num_qubits))
qc.h(# Apply Grover operator the optimal number of times
=True)
qc.compose(grover_op.power(optimal_num_iterations), inplace# Measure all qubits
qc.measure_all()="mpl", style="iqp") qc.draw(output
= AerSimulator()
simulator = transpile(qc, simulator)
qc = simulator.run(qc).result().get_counts()
results plot_histogram(results)
Slide Figures
= ["00", "01", "10", "11"]
states = (1/np.sqrt(len(states)))*np.ones(len(states))
amps
= np.average(amps)
average_amp
= "11"
choice_state = len(states)-1
choice_index
="darkblue")
plt.bar(states, amps, color="darkred", label="Choice State")
plt.bar(choice_index, amps[choice_index], color0-0.5, len(states)-1+0.5, color="darkgreen", linestyle="--", linewidth=3, label="Average Amplitude")
plt.hlines(average_amp, ="serif")
plt.xticks(fontfamily="serif")
plt.yticks(fontfamily"States", fontsize=14, fontfamily="serif")
plt.xlabel("Amplitude", fontsize=14, fontfamily="serif")
plt.ylabel(={'family':"serif", 'size':12}, loc=(1.01, 0.4))
plt.legend(prop# Save the image
"grover_vis_1.png", dpi=1000, bbox_inches="tight") plt.savefig(
*= -1
amps[choice_index] = np.average(amps)
average_amp
="darkblue")
plt.bar(states, amps, color="darkred", label="Choice State")
plt.bar(choice_index, amps[choice_index], color0-0.5, len(states)-1+0.5, color="darkgreen", linestyle="--", linewidth=3, label="Average Amplitude")
plt.hlines(average_amp, 0, -1, len(states), color="black")
plt.hlines(-1, len(states))
plt.xlim(="serif")
plt.xticks(fontfamily="serif")
plt.yticks(fontfamily"States", fontsize=14, fontfamily="serif")
plt.xlabel("Amplitude", fontsize=14, fontfamily="serif")
plt.ylabel(={'family':"serif", 'size':12}, loc=(1.01, 0.4))
plt.legend(prop
# Save the image
"grover_vis_2.png", dpi=1000, bbox_inches="tight") plt.savefig(
-= average_amp
amps = np.abs(amps)
amps
="darkblue")
plt.bar(states, amps, color="darkred", label="Choice State")
plt.bar(choice_index, amps[choice_index], color0-0.5, len(states)-1+0.5, color="darkgreen", linestyle="--", linewidth=3, label="Average Amplitude")
plt.hlines(average_amp, 0, -1, len(states), color="black")
plt.hlines(-1, len(states))
plt.xlim(="serif")
plt.xticks(fontfamily="serif")
plt.yticks(fontfamily"States", fontsize=14, fontfamily="serif")
plt.xlabel("Amplitude", fontsize=14, fontfamily="serif")
plt.ylabel(={'family':"serif", 'size':12}, loc=(1.01, 0.4))
plt.legend(prop
# Save the image
"grover_vis_3.png", dpi=1000, bbox_inches="tight") plt.savefig(
*= -1
amps[choice_index] = np.average(amps)
average_amp
="darkblue")
plt.bar(states, amps, color="darkred", label="Choice State")
plt.bar(choice_index, amps[choice_index], color0-0.5, len(states)-1+0.5, color="darkgreen", linestyle="--", linewidth=3, label="Average Amplitude")
plt.hlines(average_amp, 0, -1, len(states), color="black")
plt.hlines(-1, len(states))
plt.xlim(="serif")
plt.xticks(fontfamily="serif")
plt.yticks(fontfamily"States", fontsize=14, fontfamily="serif")
plt.xlabel("Amplitude", fontsize=14, fontfamily="serif")
plt.ylabel(={'family':"serif", 'size':12}, loc=(1.01, 0.4))
plt.legend(prop
# Save the image
"grover_vis_4.png", dpi=1000, bbox_inches="tight") plt.savefig(
-= average_amp
amps = np.abs(amps)
amps
="darkblue")
plt.bar(states, amps, color="darkred", label="Choice State")
plt.bar(choice_index, amps[choice_index], color0-0.5, len(states)-1+0.5, color="darkgreen", linestyle="--", linewidth=3, label="Average Amplitude")
plt.hlines(average_amp, 0, -1, len(states), color="black")
plt.hlines(-1, len(states))
plt.xlim(="serif")
plt.xticks(fontfamily="serif")
plt.yticks(fontfamily"States", fontsize=14, fontfamily="serif")
plt.xlabel("Amplitude", fontsize=14, fontfamily="serif")
plt.ylabel(={'family':"serif", 'size':12}, loc=(1.01, 0.4))
plt.legend(prop
# Save the image
"grover_vis_5.png", dpi=1000, bbox_inches="tight") plt.savefig(
= QuantumCircuit(1)
qc
0)
qc.x(0)
qc.h(
="mpl") qc.draw(output
# Create a single vector
= np.array([3,4])
V
# Create the plot
= plt.subplots()
fig, ax
# Add the vector V to the plot
0, 0, V[0], V[1], angles='xy', scale_units='xy', scale=1, color='r')
ax.quiver(
-5,5)
plt.xlim(-5,5)
plt.ylim(
# using 'spines', new in Matplotlib 1.0
'left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.spines['bottom')
ax.xaxis.set_ticks_position('left')
ax.yaxis.set_ticks_position(
# Show the plot along with the grid
="both")
plt.grid(which"reflection1.png", dpi=1000) plt.savefig(
# Create a single vector
= np.array([3,4])
V = np.array([3,-4])
V2
# Create the plot
= plt.subplots()
fig, ax
# Add the vector V to the plot
0, 0, V[0], V[1], angles='xy', scale_units='xy', scale=1, color='r')
ax.quiver(0, 0, V2[0], V2[1], angles='xy', scale_units='xy', scale=1, color='r')
ax.quiver(
-5,5)
plt.xlim(-5,5)
plt.ylim(
# using 'spines', new in Matplotlib 1.0
'left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.spines['bottom')
ax.xaxis.set_ticks_position('left')
ax.yaxis.set_ticks_position(
# Show the plot along with the grid
="both")
plt.grid(which"reflection2.png", dpi=1000) plt.savefig(
# Create a single vector
= np.array([3,4])
V = np.array([3,-4])
V2 = np.array([0,-4])
V3
# Create the plot
= plt.subplots()
fig, ax
# Add the vector V to the plot
0, 0, V[0], V[1], angles='xy', scale_units='xy', scale=1, color='r')
ax.quiver(0, 0, V2[0], V2[1], angles='xy', scale_units='xy', scale=1, color='r')
ax.quiver(3, 4, V3[0], V3[1], angles='xy', scale_units='xy', scale=1, color='b')
ax.quiver(3, 0, V3[0], V3[1], angles='xy', scale_units='xy', scale=1, color='b')
ax.quiver(
-5,5)
plt.xlim(-5,5)
plt.ylim(
# using 'spines', new in Matplotlib 1.0
'left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.spines['bottom')
ax.xaxis.set_ticks_position('left')
ax.yaxis.set_ticks_position(
# Show the plot along with the grid
="both")
plt.grid(which"reflection3.png", dpi=1000) plt.savefig(
= np.array([0,1])
down = np.kron(down, down)
down_down = np.outer(down_down, down_down)
outer = np.eye(4) - outer U
outer
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 1]])
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([0,-4])
s_per
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ -1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which
ax.add_patch(circ)
plt.legend()'equal', adjustable='box')
ax.set_aspect("grovercircle1.png", dpi=1000) plt.savefig(
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([1,0])
s_per
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ
ax.add_patch(circ)
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(0, 0, s_per[0], s_per[1], angles='xy', scale_units='xy', scale=1, color='g', label=r"s_perpen.", linewidth=2)
ax.quiver(
-1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which=(1.01, 0.4))
plt.legend(loc'equal', adjustable='box')
ax.set_aspect("grovercircle2.png", dpi=1000, bbox_inches="tight") plt.savefig(
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([1,0])
s_per
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(0, 0, s_per[0], s_per[1], angles='xy', scale_units='xy', scale=1, color='g', label=r"s_perpen.", linewidth=2)
ax.quiver(
= 5/13
y = 12/13
x
= np.arctan2(y, x)
angle_rad = np.degrees(angle_rad)
angle_deg
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, 0.05, f'θ', fontsize=14, color='black')
ax.text(
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ -1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which
ax.add_patch(circ)=(1.01, 0.4))
plt.legend(loc'equal', adjustable='box')
ax.set_aspect("grovercircle3.png", dpi=1000, bbox_inches="tight") plt.savefig(
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([1,0])
s_per
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(0, 0, s_per[0], s_per[1], angles='xy', scale_units='xy', scale=1, color='g', label=r"s_perpen.", linewidth=2)
ax.quiver(0, 0, phi[0], -phi[1], angles='xy', scale_units='xy', scale=1, color='purple', linewidth=2, label="Oracle 1")
ax.quiver(
= 5/13
y = 12/13
x
= np.arctan2(y, x)
angle_rad = np.degrees(angle_rad)
angle_deg
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, 0.05, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = -np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, -0.14, f'θ', fontsize=14, color='black')
ax.text(
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ -1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which
ax.add_patch(circ)=(1.01, 0.4))
plt.legend(loc'equal', adjustable='box')
ax.set_aspect("grovercircle4.png", dpi=1000, bbox_inches="tight") plt.savefig(
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([1,0])
s_per
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(0, 0, s_per[0], s_per[1], angles='xy', scale_units='xy', scale=1, color='g', label=r"s_perpen.", linewidth=2)
ax.quiver(0, 0, phi[0], -phi[1], angles='xy', scale_units='xy', scale=1, color='purple', linewidth=2, label="Oracle 1")
ax.quiver(
= 5/13
y = 12/13
x
= np.arctan2(y, x)
angle_rad = np.degrees(angle_rad)
angle_deg
= np.array([np.cos(3*angle_rad), np.sin(3*angle_rad)])
dif1
0, 0, dif1[0], dif1[1], angles='xy', scale_units='xy', scale=1, color='slategrey', linewidth=2, label="Amplify 1")
ax.quiver(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, 0.05, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = -np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, -0.14, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, 3*angle_rad, 100)
arc = np.cos(arc)/2
arc_x = np.sin(arc)/2
arc_y 'black')
ax.plot(arc_x, arc_y, 0.45, 0.4, f'3θ', fontsize=14, color='black')
ax.text(
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ -1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which
ax.add_patch(circ)=(1.01, 0.4))
plt.legend(loc'equal', adjustable='box')
ax.set_aspect("grovercircle5.png", dpi=1000, bbox_inches="tight") plt.savefig(
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([1,0])
s_per
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(0, 0, s_per[0], s_per[1], angles='xy', scale_units='xy', scale=1, color='g', label=r"s_perpen.", linewidth=2)
ax.quiver(0, 0, phi[0], -phi[1], angles='xy', scale_units='xy', scale=1, color='purple', linewidth=2, label="Oracle 1")
ax.quiver(
= 5/13
y = 12/13
x
= np.arctan2(y, x)
angle_rad = np.degrees(angle_rad)
angle_deg
= np.array([np.cos(3*angle_rad), np.sin(3*angle_rad)])
dif1
0, 0, dif1[0], dif1[1], angles='xy', scale_units='xy', scale=1, color='slategrey', linewidth=2, label="Amplify 1")
ax.quiver(0, 0, dif1[0], -dif1[1], angles='xy', scale_units='xy', scale=1, color='darkorange', linewidth=2, label="Oracle 2")
ax.quiver(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, 0.05, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = -np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, -0.14, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, 3*angle_rad, 100)
arc = np.cos(arc)/2
arc_x = np.sin(arc)/2
arc_y 'black')
ax.plot(arc_x, arc_y, 0.45, 0.4, f'3θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, 3*angle_rad, 100)
arc = np.cos(arc)/2
arc_x = -np.sin(arc)/2
arc_y 'black')
ax.plot(arc_x, arc_y, 0.45, -0.45, f'3θ', fontsize=14, color='black')
ax.text(
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ -1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which
ax.add_patch(circ)=(1.01, 0.4))
plt.legend(loc'equal', adjustable='box')
ax.set_aspect("grovercircle6.png", dpi=1000, bbox_inches="tight") plt.savefig(
= plt.subplots()
fig, ax # Create a single vector
= np.array([0,1])
s = np.array([12/13,5/13])
phi = np.array([1,0])
s_per
0, -1.1, 1.1, color="black", linewidth=0.5)
plt.hlines(0, -1.1, 1.1, color="black", linewidth=0.5)
plt.vlines(
# Add the vector V to the plot
0, 0, s[0], s[1], angles='xy', scale_units='xy', scale=1, color='r', label="s", linewidth=2)
ax.quiver(0, 0, phi[0], phi[1], angles='xy', scale_units='xy', scale=1, color='b', label=r"\phi", linewidth=2)
ax.quiver(0, 0, s_per[0], s_per[1], angles='xy', scale_units='xy', scale=1, color='g', label=r"s_perpen.", linewidth=2)
ax.quiver(0, 0, phi[0], -phi[1], angles='xy', scale_units='xy', scale=1, color='purple', linewidth=2, label="Oracle 1")
ax.quiver(
= 5/13
y = 12/13
x
= np.arctan2(y, x)
angle_rad = np.degrees(angle_rad)
angle_deg
= np.array([np.cos(3*angle_rad), np.sin(3*angle_rad)])
dif1
0, 0, dif1[0], dif1[1], angles='xy', scale_units='xy', scale=1, color='slategrey', linewidth=2, label="Amplify 1")
ax.quiver(0, 0, dif1[0], -dif1[1], angles='xy', scale_units='xy', scale=1, color='darkorange', linewidth=2, label="Oracle 2")
ax.quiver(
= np.array([np.cos(5*angle_rad), np.sin(5*angle_rad)])
dif2 0, 0, dif2[0], dif2[1], angles='xy', scale_units='xy', scale=1, color='teal', linewidth=2, label="Amplify 2")
ax.quiver(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, 0.05, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, angle_rad, 100)
arc = np.cos(arc)/4
arc_x = -np.sin(arc)/4
arc_y 'black')
ax.plot(arc_x, arc_y, 0.4, -0.14, f'θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, 3*angle_rad, 100)
arc = np.cos(arc)/2
arc_x = np.sin(arc)/2
arc_y 'black')
ax.plot(arc_x, arc_y, 0.45, 0.4, f'3θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, 3*angle_rad, 100)
arc = np.cos(arc)/2
arc_x = -np.sin(arc)/2
arc_y 'black')
ax.plot(arc_x, arc_y, 0.45, -0.45, f'3θ', fontsize=14, color='black')
ax.text(
= np.linspace(0, 5*angle_rad, 100)
arc = np.cos(arc)/3
arc_x = np.sin(arc)/3
arc_y 'black')
ax.plot(arc_x, arc_y, -0.15, 0.35, f'5θ', fontsize=14, color='black')
ax.text(
= plt.Circle((0, 0), radius=1, edgecolor='black', facecolor='None')
circ -1.1,1.1)
plt.xlim(-1.1,1.1)
plt.ylim(="both")
plt.grid(which
ax.add_patch(circ)=(1.01, 0.4))
plt.legend(loc'equal', adjustable='box')
ax.set_aspect("grovercircle7.png", dpi=1000, bbox_inches="tight") plt.savefig(