Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
Binary file added H 0-pyscf.chk
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these "H 0" files may have been accidental checkins? If so, could you please remove them from the PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they were accidental. Removed!

Binary file not shown.
226 changes: 226 additions & 0 deletions H 0-pyscf.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
#INFO: **** input file is /bin/cudaq-pyscf ****
#!/usr/bin/env python3

import argparse
import importlib, pkgutil
import cudaq_solvers.tools.molecule.pyscf.generators

from fastapi import FastAPI, Response
from pydantic import BaseModel, PlainValidator, PlainSerializer
import uvicorn, os, signal, importlib, pkgutil
from typing import List, Annotated
import numpy as np


def iter_namespace(ns_pkg):
return pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + ".")


discovered_plugins = {}
for finder, name, ispkg in iter_namespace(
cudaq_solvers.tools.molecule.pyscf.generators):
try:
discovered_plugins[name] = importlib.import_module(name)
except ModuleNotFoundError:
pass

hamiltonianGenerators = {
plugin.get_hamiltonian_generator().name(): plugin
for _, plugin in discovered_plugins.items()
}

#############################
# Argument Parser
#############################

parser = argparse.ArgumentParser()

parser.add_argument('--server-mode', action='store_true', default=False)

# Add arguments
parser.add_argument(
'--type',
type=str,
help='type of simulation (hamiltonian generator) - options include {}'.
format([k for k, v in hamiltonianGenerators.items()]),
default='gas_phase')
parser.add_argument('--xyz', help="xyz file", type=str)
parser.add_argument('--basis', help='', type=str)
parser.add_argument('--charge', help="charge of the system", type=int)
parser.add_argument('--out-file-name',
help='base file name for output data.',
type=str)
parser.add_argument('--spin', help="no. of unpaired electrons (2 *s)", type=int)
parser.add_argument('--symmetry', help="", action='store_true', default=False)
parser.add_argument('--memory', help="", type=float, default=4000)
parser.add_argument('--cycles', help="", type=int, default=100)
parser.add_argument('--initguess', help="", type=str, default='minao')
parser.add_argument('--UR', help="", action='store_true', default=False)
parser.add_argument('--MP2', help="", action='store_true', default=False)
parser.add_argument('--nele_cas', help="", type=int, default=None)
parser.add_argument('--norb_cas', help="", type=int, default=None)
parser.add_argument('--natorb', help="", action='store_true', default=False)
parser.add_argument('--casci', help="", action='store_true', default=False)
parser.add_argument('--ccsd', help="", action='store_true', default=False)
parser.add_argument('--casscf', help="", action='store_true', default=False)
parser.add_argument('--integrals_natorb',
help="",
action='store_true',
default=False)
parser.add_argument('--integrals_casscf',
help="",
action='store_true',
default=False)
parser.add_argument('--potfile', help="", type=str, default=None)
parser.add_argument('--verbose',
help="Verbose printout",
action='store_true',
default=False)

# Parse the arguments
args = parser.parse_args()

if not args.server_mode:

if args.type not in hamiltonianGenerators:
raise RuntimeError(f'invalid hamiltonian generator type - {args.type}')
hamiltonianGenerator = hamiltonianGenerators[
args.type].get_hamiltonian_generator()

filterArgs = ['xyz', 'basis']
filteredArgs = {
k: v for (k, v) in vars(args).items() if k not in filterArgs
}
res = hamiltonianGenerator.generate(args.xyz, args.basis, **filteredArgs)
print(res)

exit(0)

app = FastAPI()


@app.get("/shutdown")
async def shutdown():
os.kill(os.getpid(), signal.SIGTERM)
return Response(status_code=200, content='Server shutting down...')


class IntegralsData(BaseModel):
data: List[List]


class MoleculeInput(BaseModel):
basis: str
xyz: str
spin: int
charge: int
type: str = 'gas_phase'
symmetry: bool = False
cycles: int = 100
memory: float = 4000.
initguess: str = 'minao'
UR: bool = False
MP2: bool = False
natorb: bool = False
casci: bool = False
ccsd: bool = False
casscf: bool = False
integrals_natorb: bool = False
integrals_casscf: bool = False
verbose: bool = False
nele_cas: int = None
norb_cas: int = None
potfile: str = None


class Molecule(BaseModel):
energies: dict
num_orbitals: int
num_electrons: int
hpq: IntegralsData
hpqrs: IntegralsData


@app.get("/status")
async def get_status():
return {"status": "available"}


