Skip to content

Add user best practices documentation #5604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/_book.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ upper_tabs:
path: /cirq/start/start
- title: "Cirq Basics"
path: /cirq/start/basics
- title: "Best Practices"
path: /cirq/start/best_practices

#### TEST UNDERSTANDING ####
- heading: "Test understanding"
Expand Down
13 changes: 13 additions & 0 deletions docs/build/gates.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,19 @@
"[Circuits](circuits.ipynb)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "yS2UiFDQt-sk"
},
"source": [
"## Immutability of Gates and Operations\n",
"\n",
"Gates and Operations in Cirq are considered to be immutable objects. This means that a `cirq.Gate` or `cirq.Operation` should not be modified after its creation. If attributes of these objects need to be modified, a new object should be created.\n",
"\n",
"Modifying these objects in-place could cause unexpected behavior. For instance, changing the qubits of an existing `cirq.Operation` object could cause an existing `cirq.Moment` that contains this object to have operations with overlapping qubits."
]
},
{
"cell_type": "markdown",
"metadata": {
Expand Down
2 changes: 1 addition & 1 deletion docs/dev/rfc_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ and have a discussion with the maintainers. Mention that you are willing to writ
* Make sure to share your doc with [email protected] for comments.
* Link the RFC in your issue.
4. Recruiting a sponsor:
* A sponsor must be a maintainer of the project or the product manager (currently Alan Ho).
* A sponsor must be a maintainer of the project or the product manager.
* Write a comment in your Github issue that calls out that you are "Looking for a sponsor". A maintainer will mark the issue with a label: "rfc/needs-sponsor".
* While it might take some time to get a maintainer to sponsor your RFC, it is essential, as the sponsor will facilitate the process for reviewing your design.
* Tips to recruit a sponsor: 1) keep commenting on the issue weekly 2) attend Cirq Cynq and push for a sponsor.
Expand Down
15 changes: 15 additions & 0 deletions docs/simulate/params.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,21 @@
"You can see that the different flattened parameters have corresponding different results for their simulation."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "63FrLKWk9_mC"
},
"source": [
"### Immutability of Sweeps\n",
"\n",
"Sweeps and parameter resolvers should be considered immutable objects and should not be modified after creation.\n",
"\n",
"Many of these parameter resolvers use dictionaries for internal storage of symbol mappings. Though dictionaries are mutable in python, users should not modify internal mappings of resolvers after creation. Doing so may have undesirable and unpredictable results.\n",
"\n",
"Instead, create a new dictionary and a new parameter resolver object rather than attempting to modify an existing object."
]
},
{
"cell_type": "markdown",
"metadata": {
Expand Down
80 changes: 80 additions & 0 deletions docs/start/best_practices.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Best Practices

This page describes some of the best practices when using the Cirq library.
Following these guidelines will help you write code that is more performant and
less likely to break from version to version. Many of these rules apply to
other python libraries as well.

## Use top-level constructs

The Cirq library is designed so that important user-facing classes and objects
are exposed at the package level. Avoid referencing module names within Cirq.

For instance, use `cirq.X` and **not** `cirq.ops.X`. The second version will
break if we rename modules or move classes around from version to version.

## Do not use private member variables of classes

Any member of a class that is prefixed with an underscore is, by convention, a
private variable and should not be used outside of this class. For instance,
`cirq.XPowGate._dimension` should not be accessed or modified, since it is a
private member of that class. Using or modifying these values could result in
unexpected behavior or in broken code.

## Do not mutate "immutable" classes

While python's flexibility allows developers to modify just about anything, it
is bad practice to modify classes that are designed to be immutable. Doing so
can violate assumptions made in other parts of the library.

In particular, attributes of `cirq.Gate`, `cirq.Operation`, `cirq.Moment`, and
`cirq.ParamResolver` should not be modified after creation. If these objects
need to be modified, a new object should be created instead.

Violating this principle could cause problems in other parts of the code. For
instance, changing the qubits of an `cirq.Operation` could cause a `cirq.Moment`
that contains this Operation to have two Operations with the same qubits (which
is not allowed).

Note that `Circuit` objects can be modified, but `FrozenCircuit` objects cannot.

## Be mindful of exponential scaling

Many algorithms and procedures in quantum computing scale in an exponential
pattern. Cirq is designed for the noisy intermediate-scale quantum computing
(NISQ) regime. Creating circuits with hundreds or thousands of qubits may
surpass the capabilities of this library.

Even with smaller numbers of qubits, simulation and other tasks can very quickly
consume resources and time. The difference between a one second and an hour's
computation can be as few as ten qubits.

## What you see is what you get

Cirq tries to be as true to the specified circuits as possible, especially with
respect to hardware execution. Cirq highly discourages any hidden automatic
decomposition, compilation, or other modification of a circuit that is unknown
to the user. Any modification or transformation to the circuit should be
initiated by the user of the library.

This philosophy is important for many use cases. For instance, certain
benchmarking algorithms rely on the fact that gate sequences will not be optimized,
even if the circuit is nominally inefficient.

Of course, Cirq provides routines and functions for compilation and
transformation of circuits. Users can and should call these routines. However,
Cirq and resulting hardware integrations should not modify the circuits without
the user's "permission".

## Other style and performance guidelines

* Use `cirq.CircuitOperation` to more compactly define large, repeated
circuits. This can save space and time for analysis of larger circuits.
* For hardware execution of multiple circuits, prefer using `run_sweep` to
run variants of circuits. When not possible, try using `run_batch`. Using
these methods gives the hardware service the most opportunity to optimize
the execution of circuits and can result in much faster execution.
Read more details on the [Parameter Sweeps](/cirq/simulate/params) page.
* Consider defining and allocating qubits at the beginning of your code or
function, then applying gates and circuits to those qubits. While not
required, this style can produce cleaner code.