Skip to content

Commit

Permalink
A little more cleanup on CommutingTermsExample-TL notebook
Browse files Browse the repository at this point in the history
  • Loading branch information
rtvuser1 committed Nov 12, 2024
1 parent 11c555c commit 52dd81c
Showing 1 changed file with 18 additions and 132 deletions.
150 changes: 18 additions & 132 deletions hamlib/qiskit/WIP_benchmarks/CommutingTermsExample-TL.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -100,26 +100,13 @@
},
"outputs": [],
"source": [
"from qiskit import QuantumCircuit,transpile, assemble\n",
"from qiskit import QuantumCircuit, transpile, assemble\n",
"from qiskit_aer import Aer\n",
"import numpy as np\n",
"\n",
"# Initialize the backend and the simulator\n",
"backend = Aer.get_backend('qasm_simulator')\n",
"\n",
"'''\n",
"groups = [\n",
" [('XXII', 0.5), ('XYII', 0.2), ('XIII', 0.7)],\n",
" [('IYYI', 0.3), ('IIYX', 0.6)],\n",
" [('IIZZ', 0.4), ('IZXI', 0.1)]\n",
"]\n",
"\n",
"print(\"******** processing groups:\")\n",
"print(groups)\n",
"'''\n",
"\n",
"\n",
"\n",
"# Function to create circuits for raw Hamiltonian\n",
"def create_circuits_ham(ham):\n",
" circuits = []\n",
Expand All @@ -138,32 +125,21 @@
"\n",
" return circuits\n",
"\n",
"# Function to create circuits for each group\n",
"# Create an individual circuit for each group, returned as list tuples of (circuit, group)\n",
"def create_circuits(groups):\n",
" circuits = []\n",
" for group in groups:\n",
" qc = QuantumCircuit(num_qubits)\n",
"\n",
" ## This is NOT correct, it is adding gates for each term; instead it needs to merge the terms and add one for each qubit\n",
" '''\n",
" for term, coeff in group:\n",
" for i, pauli in enumerate(term):\n",
" if pauli == 'X':\n",
" qc.h(i)\n",
" elif pauli == 'Y':\n",
" qc.sdg(i)\n",
" qc.h(i)\n",
" '''\n",
" # create a merged term so we can create a single circuit for the group\n",
" merged_paulis = ['I'] * num_qubits\n",
" for term, coeff in group:\n",
" for i, pauli in enumerate(term):\n",
" if pauli != \"I\": merged_paulis[i] = pauli\n",
"\n",
" ###print(f\"... merged_paulis = {merged_paulis}\")\n",
"\n",
" merged_term = \"\".join(merged_paulis)\n",
" ###print(f\"... merged_term = {merged_term}\")\n",
" \n",
" ###print(f\"... merged_paulis = {merged_paulis}, merged_term = {merged_term}\")\n",
" \n",
" for i, pauli in enumerate(merged_term):\n",
" if pauli == 'X':\n",
" qc.h(i)\n",
Expand All @@ -172,11 +148,12 @@
" qc.h(i)\n",
" \n",
" qc.measure_all()\n",
" \n",
" circuits.append((qc, group))\n",
"\n",
" return circuits\n",
"\n",
"# Function to calculate expectation values from results\n",
"# Calculate expectation value, or total_energy, from execution results\n",
"# This function operates on tuples of (circuit, group)\n",
"def calculate_expectation(results, circuits, is_commuting=False):\n",
" total_energy = 0\n",
Expand All @@ -186,6 +163,7 @@
" num_shots = sum(counts.values())\n",
" ###print(f\"... got num_shots = {num_shots}: counts = {counts}\")\n",
"\n",
" # process commuting group differently from regular term; operate on merged term\n",
" if is_commuting:\n",
" merge_terms(num_qubits, group)\n",
" \n",
Expand All @@ -202,18 +180,9 @@
" else:\n",
" for term, coeff in group:\n",
" ###print(f\"--> for term: {term}, {coeff}\")\n",
" \n",
" # Calculate the expectation value for each term\n",
" exp_val = get_expectation_term(term, counts)\n",
" '''\n",
" exp_val = 0\n",
" for bitstring, count in counts.items():\n",
" print(f\"... {bitstring} {count}\")\n",
" parity = (-1)**sum([int(bitstring[i]) for i, pauli in enumerate(term) if pauli != 'I'])\n",
" \n",
" exp_val += parity * count\n",
" print(f\"... parity = {parity} {exp_val}\")\n",
" ''' \n",
" #exp_val /= num_shots\n",
" \n",
" total_energy += coeff * exp_val\n",
" ###print(f\" ******* exp_val = {exp_val} {coeff * exp_val}\")\n",
Expand Down Expand Up @@ -245,70 +214,7 @@
" # Normalize by total number of shots to get the expectation value\n",
" return exp_val / total_counts\n",
"\n",
"'''\n",
"def get_expectation_term(term, counts):\n",
" exp_val = 0\n",
" total_counts = sum(counts.values())\n",
"\n",
" for bitstring, count in counts.items():\n",
" # Reverse the bitstring to match Qiskit’s little-endian convention\n",
" bitstring = bitstring[::-1]\n",
" \n",
" # Start with a parity of +1 for each measurement result\n",
" parity = 1.0\n",
" \n",
" # Loop over each qubit in the term and apply eigenvalue mapping\n",
" for i, pauli in enumerate(term):\n",
" if pauli != 'I': # Only consider qubits with X, Y, or Z (ignore 'I')\n",
" # Map 0 to +1, 1 to -1 based on the bit value for this qubit\n",
" parity *= (-2 * int(bitstring[i]) + 1)\n",
" \n",
" # Accumulate weighted parity for this bitstring\n",
" exp_val += parity * count\n",
" \n",
" # Normalize by total number of shots to get the expectation value\n",
" return exp_val / total_counts\n",
"''' \n",
"'''\n",
"def get_expectation_term(term, counts):\n",
" exp_val = 0\n",
" total_counts = sum(counts.values())\n",
"\n",
" for bitstring, count in counts.items():\n",
" parity = 1.0 # Start with +1 for each measurement result\n",
" for i, pauli in enumerate(term):\n",
" if pauli != 'I': # Only consider relevant qubits\n",
" # Map 0 to +1, 1 to -1 based on the bit value\n",
" parity *= (-2 * int(bitstring[i]) + 1)\n",
" \n",
" # Accumulate weighted parity for this bitstring\n",
" exp_val += parity * count\n",
" \n",
" # Normalize by total number of shots to get the expectation value\n",
" return exp_val / total_counts\n",
"'''\n",
"''' \n",
"def get_expectation_term(term, counts):\n",
" exp_val = 0\n",
" total_counts = sum(counts.values())\n",
"\n",
" relevant_qubits = [i for i, pauli in enumerate(term) if pauli != 'I']\n",
" print(f\"... relevant = {relevant_qubits}\")\n",
" \n",
" for bitstring, count in counts.items():\n",
" print(f\"... {bitstring} {count}\")\n",
" print([int(bitstring[i]) for i, pauli in enumerate(term) if pauli != 'I'])\n",
" #parity = (-1)**sum([int(bitstring[i]) for i, pauli in enumerate(term) if pauli != 'I'])\n",
" parity = (-1) ** sum(int(bitstring[i]) for i in relevant_qubits)\n",
" \n",
" print(f\"... raw exp val {parity * count}\")\n",
" exp_val += parity * count\n",
" print(f\" ... parity = {parity} {exp_val}\")\n",
" \n",
" # Normalize by total number of shots to get the expectation value\n",
" return exp_val / total_counts\n",
"'''\n",
"'''\n",
"''' This version attempt does not work properly with merged terms\n",
"def get_expectation_term(term, counts):\n",
" # Identify the relevant qubits for the term\n",
" relevant_qubits = [i for i, pauli in enumerate(term) if pauli != 'I']\n",
Expand All @@ -328,26 +234,6 @@
" # Normalize by total number of shots to get the expectation value\n",
" return exp_val / total_counts\n",
"'''\n",
"'''\n",
"def get_expectation_term(term, counts):\n",
" # Find the indices of relevant qubits (non-'I' qubits in the term)\n",
" relevant_qubits = [i for i, pauli in enumerate(term) if pauli != 'I']\n",
" \n",
" exp_val = 0\n",
" total_counts = sum(counts.values())\n",
" \n",
" for bitstring, count in counts.items():\n",
" # Calculate parity only for relevant qubits in the bitstring\n",
" # Interpret `00` or `11` as +1 and `01` or `10` as -1\n",
" relevant_bits = ''.join(bitstring[i] for i in relevant_qubits)\n",
" parity = (-1) ** relevant_bits.count('1') # Parity based on the number of '1's\n",
" \n",
" # Accumulate weighted contribution of parity * count for this term\n",
" exp_val += parity * count\n",
" \n",
" # Normalize by the total number of shots\n",
" return exp_val / total_counts\n",
"''' \n",
"\n",
"# Merge a group of commuting terms into a merged_term\n",
"def merge_terms(num_qubits, group):\n",
Expand Down Expand Up @@ -459,7 +345,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 6,
"id": "0607c377-aa64-4fd7-bf3a-9353a823413b",
"metadata": {},
"outputs": [
Expand Down Expand Up @@ -489,18 +375,18 @@
" IIXIII: (-1.1086554390135441+0j)\n",
" IXIIII: (-1.1086554390135441+0j)\n",
"\n",
"... executing 2 circuits.\n",
"... constructed 2 circuits for this Hamiltonian.\n",
"\n",
"************ Compute energy of the Hamiltonian 3 times\n",
"\n",
"... total execution time = 0.461\n",
"Total Energy: (-3.822446335312669+0j)\n",
"... total execution time = 0.056\n",
"Total Energy: (-3.8527611324731956+0j)\n",
"\n",
"... total execution time = 0.045\n",
"Total Energy: (-3.8505957898188723+0j)\n",
"... total execution time = 0.057\n",
"Total Energy: (-3.835438391238609+0j)\n",
"\n",
"... total execution time = 0.046\n",
"Total Energy: (-3.809454279386729+0j)\n",
"Total Energy: (-3.887406614942369+0j)\n",
"\n"
]
}
Expand All @@ -524,7 +410,7 @@
" print(f\" {pauli}: {coeff}\") \n",
" circuits = create_circuits(groups)\n",
"\n",
"print(f\"\\n... executing {len(circuits)} circuits.\")\n",
"print(f\"\\n... constructed {len(circuits)} circuits for this Hamiltonian.\")\n",
"\n",
"N = 3\n",
"\n",
Expand Down

0 comments on commit 52dd81c

Please sign in to comment.