@app.post("/create_molecule")
async def create_molecule(molecule: MoleculeInput):
hamiltonianGenerator = hamiltonianGenerators[
molecule.type].get_hamiltonian_generator()

filterArgs = ['xyz', 'basis']
filteredArgs = {
k: v for (k, v) in vars(molecule).items() if k not in filterArgs
}
filteredArgs['cache_data'] = False
res = hamiltonianGenerator.generate(molecule.xyz, molecule.basis,
**filteredArgs)
return Molecule(energies=res['energies'],
num_orbitals=res['num_orbitals'],
num_electrons=res['num_electrons'],
hpq=IntegralsData(data=res['hpq']['data']),
hpqrs=IntegralsData(data=res['hpqrs']['data']))


if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000, log_level='critical')
#INFO: ******************** input file end ********************


System: uname_result(system='Linux', node='cf83fa189a6c', release='5.14.21-150500.55.97_13.0.78-cray_shasta_c', version='#1 SMP Thu Mar 13 20:09:44 UTC 2025 (330b47d)', machine='x86_64') Threads 256
Python 3.12.3 (main, Aug 14 2025, 17:47:21) [GCC 13.3.0]
numpy 1.26.4 scipy 1.11.4 h5py 3.12.1
Date: Sat Nov 29 18:23:41 2025
PySCF version 2.10.0
PySCF path /usr/local/lib/python3.12/dist-packages/pyscf

[CONFIG] conf_file None
[INPUT] verbose = 4
[INPUT] num. atoms = 2
[INPUT] num. electrons = 2
[INPUT] charge = 0
[INPUT] spin (= nelec alpha-beta = 2S) = 0
[INPUT] symmetry False subgroup None
[INPUT] Mole.unit = angstrom
[INPUT] Symbol X Y Z unit X Y Z unit Magmom
[INPUT] 1 H 0.000000000000 0.000000000000 0.000000000000 AA 0.000000000000 0.000000000000 0.000000000000 Bohr 0.0
[INPUT] 2 H 0.000000000000 0.000000000000 0.747400000000 AA 0.000000000000 0.000000000000 1.412381305500 Bohr 0.0

nuclear repulsion = 0.70802409810008
number of shells = 2
number of NR pGTOs = 6
number of NR cGTOs = 2
basis = sto-3g
ecp = {}
CPU time: 97.38


