Skip to content
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

[Costs] add overview documentation notebook #1334

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all 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
251 changes: 251 additions & 0 deletions qualtran/resource_counting/costs.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "d4d7bfac-b2c7-414e-921e-92da858fe216",
"metadata": {},
"source": [
"# Costs\n",
"\n",
"We cannot (yet) run the large ('fault-tolerant scale') quantum algorithms expressed in Qualtran. Instead, a major research goal is to estimate the resources required to implement interesting quantum algorithms. Resources can be time, qubits, T gates, precision, depth, or any number of things. Throughout Qualtran, we use the less ambiguous term \"costs\" to represent these quantities.\n",
"\n",
"In the research literature, there is a surface level agreement on what costs to count: Often we count gates like T, Toffoli, Clifford, and Rotations; And the number of qubits is tabulated. These are the most probable limiting factors of implementing these algorithms on real quantum computers. When it comes to details, agreement on costs is not guaranteed. Researchers may want to consider additional target gatesets or architectures; disagree on how to lump or count cliffords of various sizes; and treat rotations in a variety of ways.\n",
"\n",
"In Qualtran, we provide a set of configurable `CostKey`s that can be used to query algorithms expressed as bloqs. Developers can also implement their own costs by overriding `CostKey` to provide even more customization."
]
},
{
"cell_type": "markdown",
"id": "828e7b0d-0fc9-40ed-9580-c0a092adf65e",
"metadata": {},
"source": [
"## Getting costs\n",
"\n",
"The following functions can be used to query costs for a bloq. Each takes a bloq and a cost key:\n",
"\n",
" - `get_cost_value`\n",
" - `get_cost_cache`\n",
"\n",
"The former will return a single value whereas the latter will return a dictionary mapping every bloq for which a cost was computed to its value."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f0673ac4-e894-40b1-9fc3-cefa43e85427",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.resource_counting import get_cost_value, get_cost_cache"
]
},
{
"cell_type": "markdown",
"id": "e7eea3a8-77ba-403b-a469-6b30dd5be15e",
"metadata": {},
"source": [
"Before we start, we'll create an example bloq with enough complexity to be interesting:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4999ef9c-f4a5-487d-8069-0cb45a2528e5",
"metadata": {},
"outputs": [],
"source": [
"# Construct a PrepTHC bloq for demonstration purposes\n",
"\n",
"from qualtran.bloqs.chemistry.thc.prepare_test import build_random_test_integrals\n",
"\n",
"num_spat = 4\n",
"num_mu = 8\n",
"t_l, eta, zeta = build_random_test_integrals(num_mu, num_spat, seed=7)\n",
"prep_thc = PrepareTHC.from_hamiltonian_coeffs(t_l, eta, zeta, num_bits_state_prep=8)\n",
"prep_thc"
]
},
{
"cell_type": "markdown",
"id": "b0023aa8-7cfe-4f22-8625-e6bbe509c721",
"metadata": {},
"source": [
"`get_cost_value` takes a `Bloq` and a `CostKey` and returns a value. The type of value depends on the particular cost key. For example, if we ask for the qubit count by using the `QubitCount` cost key, we get an integer."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "600e6e48-e888-4021-aecc-3fbc6b26ab6a",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.resource_counting import get_cost_value, QubitCount\n",
"\n",
"get_cost_value(prep_thc, QubitCount())"
]
},
{
"cell_type": "markdown",
"id": "94920338-1145-4f81-8b30-c306c44f470a",
"metadata": {},
"source": [
"`get_cost_cache` has the same input arguments, but instead returns a dictionary containing the (sub-)costs for each bloq that was encountered during the recursive computation. In the following demo, we only print the top 5 entries to avoid overwhelming the output."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c077411d-8f4f-4aa1-b5a4-c3e8fca90e69",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.resource_counting import get_cost_cache\n",
"\n",
"cost_cache = get_cost_cache(prep_thc, QubitCount())\n",
"print(f'cost_cache contains {len(cost_cache)} entries. Displaying top five.\\n')\n",
"\n",
"top_five = sorted(cost_cache.items(), key=lambda x: x[1])[-5:]\n",
"for bloq, val in top_five:\n",
" print(f'{bloq}: {val} qubits')"
]
},
{
"cell_type": "markdown",
"id": "dd7c069d-3820-4a1b-95b4-326dbda87fce",
"metadata": {},
"source": [
"## Configurable Cost Keys\n",
"\n",
"The behavior of a cost computation can be modified by arguments to the cost key. The `QubitCount()` cost is simple: it has no parameters and the value of the cost is a simple integer. `QECGatesCost` will similarly give counts of pre-selected gates. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e1963547-c294-4a0f-bb57-5e2239968eb4",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.resource_counting import QECGatesCost\n",
"\n",
"get_cost_value(prep_thc, QECGatesCost())"
]
},
{
"cell_type": "markdown",
"id": "68bfe8db-e5f2-41ac-bf7d-26f38022eb67",
"metadata": {},
"source": [
"Here, we can see that the output is a `GateCounts` data class that tallys up the number of T, Toffoli, CSwap (aka Fredkin), AND, and Clifford Gates. \n",
"\n",
"For more control, you can use the `BloqCounts` `CostKey` to list specific bloqs to count."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8f1fe5bf-564b-41e1-86fe-14d5fac9759a",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.resource_counting import BloqCount\n",
"from qualtran.bloqs.basic_gates import ZGate, SGate, TGate\n",
"\n",
"z_rots = BloqCount(gateset_bloqs=[ZGate(), SGate(), TGate()], gateset_name='z rots')\n",
"get_cost_value(prep_thc, z_rots)"
]
},
{
"cell_type": "markdown",
"id": "a375c726-4a97-4640-9ced-d7a1bcb700a4",
"metadata": {},
"source": [
"## Querying Multiple Costs\n",
"\n",
"The `query_costs` function will get multiple costs for multiple bloqs simultaneously. Its output is suitable for annotating a call graph diagram"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "20a95e27-9b69-459f-9f39-56a98ec3ad67",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.resource_counting import query_costs\n",
"\n",
"from qualtran.drawing import GraphvizCallGraph\n",
"from qualtran.resource_counting.generalizers import ignore_split_join, ignore_alloc_free\n",
"\n",
"costs = query_costs(prep_thc, [QECGatesCost(), QubitCount()])\n",
"g, _ = prep_thc.call_graph(max_depth=2, generalizer=[ignore_split_join, ignore_alloc_free])\n",
"GraphvizCallGraph(g, costs).get_svg()"
]
},
{
"cell_type": "markdown",
"id": "bebbd98d-3f05-4c20-8339-de336521af20",
"metadata": {},
"source": [
"This code snippet forms the basis of the convenience function for displaying a pre-selected set of cost keys in a call graph format"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "06ea8ba4-f533-4004-86a3-ffcb88bd82f6",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.drawing import show_call_graph\n",
"show_call_graph(prep_thc, max_depth=2)"
]
},
{
"cell_type": "markdown",
"id": "5628148b-f881-4c0a-8ee0-0652f4450217",
"metadata": {},
"source": [
"## Simple Example"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bda94b4f-007e-4cc4-a1d4-f3427f286a98",
"metadata": {},
"outputs": [],
"source": [
"import sympy\n",
"from qualtran.bloqs.basic_gates import CSwap\n",
"\n",
"\n",
"n = sympy.Symbol('n', positive=True, integer=True)\n",
"cswap = CSwap(n)\n",
"show_call_graph(cswap)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading