Skip to content

Commit a556b64

Browse files
committed
Adds git hook for cleaning out notebooks; uses nb-clean to clean up all the things
1 parent ab3cd9f commit a556b64

File tree

7 files changed

+242
-187
lines changed

7 files changed

+242
-187
lines changed

.githooks/pre-commit

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/sh
2+
#
3+
# This pre-commit hook cleans Jupyter notebooks before they are committed.
4+
# It uses nb-clean to remove unnecessary metadata, which helps to reduce
5+
# noise in commits and avoid merge conflicts.
6+
7+
# Check if uv is installed. If not, warn the user and exit gracefully.
8+
if ! command -v uv >/dev/null 2>&1; then
9+
echo "-----------------------------------------------------------------"
10+
echo "Warning: 'uv' is not installed, so notebooks will not be cleaned."
11+
echo "For cleaner commits, please install uv:"
12+
echo "https://astral.sh/uv"
13+
echo "-----------------------------------------------------------------"
14+
exit 0
15+
fi
16+
17+
# Get a list of staged .ipynb files.
18+
STAGED_NOTEBOOKS=$(git diff --cached --name-only --filter=ACM -- "*.ipynb")
19+
20+
if [ -z "$STAGED_NOTEBOOKS" ]; then
21+
exit 0
22+
fi
23+
24+
echo "Cleaning staged notebooks..."
25+
26+
# Loop through the staged notebooks and clean them.
27+
for notebook in $STAGED_NOTEBOOKS; do
28+
echo " - $notebook"
29+
uvx nb-clean clean --remove-all-notebook-metadata "$notebook"
30+
git add "$notebook"
31+
done
32+
33+
echo "Notebook cleaning complete."

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,20 @@ If you're unfamiliar with Jupyter but you're used to a traditional IDE or code e
7070

7171
---
7272

73+
## Git Hooks
74+
75+
This repository includes a _`pre-commit` Git hook_ to automatically clean Jupyter notebook metadata using `nb-clean` before committing. This helps reduce unnecessary noise in commits and avoid merge conflicts.
76+
77+
To enable this, run the following command in your terminal from the root of this repository:
78+
79+
```shell
80+
git config core.hooksPath .githooks
81+
```
82+
83+
**Note:** If `uv` is not installed, the hook will issue a warning and skip the cleaning process.
84+
85+
---
86+
7387
## Support
7488

7589
For support, you can submit issues or PRs in this repository. Alternatively, you can contact us at [support@ionq.com](mailto:support@ionq.com?subject=SDK%20help).

