quantumlib / recirq Goto Github PK
View Code? Open in Web Editor NEWResearch using Cirq!
Home Page: https://quantumai.google/cirq/experiments
License: Apache License 2.0
Research using Cirq!
Home Page: https://quantumai.google/cirq/experiments
License: Apache License 2.0
See #107 (comment)
Cross-entropy benchmarking is a robust characterization tool which can
not only provide the fidelity of pairs of qubits and classically-hard
random circuits but can also be used to βfitβ the unitary parameters of
an entangling gate or a composite gate.
We aim to provide end-to-end execution of cross entropy benchmarking in
ReCirq using some of the existing utilities from Cirq.
One of the key design elements will be separating circuit generation,
execution, simulation, and analysis into their own tasks.
This will be one task that generates all the circuits to simplify the
random seeding. This task will be executed ~once ever and the same
random circuits can be used in multiple data collection runs.
This is the aspect of the flow that needs to be most tolerant to faults
(i.e. restarting from a failed pipeline). This will also be run multiple
times, so it needs to be a bit more nimble. We may want to experiment
running circuits in different orders (e.g. to avoid rastering effects).
These tasks handle collecting the XEB data for a particular circuit
index and cycle number. Additional parameters allow a given circuit to
be run on different devices, with different numbers of circuit
repetitions, and using different placements on the device (if
applicable).
These tasks are chunked such that each task corresponds to one circuit.
The circuit, however, will be simulated at all the different `cycle`
values. This permits an optimization where we can partially simulate the
circuit, save the intermediate state vector (for the truncated `cycle`
value) and continue for larger cycle values without re-computing the
first part of the circuit.
Analysis will be done via utility functions and pandas. Given the
experimental results and the simulation results, the final analysis is
not computationally expensive.
Layering a fitting routine to determine unitary parameters will be done
after the initial refactor.
A lot of specific problems are tailored to specific hardware topologies of qubits; or a problem is defined on a structured topology and mapped to a hardware topology. Specific examples:
When discussing a hardware topology, it can be convenient to use the processor id (aka device name) as a proxy for the topology. Unfortunately, a given processor is not guaranteed to have a stable hardware topology. Indeed: rainbow
has grown from Sycamore23
to its current, larger configuration. For experimental record-keeping, it's important to have a fixed topology. Furthermore: to support comparisons between multiple processors with compatible hardware graphs (i.e. one is a subset-or-equal to another) it could be useful to have a "problem topology" decoupled from a hardware topology.
A simple "record keeping" approach would be to serialize the device graph for each problem. However, there is often considerable structure in these topologies (e.g. "this was a device graph" or "this is a line"). Additionally, for ReCirq's data collection idioms to be effective it is necessary to have a descriptive "hash" of all parameters (so they can be used as inputs, shared between dependent tasks, used as parts of the filename).
Therefore, I propose we have 1) a set of problem topology classes and 2) A name-to-topolgy mapping
import networkx as nx
class LineTopology:
def __init__(self, n_qubits):
self.n_qubits = n_qubits
self.name = f'{self.n_qubits}q-line'
self.graph = nx.from_edgelist([(i1, i2) for i1, i2
in zip(range(self.n_qubits), range(1, self.n_qubits))])
SYC23_GRAPH = nx.from_edgelist([
((3, 2), (4, 2)), ((4, 1), (5, 1)), ((4, 2), (4, 1)),
((4, 2), (4, 3)), ((4, 2), (5, 2)), ((4, 3), (5, 3)),
((5, 1), (5, 0)), ((5, 1), (5, 2)), ((5, 1), (6, 1)),
((5, 2), (5, 3)), ((5, 2), (6, 2)), ((5, 3), (5, 4)),
((5, 3), (6, 3)), ((5, 4), (6, 4)), ((6, 1), (6, 2)),
((6, 2), (6, 3)), ((6, 2), (7, 2)), ((6, 3), (6, 4)),
((6, 3), (7, 3)), ((6, 4), (6, 5)), ((6, 4), (7, 4)),
((6, 5), (7, 5)), ((7, 2), (7, 3)), ((7, 3), (7, 4)),
((7, 3), (8, 3)), ((7, 4), (7, 5)), ((7, 4), (8, 4)),
((7, 5), (7, 6)), ((7, 5), (8, 5)), ((8, 3), (8, 4)),
((8, 4), (8, 5)), ((8, 4), (9, 4)),
])
class DeviceBasedTopology:
def __init__(self, graph, assoc_processor_id, epoch=1):
self.graph = graph
self.n_qubits = graph.number_of_nodes()
self.assoc_processor_id = assoc_processor_id
self.epoch = epoch
if epoch != 1:
epoch_str = f'-mk{epoch}'
else: epoch_str = ''
self.name = f'{assoc_processor_id}{epoch_str}'
RAINBOW_TOPOLOGY = DeviceBasedTopology(
graph=SYC23_GRAPH,
assoc_processor_id='rainbow',
epoch=1
)
class GridTopology:
def __init__(self, width, height):
self.graph = nx.grid_2d_graph(height, width)
self.n_qubits = width * height
self.name = f'{width}x{height}-grid'
grid_topo = GridTopology(5, 3)
print(grid_topo.name)
draw_gridlike(grid_topo.graph)
Networkx subgraph isomorphism routines can be used to place compatible topologies
The qubit picking algorithm for quantum chess greedily picks the most connected qubit. This is good if there is only one circuit transformation to do. However, if there are two distinct "chains" of moves, this greedy algorithm may no longer work. For instance, suppose the b1 knight splits on one side of the board, and the g1 knight splits on the other side of the board (and the two sides never interact). It may be possible to put b1 circuit on the right side of the chip, and g1 circuit on the left side of the chip. However, since the greedy algorithm put the b1 circuit right in the middle of the circuit, they can't both fit.
Another possibility that may be easier algorithmically (but possibly involve changing more code), is to split discrete chains of moves into different circuits, rather than try to fit both chains into the first circuit. This could also slow down performance.
The qubit picking algorithm for quantum chess is found here:
https://github.com/quantumlib/ReCirq/blob/master/recirq/quantum_chess/circuit_transformer.py#L58
See #52 (comment) and following #55
Measurements in Quantum Chess occur during excluded or capture moves. The current Cirq implementation runs 100 samples to determine the measurement outcome when it encounters one of those move variants, then stores that outcome as part of the move sequence history. Future sampling runs are post-selected based on that outcome.
In order to support features like undo move, sandbox mode demonstrations, and game replays, we need to allow the user to provide a desired measurement outcome through the REST API (currently implemented separately as a server that forwards calls to this Cirq implementation). The Cirq implementation of Quantum Chess should then use this value for the post-selection, instead of the random outcome from the 100-shot described above.
The current SwapUpdater implementation (#146) takes a short cut and uses manhattan distance when computing the shortest GridQubit-to-GridQubit distances.
But the manhattan distance is only the same as the shortest path length on the device connectivity graph when there are no unusable qubits (no holes, hanging strips, or disconnected qubits).
We should update the SwapUpdater to precompute shortest path lengths on the device connectivity graph (ex using the Floyd-Warshall algorithm, which we're already using for the initial circuit placement) and use those distances instead of manhattan distance. Otherwise, circuit placement will break in the presence of pruned qubits (see also quantumlib/unitary#51).
Currently the run_batch
method still needs specification for a list of parameters even when the circuits are non-parameterized. Upgrading to Cirq 0.10 should solve this issue.
Quantum volume never really fit into Cirq, with the library code getting shuffled around (eventually landing in contrib
) and the driver scripts landing in examples/advanced
. It is the only advanced example. This also limits our ability to extend qvol and try various improvements or different metrics. It would be a good study to include in ReCirq
In the second cell after "Precomputed Angle Data Collection" with code
await recirq.execute_in_queue(collect_data, data_collection_tasks, num_workers=2)
executing it on my laptop causes some output to be printed, the last line of which is
Processing 2020-03-tutorial/Syc23-simulator/from-2020-03-tutorial/sk-problems/nq-3/instance-0/p-3_50k_structured. Current queue size: 144
before hanging (fails to continue past that point).
We've seen this a couple of times in the CI
__________________________ test_model_policy_gradient __________________________
def test_model_policy_gradient():
x0 = np.random.randn(5)
result = model_policy_gradient(
sum_of_squares,
x0,
learning_rate=1e-1,
decay_rate=0.96,
decay_steps=10,
log_sigma_init=-6.0,
max_iterations=100,
batch_size=30,
radius_coeff=3.0,
warmup_steps=10,
known_values=None,
)
> np.testing.assert_allclose(result.x, np.zeros(len(result.x)), atol=1e-2)
E AssertionError:
E Not equal to tolerance rtol=1e-07, atol=0.01
E
E Mismatched elements: 1 / 5 (20%)
E Max absolute difference: 0.01534512
E Max relative difference: inf
E x: array([-0.015345, 0.007796, -0.00722 , -0.00189 , -0.000304])
E y: array([0., 0., 0., 0., 0.])
@JiahaoYao do you have any time to look into this?
Current version of Cirq does not support PhasedFSimGate
which makes varying the phase of FSIM gates rather clunky (i.e. up to 4 Z-gates need to be inserted). Updating Cirq to the newest version should solve this problem.
pytket has a lot of unnecessary dependencies which also cause the dependency resolver to either deadlock or overwrite your version of cirq with an old one. For the CI, we install pytket with pip install pytket==0.1.6 --no-deps
It would be good to have two functions that can easily save and load any generic objects to and from a directory, in formats that are more robust compared to pickle.
Use utility functions like
And more more of this functionality following quantumlib/Cirq#2820
Following data (collection) idioms, there should be a task to generate this data into ~/cirq-results/
and then subsequent code can consume it from there. We should also upload a copy of it to a figshare dataset for fetching during tutorials / testing.
cc @ncrubin
See #27 for details.
it downloads datasets from https://datadryad.org/stash/dataset/doi:10.5061/dryad.crjdfn32v
the download URLs are not super stable, but also datadryad.org website unavailability can cause the recirq test suites to flake out and fail
It may be better to avoid the external dependency on datadryad.org in tests and mock out the download.
concepts and rest api notebook sometimes use 2 spaces per indent level, when everywhere else 4 is used.
When running documentation notebooks in Colab, the runtime does not come with (Re)Cirq installed. Luckily, you can execute shell commands by prepending a !
to a cell:
!pip install recirq
However
Therefore, all the notebooks should have
try:
import recirq
except ImportError:
!pip install --quiet git+https://github.com/quantumlib/ReCirq
as the install step.
documentation_utils.get_qaoa_data
and documentation_utils.get_fermi_hubbard_data
).qaoa.get_publication_data
and recirq.get_publication_data
).Originally posted by @rmlarose in #117 (comment)
We should pick one and make it consistent
If a split jump is from a fully occupied square to two empty squares, then the exact squares don't matter. We can pre-process a single split jump move and cache the result. Then any split jump can immediately return that result, and subsequently append the specific sub-circuit, with the correct qubit-square mapping, to the circuit that defines the quantum state.
Provide a function that accepts an arbitrary unitary operator (possibly in matrix form?), and a list of squares, and returns the expectation value of the operator on those squares for the current quantum state.
Noticed a failure in test_undo_entangled_measurement on PR #96 which is unrelated to quantum chess. It doesn't seem to fail often but I can reproduce it after running several times.
=================================== FAILURES ===================================
_______________________ test_undo_entangled_measurement ________________________
def test_undo_entangled_measurement():
b = qb.CirqBoard(u.squares_to_bitboard(['a2','b1','c2','d1']))
assert b.perform_moves(
'b1a3c3:SPLIT_JUMP:BASIC',
'c2c4:PAWN_TWO_STEP:BASIC'
)
probs = b.get_probability_distribution(1000)
assert_prob_about(probs, qb.square_to_bit('a3'), 0.5)
assert_prob_about(probs, qb.square_to_bit('c2'), 0.5)
assert_prob_about(probs, qb.square_to_bit('c3'), 0.5)
assert_prob_about(probs, qb.square_to_bit('c4'), 0.5)
b.perform_moves( 'd1c2:JUMP:EXCLUDED')
assert b.undo_last_move()
print(b)
probs = b.get_probability_distribution(1000)
> assert_prob_about(probs, qb.square_to_bit('a3'), 0.5)
recirq/quantum_chess/quantum_board_test.py:888:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
probs = [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, ...], that = 16, expected = 0.5
atol = 0.04
def assert_prob_about(probs, that, expected, atol=0.04):
"""Checks that the probability is within atol of the expected value."""
assert probs[that] > expected - atol
> assert probs[that] < expected + atol
E assert 0.54 < (0.5 + 0.04)
recirq/quantum_chess/test_utils.py:83: AssertionError
----------------------------- Captured stdout call -----------------------------
+----------------------------------+
8| . . . . . . . . |
7| . . . . . . . . |
6| . . . . . . . . |
5| . . . . . . . . |
4| . . 54 . . . . . |
3| 54 . 46 . . . . . |
2| 100 . 46 . . . . . |
1| . . . 100 . . . . |
+----------------------------------+
a b c d e f g h
As written in optimize_instance_interp_heuristic
, there is a confusing set of if
else
clauses to implement the parameter initialization logic. This should be factored into a more readable form
The fn
attribute of tasks should use os.path.join
instead of using a filename pattern that is incompatible with some operating systems.
In quantum_board.py, some move types call the "unhook" function on qubits that may still be in an entangled state. For example consider the sequence Pd2d3 Nb1d2 Nd2^b3f3 Ng1^h3f3
(in the notation of https://cantwellc.github.io/QuantumChessWeb/). As a recirq/quantum_chess/experiments/interactive_board.py
input this is
d2d3
b1d2
d2b3f3:SPLIT_JUMP:BASIC
g1h3f3:SPLIT_JUMP:BASIC
The Python board incorrectly erases the knight on g1.
I think unhook probably shouldn't be used in any case where a measurement was not performed.
Hi @mpharrigan, I met with the install error for the package. Here are the description of the error and my approach to getting around.
Installed /home/ABC/anaconda3/envs/recirq/lib/python3.7/site-packages/recirq-0.1.dev0-py3.7.egg
Processing dependencies for recirq==0.1.dev0
Searching for cirq==0.8.2
Reading https://pypi.org/simple/cirq/
Downloading https://files.pythonhosted.org/packages/1e/5b/6f8cb54ea8c0041ad9c8e4ece07cb5ca9eb1c29de68e68795b4a40d90cc6/cirq-0.8.2-py3-none-any.whl#sha256=84c2ace7f6cb96b21e9265ea31a25c2fbc044ee79da30beb83fe3865e2cc05f8
Best match: cirq 0.8.2
Processing cirq-0.8.2-py3-none-any.whl
Installing cirq-0.8.2-py3-none-any.whl to /home/ABC/anaconda3/envs/recirq/lib/python3.7/site-packages
Adding cirq 0.8.2 to easy-install.pth file
Installed /home/ABC/anaconda3/envs/recirq/lib/python3.7/site-packages/cirq-0.8.2-py3.7.egg
error: cirq 0.8.2 is installed but cirq==0.8 is required by {'pytket-cirq'}
I think this is related to the requirement.txt.
If it is changed to cirq=0.8.0
, there is no such issue.
Similar to TFQ, ReCirq could benefit from knowing about breaking changes earlier rather than later coming from Cirq.
Right now we use QuirkQubitPermutationGate
QuantumBoard.get_probability_distributions caches the probability accumulations:
if not self.accumulations_valid:
self._generate_accumulations(repetitions)
However, this is incorrect if the number of samples changes. For instance, calling get_probability_distributions(repetitions=1) will generate probabilities of 1.0 or 0.0. If I then call get_probability_distributions(repetitions=1000), it will return this same distribution again, instead of the more fine-grained distribution.
It would be good to log timing information for the (ie. time this function: https://github.com/quantumlib/ReCirq/blob/master/recirq/quantum_chess/quantum_board.py#L136) so that we can keep track of how long moves are taking to run on hardware (or even on simulator).
At least when I build locally. Seems to be spatialaudio/nbsphinx#59 but updating IPython didn't immediately work
These are too expensive to run for every PR. Right now, I've saved executed versions of
which need to be tested manually.
Some options:
wrap_function
#184The file docs/development.md references cirq in respect to pushing to pypi, and it looks like the whole file was lifted from the cirq repo. This file needs updating. At the very least, the pieces that are not relevant (pypi) should be stripped out so that the document only references the pieces that are relevant to developing reCirq code.
The build is failing.
https://github.com/quantumlib/ReCirq/runs/1475828878?check_suite_focus=true#step:6:47
Need to check if they released a new version and why it's not backwards compatible. Pin or fix as necessary
Right now there's pythonpackage.yml
for unit tests and deploy-docs.yml
for building and deploying docs. They should share the requirements installation, package installation, and doc building steps instead of manually keeping them in sync
Current tutorial + code doesn't leverage OpenFermion or QCS's new features . We should create a more full example with the folllowing:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.