******** <class 'pyscf.scf.hf.RHF'> ********
method = RHF
initial guess = minao
damping factor = 0
level_shift factor = 0
DIIS = <class 'pyscf.scf.diis.CDIIS'>
diis_start_cycle = 1
diis_space = 8
diis_damp = 0
SCF conv_tol = 1e-09
SCF conv_tol_grad = None
SCF max_cycles = 100
direct_scf = True
direct_scf_tol = 1e-13
chkfile to save SCF result = H 0-pyscf.chk
max_memory 4000 MB (current use 163 MB)
Set gradient conv threshold to 3.16228e-05
Initial guess from minao.
init E= -0.768060785035084
HOMO = -0.516536455786875 LUMO = 0.585619259691897
cycle= 1 E= -1.11632556448611 delta_E= -0.348 |g|= 6.66e-16 |ddm|= 0.85
HOMO = -0.575502858789856 LUMO = 0.663551444043518
cycle= 2 E= -1.11632556448611 delta_E= 0 |g|= 2.22e-16 |ddm|= 8.81e-16
HOMO = -0.575502858789856 LUMO = 0.663551444043518
Extra cycle E= -1.11632556448611 delta_E= 0 |g|= 2.22e-16 |ddm|= 0
converged SCF energy = -1.11632556448611
1 change: 1 addition & 0 deletions H 0_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"num_electrons": 2, "num_orbitals": 2, "hf_energy": -1.116325564486115, "energies": {"hf_energy": -1.116325564486115, "fci_energy": -1.137175710240685, "nuclear_energy": 0.7080240981000804}, "hpq": {"data": [[-1.2488468037963392, 0.0], [0.0, 0.0], [-9.2411068332462e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [-1.2488468037963392, 0.0], [0.0, 0.0], [-9.2411068332462e-17, 0.0], [-2.681424100014354e-16, 0.0], [0.0, 0.0], [-0.4796778131338568, 0.0], [0.0, 0.0], [0.0, 0.0], [-2.681424100014354e-16, 0.0], [0.0, 0.0], [-0.4796778131338568, 0.0]]}, "hpqrs": {"data": [[0.3366719725032414, 0.0], [0.0, 0.0], [5.898059818321144e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0908126657382825, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.3366719725032414, 0.0], [0.0, 0.0], [5.898059818321144e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0908126657382825, 0.0], [0.0, 0.0], [9.71445146547012e-17, 0.0], [0.0, 0.0], [0.09081266573828267, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.33121364716348484, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [9.71445146547012e-17, 0.0], [0.0, 0.0], [0.09081266573828267, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.33121364716348484, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.3366719725032414, 0.0], [0.0, 0.0], [5.898059818321144e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0908126657382825, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.3366719725032414, 0.0], [0.0, 0.0], [5.898059818321144e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0908126657382825, 0.0], [0.0, 0.0], [9.71445146547012e-17, 0.0], [0.0, 0.0], [0.09081266573828267, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.33121364716348484, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [9.71445146547012e-17, 0.0], [0.0, 0.0], [0.09081266573828267, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.33121364716348484, 0.0], [0.0, 0.0], [5.551115123125783e-17, 0.0], [7.979727989493313e-17, 0.0], [0.0, 0.0], [0.3312136471634851, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.09081266573828246, 0.0], [0.0, 0.0], [1.1102230246251565e-16, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [7.979727989493313e-17, 0.0], [0.0, 0.0], [0.3312136471634851, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.09081266573828246, 0.0], [0.0, 0.0], [1.1102230246251565e-16, 0.0], [0.0, 0.0], [0.09081266573828264, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.34814578499360427, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.09081266573828264, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.34814578499360427, 0.0], [0.0, 0.0], [0.0, 0.0], [7.979727989493313e-17, 0.0], [0.0, 0.0], [0.3312136471634851, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.09081266573828246, 0.0], [0.0, 0.0], [1.1102230246251565e-16, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [7.979727989493313e-17, 0.0], [0.0, 0.0], [0.3312136471634851, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.09081266573828246, 0.0], [0.0, 0.0], [1.1102230246251565e-16, 0.0], [0.0, 0.0], [0.09081266573828264, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.34814578499360427, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.09081266573828264, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [8.326672684688674e-17, 0.0], [0.0, 0.0], [0.34814578499360427, 0.0]]}, "operators": {"H 0_one_body.dat": "obi", "H 0_two_body.dat": "tbi"}}
4 changes: 4 additions & 0 deletions docs/sphinx/api/solvers/cpp_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ CUDA-Q Solvers C++ API
.. doxygenclass:: cudaq::solvers::spin_complement_gsd
.. doxygenclass:: cudaq::solvers::uccsd
.. doxygenclass:: cudaq::solvers::uccgsd
.. doxygenclass:: cudaq::solvers::upccgsd

.. doxygenclass:: cudaq::solvers::qaoa_pool

.. doxygenfunction:: cudaq::solvers::get_operator_pool
Expand Down Expand Up @@ -70,6 +72,8 @@ CUDA-Q Solvers C++ API
.. doxygenfunction:: cudaq::solvers::stateprep::uccsd(cudaq::qview<>, const std::vector<double>&, std::size_t)
.. doxygenfunction:: cudaq::solvers::stateprep::get_uccgsd_pauli_lists
.. doxygenfunction:: cudaq::solvers::stateprep::uccgsd(cudaq::qview<>, const std::vector<double>&, const std::vector<std::vector<cudaq::pauli_word>>&, const std::vector<std::vector<double>>&)
.. doxygenfunction:: cudaq::solvers::stateprep::get_upccgsd_pauli_lists
.. doxygenfunction:: cudaq::solvers::stateprep::upccgsd(cudaq::qview<>, const std::vector<double>&, const std::vector<std::vector<cudaq::pauli_word>>&, const std::vector<std::vector<double>>&)


.. doxygenstruct:: cudaq::solvers::qaoa_result
Expand Down
4 changes: 4 additions & 0 deletions docs/sphinx/api/solvers/python_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ CUDA-Q Solvers Python API
.. autofunction:: cudaq_solvers.stateprep.get_num_uccsd_parameters
.. autofunction:: cudaq_solvers.stateprep.get_uccsd_excitations
.. autofunction:: cudaq_solvers.stateprep.get_uccgsd_pauli_lists
.. autofunction:: cudaq_solvers.stateprep.get_upccgsd_pauli_lists

.. autofunction:: cudaq_solvers.stateprep.uccgsd
.. autofunction:: cudaq_solvers.stateprep.upccgsd


.. autofunction:: cudaq_solvers.get_num_qaoa_parameters

Expand Down
31 changes: 31 additions & 0 deletions docs/sphinx/components/solvers/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,12 @@ CUDA-QX provides several pre-built operator pools for ADAPT-VQE:
single and double excitations, regardless of their occupied/virtual status in the reference state.
Capable of capturing both dynamic and static (strong) correlation
but at the cost of increased circuit depth and parameter count.
* **upccgsd**: UCC generalized singles and paired doubles.
A structured, lower-depth variant of UCCGSD in which double excitations are restricted to paired electron
transfers between spatial orbitals, following the UpCC (pair-cluster) construction.
While less expressive than full UCCGSD, it retains generalized spin-preserving singles
and the most physically relevant pair-correlation channels, substantially reducing circuit depth and parameter count.
This makes UpCCGSD attractive for larger systems or hardware-constrained regimes where UCCGSD is too costly.
* **qaoa**: QAOA mixer excitation operators
It generates all possible single-qubit X and Y terms, along with all possible
two-qubit interaction terms (XX, YY, XY, YX, XZ, ZX, YZ, ZY) across every pair of qubits.
Expand Down Expand Up @@ -537,6 +543,10 @@ CUDA-QX provides several pre-built operator pools for ADAPT-VQE:
"uccgsd",
num_orbitals=molecule.n_orbitals
)
upccgsd_ops = solvers.get_operator_pool(
"upccgsd",
num_orbitals=molecule.n_orbitals
)

Available Ansatz
^^^^^^^^^^^^^^^^^^
Expand All @@ -545,6 +555,7 @@ CUDA-QX provides several state preparations ansatz for VQE.

* **uccsd**: UCCSD operators
* **uccgsd**: UCC generalized singles and doubles
* **upccgsd**: UCC generalized singles and paired doubles

.. code-block:: python

Expand Down Expand Up @@ -585,6 +596,26 @@ CUDA-QX provides several state preparations ansatz for VQE.
for i in range(numElectrons):
x(q[i])
solvers.stateprep.uccgsd(q, thetas, pauliWordsList, coefficientsList)

# Using UpCCGSD ansatz
geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))]
molecule = solvers.create_molecule(geometry, 'sto-3g', 0, 0, casci=True)

numQubits = molecule.n_orbitals * 2
numElectrons = molecule.n_electrons

# Get grouped Pauli words and coefficients from UpCCGSD pool
pauliWordsList, coefficientsList = solvers.stateprep.get_upccgsd_pauli_lists(
numQubits, only_singles=False, only_doubles=False)

@cudaq.kernel
def ansatz(numQubits: int, numElectrons: int, thetas: list[float],
pauliWordsList: list[list[cudaq.pauli_word]],
coefficientsList: list[list[float]]):
q = cudaq.qvector(numQubits)
for i in range(numElectrons):
x(q[i])
solvers.stateprep.upccgsd(q, thetas, pauliWordsList, coefficientsList)


Algorithm Parameters
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/****************************************************************-*- C++ -*-****
* Copyright (c) 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/

#pragma once

#include "../operator_pool.h"

namespace cudaq::solvers {

/// @brief UpCCGSD operator pool is a class which generates a pool
/// of UpCCGSD operators for use in quantum algorithms, like Adapt-VQE.
/// @details This class extends the operator_pool interface
/// therefore inherits the extension_point template, allowing for
/// runtime extensibility. The UpCCGSD pool restricts generalized
/// doubles to paired αβ→αβ excitations while retaining spin-preserving
/// generalized singles.
class upccgsd : public operator_pool {

public:
/// @brief Generate a vector of spin operators based on the provided
/// configuration.
/// @details The UpCCGSD operator pool is generated with an imaginary factor
/// 'i' in the coefficients of the operators, which simplifies the use for
/// running Adapt-VQE.
/// @param config A heterogeneous map containing configuration parameters for
/// operator generation, including the number of spatial orbitals
/// ("num-orbitals" or "num_orbitals").
/// @return A vector of cudaq::spin_op objects representing the generated
/// UpCCGSD operator pool.
std::vector<cudaq::spin_op>
generate(const heterogeneous_map &config) const override;

/// @brief Call to macro for defining the creator function for an extension
/// @details This function is used by the extension point mechanism to create
/// instances of the upccgsd class.
CUDAQ_EXTENSION_CREATOR_FUNCTION(operator_pool, upccgsd)
};

/// @brief Register the upccgsd extension type with the CUDA-Q framework
CUDAQ_REGISTER_TYPE(upccgsd)

} // namespace cudaq::solvers
Loading