cirq.ipynb

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
{
1515
"cell_type": "code",
16-
"execution_count": 1,
16+
"execution_count": null,
1717
"metadata": {},
1818
"outputs": [],
1919
"source": [
@@ -31,11 +31,26 @@
3131
"execution_count": null,
3232
"metadata": {},
3333
"outputs": [],
34-
"source": "import cirq\nimport cirq_ionq\nimport matplotlib.pyplot as plt\n\nfrom helpers import get_ionq_api_key\n\n# Before you begin, get your API key from https://cloud.ionq.com/settings/keys\n\n# If your API key is stored as \"IONQ_API_KEY\" in your local environment, this\n# should find it. Otherwise you'll be prompted to enter your API key manually.\n\napi_key = get_ionq_api_key()\n\nservice = cirq_ionq.Service(api_key=api_key, default_target='simulator')"
34+
"source": [
35+
"import cirq\n",
36+
"import cirq_ionq\n",
37+
"import matplotlib.pyplot as plt\n",
38+
"\n",
39+
"from helpers import get_ionq_api_key\n",
40+
"\n",
41+
"# Before you begin, get your API key from https://cloud.ionq.com/settings/keys\n",
42+
"\n",
43+
"# If your API key is stored as \"IONQ_API_KEY\" in your local environment, this\n",
44+
"# should find it. Otherwise you'll be prompted to enter your API key manually.\n",
45+
"\n",
46+
"api_key = get_ionq_api_key()\n",
47+
"\n",
48+
"service = cirq_ionq.Service(api_key=api_key, default_target='simulator')"
49+
]
3550
},
3651
{
3752
"cell_type": "code",
38-
"execution_count": 3,
53+
"execution_count": null,
3954
"metadata": {},
4055
"outputs": [],
4156
"source": [
@@ -52,19 +67,9 @@
5267
},
5368
{
5469
"cell_type": "code",
55-
"execution_count": 4,
70+
"execution_count": null,
5671
"metadata": {},
57-
"outputs": [
58-
{
59-
"name": "stdout",
60-
"output_type": "stream",
61-
"text": [
62-
"0: ───H───@───M───\n",
63-
" │ │\n",
64-
"1: ───────X───M───\n"
65-
]
66-
}
67-
],
72+
"outputs": [],
6873
"source": [
6974
"# Before submitting the job, we can visualize the circuit using print().\n",
7075
"\n",
@@ -76,33 +81,25 @@
7681
"execution_count": null,
7782
"metadata": {},
7883
"outputs": [],
79-
"source": "# Now we'll send the job to our backend for processing and plot the results.\n\nresult = service.run(circuit, name=\"Cirq example\", repetitions=100)\n_ = cirq.plot_state_histogram(result, plt.subplot())\nplt.show()"
84+
"source": [
85+
"# Now we'll send the job to our backend for processing and plot the results.\n",
86+
"\n",
87+
"result = service.run(circuit, name=\"Cirq example\", repetitions=100)\n",
88+
"_ = cirq.plot_state_histogram(result, plt.subplot())\n",
89+
"plt.show()"
90+
]
8091
},
8192
{
8293
"cell_type": "markdown",
83-
"source": "## And that's a wrap!\n\nTo continue learning with Cirq, check out more examples and documentation at https://quantumai.google/cirq",
84-
"metadata": {}
94+
"metadata": {},
95+
"source": [
96+
"## And that's a wrap!\n",
97+
"\n",
98+
"To continue learning with Cirq, check out more examples and documentation at https://quantumai.google/cirq"
99+
]
85100
}
86101
],
87-
"metadata": {
88-
"kernelspec": {
89-
"display_name": "venv (3.14.2)",
90-
"language": "python",
91-
"name": "python3"
92-
},
93-
"language_info": {
94-
"codemirror_mode": {
95-
"name": "ipython",
96-
"version": 3
97-
},
98-
"file_extension": ".py",
99-
"mimetype": "text/x-python",
100-
"name": "python",
101-
"nbconvert_exporter": "python",
102-
"pygments_lexer": "ipython3",
103-
"version": "3.14.2"
104-
}
105-
},
102+
"metadata": {},
106103
"nbformat": 4,
107104
"nbformat_minor": 4
108-
}
105+
}

