Releases: tequilahub/tequila
v.1.9.8
Overview
- oo more flexible (#366)
- Fix current Qiskit versions
- Update ci_backends.yml
- Add Qiskit GPU simulator
- Refactor QubitWaveFunction, add support for Numpy array backed dense representation (#370)
- Fix some tests
- Reactivate QASM tests
- Enable arbitrary state initialization for Qulacs and Qiskit backends (#371)
Details:
- Enable arbitrary state initialization for Qulacs and Qiskit backends (#371) (Oliver Huettenhofer )
For the Qulacs and Qiskit backend, it makes it possible to initialize circuits with arbitrary wavefunctions instead of only basis states.
This also adds the parameter for sampling and to tq.simulate
.
I have added boolean flags to the backend circuit objects that indicate which backends support this and throw an error message when necessary. This doesn't seem ideal, but I didn't want to change the other backends that I can't test.
Also, combining initial states with a keymap is awkward, I think it only makes sense if we assume that all states on the inactive qubits are the same. For now I disabled it and throw an error message.
I noticed that there's no keymap for sampling, can we get rid of it for simulating too?
Example usage:
import numpy as np
import tequila as tq
from tequila import QubitWaveFunction
U = tq.gates.H(target=0)
state = QubitWaveFunction.from_array(np.array([1.0, 1.0])).normalize()
result = tq.simulate(U, initial_state=state, backend="qulacs")
assert result.isclose(QubitWaveFunction.from_basis_state(n_qubits=1, basis_state=0))
result = tq.simulate(U, initial_state=state, backend="qulacs", samples=100)
assert result.isclose(QubitWaveFunction.from_array(np.array([100.0, 0.0])))
- Refactor QubitWaveFunction, add support for Numpy array backed dense representation (#370) (Oliver Huettenhofer)
When running simulate
to get the output wavefunction of a circuit, currently the conversion from the array that the backend returns to the dictionary format that Tequila uses can be a bottleneck.
This pull request fixes this by refactoring the QubitWaveFunction
class and allowing it to either use a dictionary for sparse wavefunctions, or a Numpy array for dense wavefunctions.
To see the performance improvement, consider the code from my previous pull request, but increase the number of qubits to 22:
import tequila as tq
from math import pi
import time
SIZE = 22
def qft(size: int, inverse: bool = False) -> tq.QCircuit():
U = tq.QCircuit()
for i in range(size):
U += tq.gates.H(target=i)
for j in range(size - i - 1):
U += tq.gates.Phase(target=i + j + 1, angle=(-1 if inverse else 1) * pi / 2 ** (j + 2))
U += tq.gates.CRz(target=i, control=i + j + 1, angle=(-1 if inverse else 1) * pi / 2 ** (j + 1))
return U
U = qft(SIZE)
V = qft(SIZE) + qft(SIZE, inverse=True)
start = time.time()
wfn = tq.simulate(U, backend="qulacs")
print(f"QFT time: {time.time() - start} s")
start = time.time()
wfn = tq.simulate(V, backend="qulacs")
print(f"QFT + inverse QFT time: {time.time() - start} s")
On the current devel
branch, this takes around 10 seconds for only the QFT, and around 2.4 seconds for the QFT combined with the inverse. With this pull request, this is reduced to around 0.95s / 1.85s. Not only is it faster, but the larger circuit is now slower, unlike before where the larger circuit was faster because the result was a sparse wavefunction. The time spent in the Qulacs update_quantum_state
method is around 0.7s / 1.4s, so now the simulation actually makes up the majority of the runtime.
In theory, both sparse and dense representations should be functionally equivalent, and the only difference should be a space-time tradeoff.
Most of the time, the sparse representation is used by default to preserve the previous behaviour.
The dense representation is used when the wavefunction is constructed from an array, or when it is chosen explicitly.
I also made various other changes to the wavefunction API.
- Add Qiskit GPU simulator (Oliver Huettenhofer)
I added support for running the Qiskit simulator on the GPU by creating a subclass that changes the device name. I used the same structure as for the Qulacs GPU simulator.
Using this requires the qiskit-aer-gpu
package.
I also commented out the package check for qulacs-gpu
, because that package is not maintained, instead you have to compile Qulacs with GPU support, see qulacs/qulacs#623 (comment).
Co-authored-by: Oliver Huettenhofer [email protected]
v.1.9.7
Minor convenience changes
Major Performance improvements for wavefunction simulation (without using expecation values)
- Fix
U.export_to("path.png)"
syntax - Deepcopy gates in
__iadd__
ofQCircuit
(#360) - Simulation performance improvements (#359)
- Only apply keymap if necessary in
simulate
- Simplify comparison and only calculate index bitstring when necessary in
from_array
- Fix
numbering_out
parameter ininitialize_bitstring
and remove MSB2LSB/LSB2MSB keymap infrom_array
- Optimize
initialize_bitstring
- Update requirements.txt (no scipy version restriction, issue #361)
- rdm calculation more flexible (#363)
- Update version.py
RDM calculations:
calling the rdm function in the quantum chemistry module with evaluate=False
gives back a tq.QTensor
object
direct evaluation within compute_rdm
is however faster (no repetitions in the simulation)
rdm1, rdm2 = mol.compute_rdms(U=U, evaluate=False)
Performance improvements @ohuettenhofer
see the original pr: #359
no syntax changes
Co-authored-by: Oliver Huettenhofer [email protected]
Co-authored-by: Oliver Hüttenhofer [email protected]
v.1.9.6
New functionality in chemistry module, smaller bug fixes, minor changes.
New functionality in Chemistry Module:
Orbital Rotation Circuits
UR = mol.get_givens_circuit(spatial_orbital_transformation_matrix)
Optimized compilation of Jordan-Wigner UCC excitation gates
According to: Yordanov et. al.
Unitary Conversion between Bravyi-Kitaev and Jordan-Wigner
U = mol.transformation.me_to_jw()
Transform molecular RDMS
e.g. freeze orbital 1 (in JW) explicitly.
rdm1, rdm2 = mol.compute_rdms(..., rdm_trafo=tq.paulis.X([0,1])
Otherwise
- dropping GPyOpt support (not updated to dependencies/new python versions)
- Qiskit translation updated to current qiskit version.
individual PRs
- Fixing Pyscf_mol.from_tq() (#342)
- Fixing Pyscf_mol.from_tq()
- RDMs transformation (#341)
- rdms transformation
- rdm_trafo default from False to None
- fix U.export_to() personalized (#344)
- Add Givens Methods (#343)
- add automatic construction of orbital rotation circuits
- control not passed form QubitExcitation to QubitExcitationImpl (#346)
- fixing error in the initialization of binary hamiltonians closes #394 (#351)
- Fermionic Excitation Implementation (#350)
- Fermionic Excitation Implementation
- made indices in Fermionic excitations more consistent
- Update chemistry_tools.py
- Update qc_base.from tequila (#353)
- Update simulator_qiskit.py (#354)
fixing u1, cu1 deprecation in qiskit - quantumchemistry: added encoding transformations (#345)
- quantum chemistry: added encoding transformations
- Update CI
- updating qiskit noise imports to latest versions (#355)
Co-authored-by: JdelArco98 [email protected]
Co-authored-by: Phillip W. K. Jensen [email protected]
Co-authored-by: JdelArco98 [email protected]
Co-authored-by: Deadly Artist [email protected]
Co-authored-by: Benjamin Meyer [email protected]
v.1.9.5
Tequila Version 1.9.5
- orbital names are better tracked through transformations (#338)
- keep basis info when re-initializing with mol.from_tequila
Example (Gaussian Basis Set)
needs
pip install pyscf
geom = "H 0.0 0.0 0.0\nH 0.0 0.0 1.5"
mol = tq.Molecule(geometry=geom, basis_set="sto-3g")
mol.print_basis_info()
gives
basis_name : sto-3g
orbital_type : hf
orthogonal basis : False
basis functions : 2
active orbitals : [0, 1]
reference : [0]
Current Orbitals
{idx_total:0, idx:0}
coefficients: [0.63074567 0.63074567]
{idx_total:1, idx:1}
coefficients: [ 0.82021585 -0.82021585]
change to "native orbitals", meaning in this case orthonormalized atomics
mol = mol.use_native_orbitals()
mol.print_basis_info()
gives
basis_name : sto-3g
orbital_type : orthonormalized-sto-3g-basis
orthogonal basis : False
basis functions : 2
active orbitals : [0, 1]
reference : [0]
Current Orbitals
{idx_total:0, idx:0}
coefficients: [ 1.02598473 -0.13397565]
{idx_total:1, idx:1}
coefficients: [-0.13397565 1.02598473]
Using the orbital optimization routine will now set the orbital coefficients w.r.t the original basis
U = mol.make_ansatz(name="SPA", edges=[(0,1)])
opt = tq.chemistry.optimize_orbitals(molecule=mol, circuit=U)
mol2 = opt.molecule
mol2.print_basis_info()
basis_name : sto-3g
orbital_type : optimized
orthogonal basis : False
basis functions : 2
active orbitals : [0, 1]
reference : [0]
Current Orbitals
{idx_total:0, idx:0}
coefficients: [-0.63074597 -0.63074537]
{idx_total:1, idx:1}
coefficients: [ 0.82021562 -0.82021608]
Example MRA-PNOs
MRA-PNOs from the madness module, need
pip install pyscf
conda install madtequila -c kottmann
geom = "H 0.0 0.0 0.0\nH 0.0 0.0 1.5"
mol = tq.Molecule(geometry=geom)
mol.print_basis_info()
basis_name : mra
orbital_type : pno
orthogonal basis : True
basis functions : 2
active orbitals : [0, 1]
reference : [0]
Current Orbitals
{idx_total:0, idx:0, occ:2.0, pair:(0, 0)}
coefficients: [1. 0.]
{idx_total:1, idx:1, occ:0.0425791, pair:(0, 0)}
coefficients: [0. 1.]
MRA-PNOs are the native basis, so mol.use_native_basis()
has no effect here. After calling the orbital-optimizer, coefficients of the optimized molecule are w.r.t the MRA-PNOs.
-
fixing syntax issue in post_init of dataclass (#327)
-
Support for phoenics optimizer dropped (dependency not maintained anymore and problems with downstream dependencies are piling up)
-
more convenient randomization initialization for orbital optimizer (e.g
initial_guess="near_zero"
) -
added methods to create annihilation, creation, sz, sp, sm and s2 operators in qubit representation (#336)
ak = mol.make_annihilation_op(k) # spin-orbital k
ck = mol.make_creation_op(k)
ck = ak.dagger()
S = mol.make_s2_op() # total-spin operator
Sz = mol.make_sz_op() # spin-polarization
Nk = mol.make_number_op(k)
Co-authored-by: davibinco [email protected]
v.1.9.4
v.1.9.3
v.1.9.2
v.1.9.1
v.1.9.0
- orbital optimizer more flexible with regards to qubit encodings (#305)
see https://arxiv.org/abs/2105.03836 for more on the "HCB" encoding
orbital optimization with circuits that respect HCB encodings now around a factor of 2 faster.
see tequilahub/quantum-valence-bond for an example in fileh6_spa.py
Example:
import tequila as tq
mol = tq.Molecule(geometry="H 0.0 0.0 1.0\nH 0.0 0.0 2.0\nH 0.0 0.0 3.0\nH 0.0 0.0 4.0")
U = mol.make_ansatz(name="HCB-SPA")
opt = tq.chemistry.optimize_orbitals(mol, U, use_hcb=True)
-
Structures for F3 circuit optimizations (#303)
-
Adding linear depth F3 circuit
-
Adding trotter error feature along testing data (#292)
-
Adding trotter error feature along testing data
-
iSWAP gate and Givens gate (#304)
-
Implement iSWAP gate.
-
Implement Givens gate and bugfix tests iSWAP.
-
Remove iSWAP from Cirq simulator.
-
Refactor
GeneralizedRotation
to generators with (possible) nullspace. (#306) -
Migrate shifted_gates method from QubitExcitation to GeneralizedRotation.
-
Bugfix: list of
GeneralizedRotationImpl
. -
Bugfix: target order matters in
QubitExcitation
. -
Add check for p0 in
GeneralizedRotation
. -
SWAP gate initialization updated to follow conventions
-
Refactor
mapped_qubits
to avoid duplicate code. -
added GenRot shortcut
-
Bugfix: change API to modularized
cirq
package. (#308) -
Refactor circuit build to
cirq_google
module. -
Add check for
cirq_google
, add test. -
Update ci_backends.yml
-
Some BugFixes (#311)
-
UpCCGSD mix_sd fixed
Co-authored-by: Praveen Jayakumar [email protected]
Co-authored-by: Praveen Jayakumar [email protected]
Co-authored-by: lamq317 [email protected]
Co-authored-by: Daria Van Hende [email protected]
Co-authored-by: JdelArco98 [email protected]
v.1.8.9
-
better messages for madtequila (#291)
-
qubit encodings consistency (#294)
-
more consistency in HCB approximation and SPA wavefunctions (#295)
-
more consistency in HCB approximation and SPA wavefunctions
-
keeping up to date with pyscf and setting parse_arg=False in mol constructor (mainly blocks pytest commands)
-
added plot2cube support to madness interface (#296)
-
Update madness_interface.py
-
dropping noisy simulation support in qulacs -- no longer maintained
-
fixing small issue in tests regarding scipy 1.11 release
-
adding args/kwargs to psi4.compute_rdms function
-
adding return to call of base class in psi4.compute_rdms function
# create cube files form madness orbitals
mol = tq.Molecule(geometry="myfile.xyz")
mol.plot2cube(orbital=2) # plots active orbital 2 to a cube file
- preparing for hcb merge (#293)
mol.compute_rdms(use_hcb=True) is now enabled for spin-free matrices. Allows to compute RDMs with half the qubits (given that the circuit is in HCB encoding). - Implementing HCB rdm on general compute_rdms()
- consistency in rdm computation with hcb for reordered transformations
- fixes hcb_rdms and Tests rdms_hcb
Co-authored-by: Javier del Arco [email protected]
Co-authored-by: J. S. Kottmann [email protected]
- enabled HCB in orbital optimization, can be done via tq.chemistry.opt… (#297)
- enabled HCB in orbital optimization, can be done via tq.chemistry.optimize_orbitals(...,use_hcb=True)
# orbital optimization with hardcore-boson circuits
U = mol.make_ansatz("HCB-UpCCD")
opt = tq.chemistry.optimize_orbitals(circuit=U, molecule=mol, initial_guess=guess, use_hcb=True)
- small issue in consistency test, silenced unnecesarry warning
- QASM string parsing bug (#298)
Co-authored-by: Praveen Jayakumar [email protected]
- Update requirements.txt
- Fix NumPy float and int (#301)
Co-authored-by: JdelArco98 [email protected]
Co-authored-by: Javier del Arco [email protected]
Co-authored-by: Praveen Jayakumar [email protected]
Co-authored-by: Praveen Jayakumar [email protected]
Co-authored-by: Erik Kjellgren [email protected]