minor improvements to examples, documentation, internally used variable names

This commit is contained in:
mattia-robbiano
2025-11-13 10:45:32 +02:00
parent 7ea8dc861b
commit d4ab3eba52
2 changed files with 59 additions and 33 deletions

View File

@@ -28,7 +28,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "a009a5e0-cfd4-4a49-9f7c-e82f252c6147", "id": "0c5a8939",
"metadata": {}, "metadata": {},
"source": [ "source": [
"#### Some hyper parameters" "#### Some hyper parameters"
@@ -36,24 +36,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"id": "b0a1da82",
"metadata": {},
"outputs": [],
"source": [
"import cotengra as ctg\n",
"ctg_opt = ctg.ReusableHyperOptimizer(\n",
" max_time=10,\n",
" minimize='combo',\n",
" slicing_opts=None,\n",
" parallel=True,\n",
" progbar=True\n",
")\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "64162116-1555-4a68-811c-01593739d622", "id": "64162116-1555-4a68-811c-01593739d622",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -67,7 +50,39 @@
"# set numpy random seed\n", "# set numpy random seed\n",
"np.random.seed(42)\n", "np.random.seed(42)\n",
"\n", "\n",
"quimb_backend.setup_backend_specifics(quimb_backend=\"jax\")" "quimb_backend.setup_backend_specifics(quimb_backend=\"jax\", contractions_optimizer='auto-hq')"
]
},
{
"cell_type": "markdown",
"id": "926cfea5",
"metadata": {},
"source": [
"Quimb accepts different methods for optimizing the way it does contractions, that we pass through \"contractions_optimizer\". \n",
"We could also define our own cotengra contraction optimizer! \n",
"\n",
"cotengra is a Python library designed for **optimising contraction trees** and performing efficient contractions of large tensornetworks.\n",
"You can find it here: [https://github.com/jcmgray/cotengra](https://github.com/jcmgray/cotengra)\n",
"\n",
"For the sake of this tutorial however the default \"auto-hq\" will be fine :) "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b0a1da82",
"metadata": {},
"outputs": [],
"source": [
"import cotengra as ctg\n",
"ctg_opt = ctg.ReusableHyperOptimizer(\n",
" max_time=10,\n",
" minimize='combo',\n",
" slicing_opts=None,\n",
" parallel=True,\n",
" progbar=True\n",
")\n",
"# quimb_backend.setup_backend_specifics(quimb_backend=\"jax\", contractions_optimizer='ctg_opt')"
] ]
}, },
{ {

View File

@@ -20,7 +20,7 @@ GATE_MAP = {
"rx": "RX", "rx": "RX",
"ry": "RY", "ry": "RY",
"rz": "RZ", "rz": "RZ",
"u3": "U3", # TODO: check "u3": "U3",
"cx": "CX", "cx": "CX",
"cnot": "CNOT", "cnot": "CNOT",
"cy": "CY", "cy": "CY",
@@ -210,7 +210,10 @@ def expectation_observable_symbolic(
This method takes a Qibo circuit, converts it to a Quimb tensor network circuit, and evaluates the expectation value This method takes a Qibo circuit, converts it to a Quimb tensor network circuit, and evaluates the expectation value
of a Hamiltonian specified by three lists of strings: operators, sites, and coefficients. of a Hamiltonian specified by three lists of strings: operators, sites, and coefficients.
The expectation value is computed by summing the contributions from each term in the Hamiltonian, where each term's The expectation value is computed by summing the contributions from each term in the Hamiltonian, where each term's
expectation is calculated using Quimb's `local_expectation` function. expectation is calculated using Quimb's `local_expectation` function.
Each operator string must act on all different qubits, i.e., for each term, the corresponding sites tuple must contain unique qubit indices.
Example: operators_list = ['xyz', 'xyz'], sites_list = [(1,2,3), (1,2,3)], coeffs_list = [1, 2]
Parameters Parameters
---------- ----------
@@ -218,15 +221,23 @@ def expectation_observable_symbolic(
The quantum circuit to evaluate, provided as a Qibo circuit object. The quantum circuit to evaluate, provided as a Qibo circuit object.
operators_list : list of str operators_list : list of str
List of operator strings representing the symbolic Hamiltonian terms. List of operator strings representing the symbolic Hamiltonian terms.
sites_list : list of str sites_list : list of tuple of int
List of strings, each specifying the qubits (sites) the corresponding operator acts on. Tuples each specifying the qubits (sites) the corresponding operator acts on.
coeffs_list : list of str coeffs_list : list of real/complex
List of strings representing the coefficients for each Hamiltonian term. The coefficients for each Hamiltonian term.
Returns Returns
------- -------
float float
The real part of the expectation value of the Hamiltonian on the given circuit state. The real part of the expectation value of the Hamiltonian on the given circuit state.
""" """
# Validate that no term acts multiple times on the same qubit (no repeated indices in a sites tuple)
for sites in sites_list:
if len(sites) != len(set(sites)):
raise_error(
ValueError,
f"Invalid Hamiltonian term sites {sites}: repeated qubit indices are not allowed "
"within a single term (e.g. (0,0,0) is invalid).",
)
quimb_circuit = self._qibo_circuit_to_quimb( quimb_circuit = self._qibo_circuit_to_quimb(
circuit, circuit,
quimb_circuit_type=self.circuit_ansatz, quimb_circuit_type=self.circuit_ansatz,
@@ -276,12 +287,12 @@ def _qibo_circuit_to_quimb(
circ = quimb_circuit_type(nqubits, **circuit_kwargs) circ = quimb_circuit_type(nqubits, **circuit_kwargs)
for gate in qibo_circ.queue: for gate in qibo_circ.queue:
gname = getattr(gate, "name", None) gate_name = getattr(gate, "name", None)
qname = GATE_MAP.get(gname, None) quimb_gate_name = GATE_MAP.get(gate_name, None)
if qname == "measure": if quimb_gate_name == "measure":
continue continue
if qname is None: if quimb_gate_name is None:
raise_error(ValueError, f"Gate {gname} not supported in Quimb backend.") raise_error(ValueError, f"Gate {gate_name} not supported in Quimb backend.")
params = getattr(gate, "parameters", ()) params = getattr(gate, "parameters", ())
qubits = getattr(gate, "qubits", ()) qubits = getattr(gate, "qubits", ())
@@ -290,10 +301,10 @@ def _qibo_circuit_to_quimb(
gate, "trainable", True gate, "trainable", True
) )
if is_parametrized: if is_parametrized:
circ.apply_gate(qname, *params, *qubits, parametrized=is_parametrized) circ.apply_gate(quimb_gate_name, *params, *qubits, parametrized=is_parametrized)
else: else:
circ.apply_gate( circ.apply_gate(
qname, quimb_gate_name,
*params, *params,
*qubits, *qubits,
) )