cuda-quantum/main.ipynb

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,68 @@
1717
},
1818
{
1919
"cell_type": "markdown",
20-
"source": "# CUDA-Q\n\n[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ionq-samples/getting-started/blob/main/cuda-quantum/main.ipynb)\n\n[CUDA-Q](https://nvidia.github.io/cuda-quantum/latest/) is NVIDIA's platform for hybrid quantum-classical computing. It provides a unified programming model for quantum algorithm development and seamlessly integrates with classical computing workflows.",
21-
"metadata": {}
20+
"metadata": {},
21+
"source": [
22+
"# CUDA-Q\n",
23+
"\n",
24+
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ionq-samples/getting-started/blob/main/cuda-quantum/main.ipynb)\n",
25+
"\n",
26+
"[CUDA-Q](https://nvidia.github.io/cuda-quantum/latest/) is NVIDIA's platform for hybrid quantum-classical computing. It provides a unified programming model for quantum algorithm development and seamlessly integrates with classical computing workflows."
27+
]
2228
},
2329
{
2430
"cell_type": "code",
2531
"execution_count": null,
2632
"metadata": {},
2733
"outputs": [],
28-
"source": "import os\n\nimport cudaq\n\nfrom helpers import get_ionq_api_key\n\napi_key = get_ionq_api_key()\nos.environ[\"IONQ_API_KEY\"] = api_key # Remove when set_target takes api_key\ncudaq.set_target(\"ionq\", qpu=\"simulator\")"
34+
"source": [
35+
"import os\n",
36+
"\n",
37+
"import cudaq\n",
38+
"\n",
39+
"from helpers import get_ionq_api_key\n",
40+
"\n",
41+
"api_key = get_ionq_api_key()\n",
42+
"os.environ[\"IONQ_API_KEY\"] = api_key # Remove when set_target takes api_key\n",
43+
"cudaq.set_target(\"ionq\", qpu=\"simulator\")"
44+
]
2945
},
3046
{
3147
"cell_type": "code",
3248
"execution_count": null,
3349
"metadata": {},
3450
"outputs": [],
35-
"source": "# Now we set up our circuit. In this case, we're creating a Bell state with two\n# qubits, applying an H gate to qubit-0, a controlled-X gate to both qubits.\n\nSHOTS = 100\n\n\n@cudaq.kernel\ndef bell_state():\n qubits = cudaq.qvector(2)\n h(qubits[0])\n x.ctrl(qubits[0], qubits[1])\n\n\n# Execute the kernel on IonQ's simulator and display the results.\n\nresult = cudaq.sample(bell_state, shots_count=SHOTS)\nprint(result)"
51+
"source": [
52+
"# Now we set up our circuit. In this case, we're creating a Bell state with two\n",
53+
"# qubits, applying an H gate to qubit-0, a controlled-X gate to both qubits.\n",
54+
"\n",
55+
"SHOTS = 100\n",
56+
"\n",
57+
"\n",
58+
"@cudaq.kernel\n",
59+
"def bell_state():\n",
60+
" qubits = cudaq.qvector(2)\n",
61+
" h(qubits[0])\n",
62+
" x.ctrl(qubits[0], qubits[1])\n",
63+
"\n",
64+
"\n",
65+
"# Execute the kernel on IonQ's simulator and display the results.\n",
66+
"\n",
67+
"result = cudaq.sample(bell_state, shots_count=SHOTS)\n",
68+
"print(result)"
69+
]
3670
},
3771
{
3872
"cell_type": "markdown",
39-
"source": "## And that's a wrap!\n\nTo explore more about CUDA-Q and quantum computing with NVIDIA, check out the official documentation at https://nvidia.github.io/cuda-quantum/",
40-
"metadata": {}
73+
"metadata": {},
74+
"source": [
75+
"## And that's a wrap!\n",
76+
"\n",
77+
"To explore more about CUDA-Q and quantum computing with NVIDIA, check out the official documentation at https://nvidia.github.io/cuda-quantum/"
78+
]
4179
}
4280
],
43-
"metadata": {
44-
"kernelspec": {
45-
"display_name": "venv (3.14.2)",
46-
"language": "python",
47-
"name": "python3"
48-
},
49-
"language_info": {
50-
"codemirror_mode": {
51-
"name": "ipython",
52-
"version": 3
53-
},
54-
"file_extension": ".py",
55-
"mimetype": "text/x-python",
56-
"name": "python",
57-
"nbconvert_exporter": "python",
58-
"pygments_lexer": "ipython3",
59-
"version": "3.14.2"
60-
},
61-
"orig_nbformat": 4
62-
},
81+
"metadata": {},
6382
"nbformat": 4,
6483
"nbformat_minor": 2
65-
}
84+
}

pennylane.ipynb

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
{
1515
"cell_type": "code",
16-
"execution_count": 1,
16+
"execution_count": null,
1717
"metadata": {},
1818
"outputs": [],
1919
"source": [
@@ -31,54 +31,96 @@
3131
"execution_count": null,
3232
"metadata": {},
3333
"outputs": [],
34-
"source": "from functools import partial\n\nimport matplotlib.pyplot as plt\nimport pennylane as qml\n\nfrom helpers import get_ionq_api_key\n\n# Before you begin, get your API key from https://cloud.ionq.com/settings/keys\n\n# If your API key is stored as \"IONQ_API_KEY\" in your local environment, this\n# should find it. Otherwise you'll be prompted to enter your API key manually.\n\napi_key = get_ionq_api_key()\n\n# We need to specify the device where the circuit will be executed. In\n# this case we're using the `ionq.simulator`, but if you have QPU access you\n# can specify it here to run the job on a QPU directly.\n\ndev = qml.device(\n 'ionq.simulator',\n api_key=api_key,\n wires=2,\n)"
34+
"source": [
35+
"from functools import partial\n",
36+
"\n",
37+
"import matplotlib.pyplot as plt\n",
38+
"import pennylane as qml\n",
39+
"\n",
40+
"from helpers import get_ionq_api_key\n",
41+
"\n",
42+
"# Before you begin, get your API key from https://cloud.ionq.com/settings/keys\n",
43+
"\n",
44+
"# If your API key is stored as \"IONQ_API_KEY\" in your local environment, this\n",
45+
"# should find it. Otherwise you'll be prompted to enter your API key manually.\n",
46+
"\n",
47+
"api_key = get_ionq_api_key()\n",
48+
"\n",
49+
"# We need to specify the device where the circuit will be executed. In\n",
50+
"# this case we're using the `ionq.simulator`, but if you have QPU access you\n",
51+
"# can specify it here to run the job on a QPU directly.\n",
52+
"\n",
53+
"dev = qml.device(\n",
54+
" 'ionq.simulator',\n",
55+
" api_key=api_key,\n",
56+
" wires=2,\n",
57+
")"
58+
]
3559
},
3660
{
3761
"cell_type": "code",
3862
"execution_count": null,
3963
"metadata": {},
4064
"outputs": [],
41-
"source": "# Now we set up our circuit. In this case, we're creating a circuit with two\n# qubits, applying an H gate to qubit-0, a CNOT gate to both qubits.\n\n@partial(qml.set_shots, shots=100)\n@qml.qnode(dev)\ndef circuit():\n qml.Hadamard(wires=0)\n qml.CNOT(wires=[0, 1])\n return qml.counts()"
65+
"source": [
66+
"# Now we set up our circuit. In this case, we're creating a circuit with two\n",
67+
"# qubits, applying an H gate to qubit-0, a CNOT gate to both qubits.\n",
68+
"\n",
69+
"@partial(qml.set_shots, shots=100)\n",
70+
"@qml.qnode(dev)\n",
71+
"def circuit():\n",
72+
" qml.Hadamard(wires=0)\n",
73+
" qml.CNOT(wires=[0, 1])\n",
74+
" return qml.counts()"
75+
]
4276
},
4377
{
4478
"cell_type": "code",
4579
"execution_count": null,
4680
"metadata": {},
4781
"outputs": [],
48-
"source": "# Before submitting the job, we can visualize the circuit using draw_mpl().\n\nfig, ax = qml.draw_mpl(circuit, style='sketch')()"
82+
"source": [
83+
"# Before submitting the job, we can visualize the circuit using draw_mpl().\n",
84+
"\n",
85+
"fig, ax = qml.draw_mpl(circuit, style='sketch')()"
86+
]
4987
},
5088
{
5189
"cell_type": "code",
5290
"execution_count": null,
5391
"metadata": {},
5492
"outputs": [],
55-
"source": "# Now we'll send the job to our backend for processing and plot the results.\n\ncounts = circuit()\n\n# Robust scalar conversion (works whether values are Python ints, numpy scalars, torch scalars, etc.)\ncounts = {k: int(v) for k, v in counts.items()}\n\n# Optional: If you want missing outcomes shown as 0, define the QNode with counts(all_outcomes=True).\n\nlabels = sorted(counts.keys())\nvalues = [counts[k] for k in labels]\n\nplt.bar(labels, values)\nplt.xlabel(\"bitstring\")\nplt.ylabel(\"counts\")\nplt.title(\"Measurement counts\")\nplt.show()"
93+
"source": [
94+
"# Now we'll send the job to our backend for processing and plot the results.\n",
95+
"\n",
96+
"counts = circuit()\n",
97+
"\n",
98+
"# Robust scalar conversion (works whether values are Python ints, numpy scalars, torch scalars, etc.)\n",
99+
"counts = {k: int(v) for k, v in counts.items()}\n",
100+
"\n",
101+
"# Optional: If you want missing outcomes shown as 0, define the QNode with counts(all_outcomes=True).\n",
102+
"\n",
103+
"labels = sorted(counts.keys())\n",
104+
"values = [counts[k] for k in labels]\n",
105+
"\n",
106+
"plt.bar(labels, values)\n",
107+
"plt.xlabel(\"bitstring\")\n",
108+
"plt.ylabel(\"counts\")\n",
109+
"plt.title(\"Measurement counts\")\n",
110+
"plt.show()"
111+
]
56112
},
57113
{
58114
"cell_type": "markdown",
59-
"source": "## And that's a wrap!\n\nTo continue learning with PennyLane, check out more examples and tutorials at https://pennylane.ai/qml/",
60-
"metadata": {}
115+
"metadata": {},
116+
"source": [
117+
"## And that's a wrap!\n",
118+
"\n",
119+
"To continue learning with PennyLane, check out more examples and tutorials at https://pennylane.ai/qml/"
120+
]
61121
}
62122
],
63-
"metadata": {
64-
"kernelspec": {
65-
"display_name": "venv (3.14.2)",
66-
"language": "python",
67-
"name": "python3"
68-
},
69-
"language_info": {
70-
"codemirror_mode": {
71-
"name": "ipython",
72-
"version": 3
73-
},
74-
"file_extension": ".py",
75-
"mimetype": "text/x-python",
76-
"name": "python",
77-
"nbconvert_exporter": "python",
78-
"pygments_lexer": "ipython3",
79-
"version": "3.14.2"
80-
}
81-
},
123+
"metadata": {},
82124
"nbformat": 4,
83125
"nbformat_minor": 4
84-
}
126+
}

0 commit comments

Comments
 (0)