|
| 1 | +# qsim style guide |
| 2 | + |
| 3 | +This style guide outlines the coding conventions for this project. There are |
| 4 | +separate subsections for Python, C++, and other file types below. |
| 5 | + |
| 6 | +## General guidance |
| 7 | + |
| 8 | +### Overall principles |
| 9 | + |
| 10 | +* _Readability_: Code should be easy to understand for all team members. |
| 11 | + |
| 12 | +* _Maintainability_: Code should be easy to modify and extend. |
| 13 | + |
| 14 | +* _Consistency_: Adhering to a consistent style across all projects improves |
| 15 | + collaboration and reduces errors. |
| 16 | + |
| 17 | +* _Performance_: While readability is paramount, code should be efficient. |
| 18 | + |
| 19 | +### Overall development approach |
| 20 | + |
| 21 | +* When new functions, classes, and files are introduced, they should also |
| 22 | + have corresponding tests. Existing tests must continue to pass (or be |
| 23 | + updated) when changes are introduced, and code should be covered by tests. |
| 24 | + |
| 25 | +* Test coverage must be high. We don't require 100% coverage, but any |
| 26 | + uncovered code must be annotated appropriate directives (for example, |
| 27 | + `# pragma: no cover` in Python). |
| 28 | + |
| 29 | +* Tests must be independent and must not rely on the state of other tests. |
| 30 | + Setup and teardown functions should be used to create a clean environment |
| 31 | + for each test run. |
| 32 | + |
| 33 | +* Make sure to cover edge cases: write tests for invalid inputs, null values, |
| 34 | + empty arrays, zero values, and off-by-one errors. |
| 35 | + |
| 36 | +* Use asserts intelligently. Test assertions should be specific: instead of |
| 37 | + just asserting `true`, assert that a specific value equals an expected |
| 38 | + value. Provide meaningful failure messages. |
| 39 | + |
| 40 | +### Overall code format conventions |
| 41 | + |
| 42 | +This project generally follows Google coding conventions, with a few changes. |
| 43 | +The following Google style guides are the starting points: |
| 44 | + |
| 45 | +* [Google C++ Style Guide]( |
| 46 | + https://google.github.io/styleguide/cppguide.html) |
| 47 | + |
| 48 | +* [Google Python Style Guide]( |
| 49 | + https://google.github.io/styleguide/pyguide.html) |
| 50 | + |
| 51 | +* [Google Markdown Style Guide]( |
| 52 | + https://google.github.io/styleguide/docguide/style.html) |
| 53 | + |
| 54 | +* [Google Shell Style Guide]( |
| 55 | + https://google.github.io/styleguide/shellguide.html) |
| 56 | + |
| 57 | +To learn the conventions for line length, indentation, and other style |
| 58 | +characteristics, please inspect the following configuration files (if present at |
| 59 | +the top level of this project repository): |
| 60 | + |
| 61 | +* [`.editorconfig`](../.editorconfig) for basic code editor configuration for |
| 62 | + indentation and line length. |
| 63 | + |
| 64 | +* [`.clang-format`](../.clang-format) for C++ code and also protobuf (Protocol |
| 65 | + Buffers) data structure definitions. |
| 66 | + |
| 67 | +* [`.hadolint.yaml`](../.hadolint.yaml) for `Dockerfile`s. |
| 68 | + |
| 69 | +* [`.jsonlintrc.yaml`](../.jsonlintrc.yaml) for JSON files. |
| 70 | + |
| 71 | +* [`.markdownlintrc`](../.markdownlintrc) for Markdown files. |
| 72 | + |
| 73 | +* [`.pylintrc`](../.pylintrc) for Python code. |
| 74 | + |
| 75 | +* [`.yamllint.yaml`](../.yamllint.yaml) for YAML files. |
| 76 | + |
| 77 | +### Overall code commenting conventions |
| 78 | + |
| 79 | +Every source file must begin with a header comment with the copyright and |
| 80 | +license. We use the Apache 2.0 license, and copyright by Google LLC. Here is an |
| 81 | +example of the required file header for a Python language code file: |
| 82 | + |
| 83 | +```python |
| 84 | +# Copyright 2025 Google LLC |
| 85 | +# |
| 86 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 87 | +# you may not use this file except in compliance with the License. |
| 88 | +# You may obtain a copy of the License at |
| 89 | +# |
| 90 | +# https://www.apache.org/licenses/LICENSE-2.0 |
| 91 | +# |
| 92 | +# Unless required by applicable law or agreed to in writing, software |
| 93 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 94 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 95 | +# See the License for the specific language governing permissions and |
| 96 | +# limitations under the License. |
| 97 | +``` |
| 98 | + |
| 99 | +License headers are necessary on Python, C++, Bash/shell, and other programming |
| 100 | +language files, as well as configuration files in YAML, TOML, ini, and other |
| 101 | +config file formats. They are not necessary in Markdown or plain text files. |
| 102 | + |
| 103 | +For comments in other parts of the files, follow these guidelines: |
| 104 | + |
| 105 | +* _Write clear and concise comments_: Comments should explain the "why", not |
| 106 | + the "what". The code itself shows what it's doing. The comments should |
| 107 | + explain the intent, trade-offs, and reasoning behind the implementation. |
| 108 | + |
| 109 | +* _Comment sparingly_: Well-written code should be self-documenting where |
| 110 | + possible. It's not necessary to add comments for code fragments that can |
| 111 | + reasonably be assumed to be self-explanatory. |
| 112 | + |
| 113 | +* _Use complete sentences_: Start comments with a capital letter, use |
| 114 | + proper punctuation, and use proper grammar. |
| 115 | + |
| 116 | +## Python-specific guidance |
| 117 | + |
| 118 | +This section outlines coding conventions for Python code in this project. |
| 119 | + |
| 120 | +### Python naming conventions |
| 121 | + |
| 122 | +This project follows some nomenclature rules and conventions in order to |
| 123 | +maintain a consistent interface that is easy to use. By using consistent |
| 124 | +naming, we can reduce cognitive load on human users and developers. |
| 125 | + |
| 126 | +* _Variables_: Use lowercase with underscores (snake_case). Examples: |
| 127 | + `qsim_op`, `qubit_to_index_dict`, `gate_kind`. |
| 128 | + |
| 129 | +* _Constants_: Use uppercase with underscores. Examples: `MAX_VALUE`, |
| 130 | + `DATABASE_NAME`. |
| 131 | + |
| 132 | +* _Functions_: Use lowercase with underscores (snake_case). Examples: |
| 133 | + `calculate_total()`, `process_data()`. Internal functions are prefixed with |
| 134 | + an understore (`_`). |
| 135 | + |
| 136 | +* _Classes_: Use CapWords (CamelCase). Examples: `UserManager`, |
| 137 | + `PaymentProcessor`. |
| 138 | + |
| 139 | +* _Modules_: Use lowercase with underscores (snake_case). Examples: |
| 140 | + `user_utils`, `payment_gateway`. |
| 141 | + |
| 142 | +* _Domain-specific terms_: |
| 143 | + |
| 144 | + * Use `state_vector` to describe a pure state; do not use |
| 145 | + `wavefunction` or `wave_function`. |
| 146 | + |
| 147 | + * If an object is an array or a computational basis state (given by an |
| 148 | + `int`), use the term `state_rep`. If it is the initial state of a |
| 149 | + system, use `initial_state`. |
| 150 | + |
| 151 | + * A function argument (`state_vector`, `state_rep`, or `initial_state`) |
| 152 | + should permit any of the possible representations of a state: A NumPy |
| 153 | + array, a NumPy tensor, an integer representing a qubit-system's |
| 154 | + computational basis state, a sequence of _n_ integers representing a |
| 155 | + qudit's basis state, or a `cirq.ProductState`. The type annotation |
| 156 | + should be `cirq.STATE_VECTOR_LIKE` and you should use |
| 157 | + `cirq.to_valid_state_vector` to canonicalize as a NumPy array of |
| 158 | + amplitudes. If a function expects a NumPy array of amplitudes, its type |
| 159 | + annotation should be `np.ndarray`. |
| 160 | + |
| 161 | +### Docstrings and documentation |
| 162 | + |
| 163 | +This project uses [Google style doc strings]( |
| 164 | +http://google.github.io/styleguide/pyguide.html#381-docstrings) with a Markdown |
| 165 | +flavor and support for LaTeX. Docstrings use tripe double quotes, and the first |
| 166 | +line should be a concise one-line summary of the function or object. |
| 167 | + |
| 168 | +Here is an example docstring: |
| 169 | + |
| 170 | +```python |
| 171 | +def some_function(a: int, b: str) -> float: |
| 172 | + r"""One-line summary of method. |
| 173 | +
|
| 174 | + Additional information about the method, perhaps with some sort of LaTeX |
| 175 | + equation to make it clearer: |
| 176 | +
|
| 177 | + $$ |
| 178 | + M = \begin{bmatrix} |
| 179 | + 0 & 1 \\ |
| 180 | + 1 & 0 |
| 181 | + \end{bmatrix} |
| 182 | + $$ |
| 183 | +
|
| 184 | + Notice that this docstring is an r-string, since the LaTeX has backslashes. |
| 185 | + We can also include example code: |
| 186 | +
|
| 187 | + print(cirq_google.Sycamore) |
| 188 | +
|
| 189 | + You can also do inline LaTeX like $y = x^2$ and inline code like |
| 190 | + `cirq.unitary(cirq.X)`. |
| 191 | +
|
| 192 | + And of course there's the standard sections. |
| 193 | +
|
| 194 | + Args: |
| 195 | + a: The first argument. |
| 196 | + b: Another argument. |
| 197 | +
|
| 198 | + Returns: |
| 199 | + An important value. |
| 200 | +
|
| 201 | + Raises: |
| 202 | + ValueError: The value of `a` wasn't quite right. |
| 203 | + """ |
| 204 | +``` |
| 205 | + |
| 206 | +### Python formatting |
| 207 | + |
| 208 | +Note: the Python code uses 88-column line widths, which is the default used by |
| 209 | +code the formatters `black` and `flynt`. (The C++ files use 80.) |
| 210 | + |
| 211 | +The following programs can be used to perform some automated formatting. |
| 212 | + |
| 213 | +* `black --diff --check PATH/TO/FILE` will report whether the file |
| 214 | + `PATH/TO/FILE` conforms to the project style conventions. |
| 215 | + |
| 216 | +* `black PATH/TO/FILE` will reformat the file. |
| 217 | + |
| 218 | +* `isort PATH/TO/FILE` will sort the `import` statements into a consistent |
| 219 | + form. We follow the [import |
| 220 | + standards](https://www.python.org/dev/peps/pep-0008/#imports) of PEP 8. |
| 221 | + |
| 222 | +* `check/format-incremental` will check and optionally reformat files that |
| 223 | + have been changed since the last commit. |
| 224 | + |
| 225 | +### Python type annotations |
| 226 | + |
| 227 | +This project makes extensive use of type annotations as defined by [PEP 484]( |
| 228 | +https://peps.python.org/pep-0484/). All new code should use type annotations |
| 229 | +where possible, especially on public classes and functions to serve as |
| 230 | +documentation, but also on internal code so that the `mypy` type checker can |
| 231 | +help catch coding errors. |
| 232 | + |
| 233 | +### Python linting |
| 234 | + |
| 235 | +Python files: |
| 236 | + |
| 237 | +* `pylint PATH/TO/FILE` will run `pylint` on the file `PATH/TO/FILE`. This is |
| 238 | + useful to use after editing a single file and before committing changes to |
| 239 | + the git repository. |
| 240 | + |
| 241 | +* `pylint -j0 .` will run `pylint` on all Python files. |
| 242 | + |
| 243 | +### Python testing |
| 244 | + |
| 245 | +Unit and integration tests can be run for the Python portions of this project |
| 246 | +using the following command: |
| 247 | + |
| 248 | +```shell |
| 249 | +make -j run-py-tests |
| 250 | +``` |
| 251 | + |
| 252 | +## C++-specific guidance |
| 253 | + |
| 254 | +This section outlines coding conventions for C++ code in this project. |
| 255 | + |
| 256 | +### C++ naming conventions |
| 257 | + |
| 258 | +* _Variables_: Use lowercase with underscores (snake_case). Examples: |
| 259 | + `user_name`, `total_count`. |
| 260 | + |
| 261 | +* _Functions_: Use CapWords (CamelCase). Examples: `PrintAmplitudes`, |
| 262 | + `FillIndices,`. |
| 263 | + |
| 264 | +* _Classes_/_Structs_: Use CapWords (CamelCase). Examples: `UserManager`, |
| 265 | + `PaymentProcessor`. |
| 266 | + |
| 267 | +* _Namespaces_: Use snake_case. |
| 268 | + |
| 269 | +* _Domain-specific terms_: |
| 270 | + |
| 271 | + * In the C++ code, `state` is used everywhere for state vectors. |
| 272 | + |
| 273 | + * A computational basis state (say, $|0000\rangle$) is typically |
| 274 | + referred to as a `bitstring`. |
| 275 | + |
| 276 | +### C++ formatting |
| 277 | + |
| 278 | +Note: the C++ code files use 80-column line widths. (The Python files use 88.) |
| 279 | + |
| 280 | +* `clang-format -n PATH/TO/FILE` will report whether the file `PATH/TO/FILE` |
| 281 | + conforms to the project style conventions. |
| 282 | + |
| 283 | +* `clang-format -i PATH/TO/FILE` will reformat the file. |
| 284 | + |
| 285 | +#### C++ testing |
| 286 | + |
| 287 | +If you only want to run tests for the core C++ libraries, use this command: |
| 288 | + |
| 289 | +```shell |
| 290 | +bazel test tests:all |
| 291 | +``` |
| 292 | + |
| 293 | +To build tests without running them, instead use: |
| 294 | + |
| 295 | +```shell |
| 296 | +bzel build tests:all |
| 297 | +``` |
0 commit comments