Trotter Bloqs#
Bloqs for Trotter simulation of the real space grid Hamiltonian.
from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register
from qualtran import QBit, QInt, QUInt, QAny
from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma
from typing import *
import numpy as np
import sympy
import cirq
PolynmomialEvaluationInverseSquareRoot
#
Bloq to evaluate a polynomial approximation to inverse Square root from QROM.
Parameters#
in_bitsize
: The number of bits encoding the input registers.out_bitsize
: The number of bits encoding the input registers.
Registers#
in_c{0,1,2,3}
: QROM input containing the 4 polynomial coefficients.out
: Output register to store polynomial approximation to inverse square root.
References#
from qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt import PolynmomialEvaluationInverseSquareRoot
Example Instances#
poly_inv_sqrt = PolynmomialEvaluationInverseSquareRoot(7, 8, 12)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([poly_inv_sqrt],
['`poly_inv_sqrt`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
poly_inv_sqrt_g, poly_inv_sqrt_sigma = poly_inv_sqrt.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(poly_inv_sqrt_g)
show_counts_sigma(poly_inv_sqrt_sigma)
Counts totals:
Add
: 3MultiplyTwoReals
: 3
NewtonRaphsonApproxInverseSquareRoot
#
Bloq implementing a single Newton-Raphson step to approximate the inverse square root.
Given a (polynomial) approximation for \(1/\sqrt{x}\) (which will be \(y_0\)) below we can approximate the inverse square root by
For the case of computing the Coulomb potential we want
where \(x^{k}_i\) is the \(i\)-th electron’s coordinate in 3D and \(k \in \{x,y,z\}\). Thus the input register should store \(\sum_{k=x,y,z} (x^{k}_i-x^{k}_j)^2\).
Parameters#
x_sq_bitsize
: The number of bits encoding the input (integer) register holding (x^2).poly_bitsize
: The number of bits encoding the input (fp-real) register holding y0 (the output of PolynomialEvaluation).output_bitsize
: The number of bits to store the output of the NewtonRaphson step.
Registers#
x_sq
: an input_bitsize size register storing the value x^2.poly
: an poly_bitsize size register storing the value x^2.target
: a target_bitsize size register storing the output of the newton raphson step.
References#
from qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt import NewtonRaphsonApproxInverseSquareRoot
Example Instances#
nr_inv_sqrt = NewtonRaphsonApproxInverseSquareRoot(7, 8, 12)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([nr_inv_sqrt],
['`nr_inv_sqrt`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
nr_inv_sqrt_g, nr_inv_sqrt_sigma = nr_inv_sqrt.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(nr_inv_sqrt_g)
show_counts_sigma(nr_inv_sqrt_sigma)
Counts totals:
Add
: 1MultiplyTwoReals
: 2ScaleIntByReal
: 1SquareRealNumber
: 1
QuantumVariableRotation
#
Bloq implementing Quantum Variable Rotation
This is the basic implementation in Fig. 14 of the reference.
Parameters#
bitsize
: The number of bits encoding the phase angle \(\phi_j\).
Registers#
phi
: a bitsize size register storing the angle \(\phi_j\).
References#
from qualtran.bloqs.chemistry.trotter.grid_ham.qvr import QuantumVariableRotation
Example Instances#
qvr = QuantumVariableRotation(12)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([qvr],
['`qvr`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
qvr_g, qvr_sigma = qvr.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(qvr_g)
show_counts_sigma(qvr_sigma)
Counts totals:
Rz(_theta0)
: 12
KineticEnergy
#
Bloq for the Kinetic energy unitary defined in the reference.
Parameters#
num_elec
: The number of electrons.num_grid
: The number of grid points in each of the x, y and z directions. In total, for a cubic grid, there are \(N = \mathrm{num\_grid}^3\) grid points. The number of bits required (in each spatial dimension) is thus log N + 1, where the + 1 is for the sign bit.
Registers#
system
: The system register of size eta * 3 * nb
References#
from qualtran.bloqs.chemistry.trotter.grid_ham import KineticEnergy
Example Instances#
nelec = 12
ngrid_x = 2 * 8 + 1
kinetic_energy = KineticEnergy(nelec, ngrid_x)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([kinetic_energy],
['`kinetic_energy`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
kinetic_energy_g, kinetic_energy_sigma = kinetic_energy.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(kinetic_energy_g)
show_counts_sigma(kinetic_energy_sigma)
Counts totals:
Free
: 12QuantumVariableRotation
: 12SumOfSquares
: 12
PairPotential
#
Potential Energy bloq for single pair of particles i and j.
Parameters#
bitsize
: The number of bits for a single component of the system register.qrom_data
: The polynomial coefficients to load by QROM.poly_bitsize
: The number of bits of precision for the polynomial coefficients.label
: A label for the bloqs short name. The potential bloq can encode any sort of Coulomb interaction (electron-electron, election-ion, ion-ion,…) so can be reused. This label is to distinguish these different cases.
Registers#
system_i
: The ith electron’s register.system_j
: The jth electron’s register.
References#
from qualtran.bloqs.chemistry.trotter.grid_ham.potential import PairPotential, build_qrom_data_for_poly_fit
from qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt import get_inverse_square_root_poly_coeffs
Example Instances#
bitsize = 7
poly_bitsize = 15
poly_coeffs = get_inverse_square_root_poly_coeffs()
qrom_data = build_qrom_data_for_poly_fit(2 * bitsize + 2, poly_bitsize, poly_coeffs)
qrom_data = tuple(tuple(int(k) for k in d) for d in qrom_data)
pair_potential = PairPotential(bitsize=bitsize, qrom_data=qrom_data, poly_bitsize=poly_bitsize)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([pair_potential],
['`pair_potential`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
pair_potential_g, pair_potential_sigma = pair_potential.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(pair_potential_g)
show_counts_sigma(pair_potential_sigma)
Counts totals:
Allocate
: 1Allocate
: 5Free
: 1Free
: 1Free
: 5NewtonRaphsonApproxInverseSquareRoot
: 1OutOfPlaceAdder
: 3OutOfPlaceAdder
: 3PolynmomialEvaluationInverseSquareRoot
: 1QROM((65536,), ((), (), (), ()), (15, 15, 15, 15))
: 1QuantumVariableRotation
: 1SumOfSquares
: 1
PotentialEnergy
#
Bloq for a Coulombic Unitary.
This is a basic implementation which just iterates through num_elec * (num_elec - 1) electron pairs.
Parameters#
num_elec
: The number of electrons.num_grid
: The number of grid points in each of the x, y and z directions. In total, for a cubic grid there are N = num_grid**3 grid points. The number of bits required (in each spatial dimension) is thus log N + 1, where the + 1 is for the sign bit.label
: A label for the bloqs short name. The potential bloq can encode any sort of Coulomb interaction (electron-electron, election-ion, ion-ion,…) so can be reused. This label is to distinguish these different cases.
Registers#
system
: The system register of size eta * 3 * nb
References#
from qualtran.bloqs.chemistry.trotter.grid_ham import PotentialEnergy
Example Instances#
nelec = 12
ngrid_x = 2 * 8 + 1
potential_energy = PotentialEnergy(nelec, ngrid_x)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([potential_energy],
['`potential_energy`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
potential_energy_g, potential_energy_sigma = potential_energy.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(potential_energy_g)
show_counts_sigma(potential_energy_sigma)
Counts totals:
PairPotential
: 66