Skip to content

Commit

Permalink
generate all permutations of coeff + uccsd op
Browse files Browse the repository at this point in the history
Signed-off-by: Alex McCaskey <[email protected]>
  • Loading branch information
amccaskey committed Jul 26, 2024
1 parent 14fecfe commit 91237f9
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 20 deletions.
18 changes: 17 additions & 1 deletion cudaqlib/gse/utils/pools/uccsd_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ uccsd::generate(const std::unordered_map<std::string, std::any> &config) const {
"parameter of type std::size_t.");
auto numElectrons = getIntLike(iter.value()->second);

iter = findIter({"operatorCoeffs", "operator-coeffs", "operator_coeffs",
"coeffs", "thetas"},
config);
if (!iter.has_value())
throw std::runtime_error("uccsd_pool requires coefficient list config "
"parameter of type vector<double>.");

auto operatorCoeffs =
std::any_cast<std::vector<double>>(iter.value()->second);

auto [singlesAlpha, singlesBeta, doublesMixed, doublesAlpha, doublesBeta] =
cudaq::get_uccsd_excitations(numElectrons, numQubits);

Expand Down Expand Up @@ -65,7 +75,13 @@ uccsd::generate(const std::unordered_map<std::string, std::any> &config) const {
for (auto &d : doublesBeta)
addDoublesExcitation(ops, d[0], d[1], d[2], d[3]);

return ops;
std::vector<spin_op> retOps;
for (auto &c : operatorCoeffs) {
for (auto &op : ops) {
retOps.push_back(c * op);
}
}
return retOps;
}

} // namespace cudaq
41 changes: 23 additions & 18 deletions examples/python/gqe_h2.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import cudaq, cudaqlib, numpy as np
import cudaq, cudaqlib

# Define the molecule
geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))]
molecule = cudaqlib.operators.create_molecule(geometry,
'sto-3g',
0,
0)
molecule = cudaqlib.operators.create_molecule(geometry, 'sto-3g', 0, 0)

# Get the number of qubits
hamiltonian = molecule.hamiltonian
Expand All @@ -14,14 +11,14 @@
numQubits = molecule.hamiltonian.get_qubit_count()

# Create the operator pool
# FIXME needs to better incorporate thetas.
pool = cudaqlib.gse.get_operator_pool('uccsd', num_qubits=4, num_electrons=2)
operatorCoeffs = [
0.003125, -0.003125, 0.00625, -0.00625, 0.0125, -0.0125, 0.025, -0.025,
0.05, -0.05, 0.1, -0.1
]
assert len(pool) == len(operatorCoeffs
)
pool = cudaqlib.gse.get_operator_pool('uccsd',
num_qubits=4,
num_electrons=2,
operator_coeffs=[
0.003125, -0.003125, 0.00625,
-0.00625, 0.0125, -0.0125, 0.025,
-0.025, 0.05, -0.05, 0.1, -0.1
])
# Need an initial state
@cudaq.kernel
def init(q: cudaq.qview):
Expand All @@ -30,14 +27,20 @@ def init(q: cudaq.qview):


# Define the GQE cost function
def cost(sampledPoolOperations : list):
def cost(sampledPoolOperations: list):
"""
Cost should take operator pool indices and
return the associated cost. For the chemistry
example, we'll take uccsd pool indices and return
cudaq observe result
"""
asWords = [cudaq.pauli_word(op.to_string(False)) for op in sampledPoolOperations]
# Convert the operator pool elements to cudaq.pauli_words
asWords = [
cudaq.pauli_word(op.to_string(False)) for op in sampledPoolOperations
]

# Get the pool coefficients as its own list
operatorCoeffs = [op.get_coefficient().real for op in sampledPoolOperations]

@cudaq.kernel
def kernel(numQubits: int, coeffs: list[float],
Expand All @@ -47,10 +50,12 @@ def kernel(numQubits: int, coeffs: list[float],
for i, word in enumerate(words):
exp_pauli(coeffs[i], q, word)

return cudaq.observe(kernel, molecule.hamiltonian, numQubits, operatorCoeffs, asWords).expectation()
return cudaq.observe(kernel, molecule.hamiltonian, numQubits,
operatorCoeffs, asWords).expectation()


minE, optimPoolOps = cudaqlib.gqe(cost, pool)
minE, optimPoolOps = cudaqlib.gqe(cost, pool, max_iters=20)
print(f'Ground Energy = {minE}')
print('Ansatz Ops')
for idx in optimPoolOps: print(pool[idx].to_string(False))
for idx in optimPoolOps:
print(pool[idx].get_coefficient().real, pool[idx].to_string(False))
4 changes: 3 additions & 1 deletion python/bindings/gse/py_gse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ void bindGse(py::module &mod) {
std::string asStr = k.cast<std::string>();

if (py::isinstance<py::int_>(v))
asCpp.insert({k.cast<std::string>(), v.cast<std::size_t>()});
asCpp.insert({asStr, v.cast<std::size_t>()});
if (py::isinstance<py::list>(v))
asCpp.insert({asStr, v.cast<std::vector<double>>()});
}
return operator_pool::get(name)->generate(asCpp);
});
Expand Down
1 change: 1 addition & 0 deletions python/cudaqlib/algorithms/gqe.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ def __internal_run_gqe(temperature_scheduler: TemperatureScheduler,
def gqe(cost, pool, config=None, **kwargs):
cfg = get_default_config() if config == None else config
cfg.vocab_size = len(pool)
if 'max_iters' in kwargs: cfg.max_iters = kwargs['max_iters']
model = Transformer(
cfg, cost, loss='exp') if 'model' not in kwargs else kwargs['model']
optimizer = torch.optim.AdamW(
Expand Down

0 comments on commit 91237f9

Please sign in to comment.