From 30d195bec1b77b48b78a7f921f575169a5557f13 Mon Sep 17 00:00:00 2001 From: Michelle Richer Date: Thu, 22 Aug 2024 12:02:18 -0400 Subject: [PATCH 001/197] Add placeholder FanCI Wfn (squash this commit) --- pyci/fanci/__init__.py | 2 + pyci/fanci/placeholder.py | 135 ++++++++++++++++++++++++++++++++++++++ pyci/include/pyci.h | 47 +++++++++++++ pyci/src/binding.cpp | 33 ++++++++++ pyci/src/placeholder.cpp | 75 +++++++++++++++++++++ 5 files changed, 292 insertions(+) create mode 100644 pyci/fanci/placeholder.py create mode 100644 pyci/src/placeholder.cpp diff --git a/pyci/fanci/__init__.py b/pyci/fanci/__init__.py index 150f7e4..b89b56c 100644 --- a/pyci/fanci/__init__.py +++ b/pyci/fanci/__init__.py @@ -10,6 +10,7 @@ "AP1roG", "DetRatio", "pCCDS", + "Placeholder", ] @@ -18,3 +19,4 @@ from .ap1rog import AP1roG from .detratio import DetRatio from .pccds import pCCDS +from .placeholder import Placeholder diff --git a/pyci/fanci/placeholder.py b/pyci/fanci/placeholder.py new file mode 100644 index 0000000..8367ba5 --- /dev/null +++ b/pyci/fanci/placeholder.py @@ -0,0 +1,135 @@ +r""" +FanCI Placeholder module. + +""" + +from typing import Any, Union + +import numpy as np + +import pyci + +from ..pyci import PlaceholderObjective +from .fanci import FanCI + + +__all___ = [ + "Placeholder", +] + + +class Placeholder(FanCI): + r""" + DOC + """ + + def __init__( + self, + ham: pyci.hamiltonian, + nocc: int, + nproj: int = None, + wfn: pyci.fullci_wfn = None, + **kwargs: Any, + ) -> None: + r""" + Initialize the FanCI problem. + + Parameters + ---------- + ham : pyci.hamiltonian + PyCI Hamiltonian. + nocc : int + Number of occupied orbitals. + nproj : int, optional + Number of determinants in projection ("P") space. + wfn : pyci.fullci_wfn, optional + If specified, this PyCI wave function defines the projection ("P") space. + kwargs : Any, optional + Additional keyword arguments for base FanCI class. + + """ + # SEE OTHER FANCI WFNS + + if not isinstance(ham, pyci.hamiltonian): + raise TypeError(f"Invalid `ham` type `{type(ham)}`; must be `pyci.hamiltonian`") + + # Initialize base class + FanCI.__init__(self, ham, wfn, nproj, nparam, **kwargs) + + self._cext = PlaceholderObjective( + self._ci_op, self._wfn, + idx_det_cons=idx_det_cons, det_cons=det_cons, + idx_param_cons=idx_param_cons, param_cons=param_cons, + ) + + def compute_overlap(self, x: np.ndarray) -> np.ndarray: + r""" + Compute the FanCI overlap vector. + + Parameters + ---------- + x : np.ndarray + Parameter array, [p_0, p_1, ..., p_n]. + + Returns + ------- + ovlp : np.ndarray + Overlap array. + + """ + return self._cext.overlap(x) + + def compute_overlap_deriv(self, x: np.ndarray) -> np.ndarray: + r""" + Compute the FanCI overlap derivative matrix. + + Parameters + ---------- + x : np.ndarray + Parameter array, [p_0, p_1, ..., p_n]. + + Returns + ------- + ovlp : np.ndarray + Overlap derivative array. + + """ + return self._cext.d_overlap(x) + + def compute_objective(self, x: np.ndarray) -> np.ndarray: + r""" + Compute the FanCI objective function. + + f : x[k] -> y[n] + + Parameters + ---------- + x : np.ndarray + Parameter array, [p_0, p_1, ..., p_n, E]. + + Returns + ------- + obj : np.ndarray + Objective vector. + + """ + return self._cext.objective(self._ci_op, x) + + def compute_jacobian(self, x: np.ndarray) -> np.ndarray: + r""" + Compute the Jacobian of the FanCI objective function. + + j : x[k] -> y[n, k] + + Parameters + ---------- + x : np.ndarray + Parameter array, [p_0, p_1, ..., p_n, E]. + + Returns + ------- + jac : np.ndarray + Jacobian matrix. + + """ + return self._cext.jacobian(self._ci_op, x) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 826195c..5f78bd0 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -799,4 +799,51 @@ class APIGObjective : public Objective { virtual void d_overlap(const size_t, const double *x, double *y); }; +// Specialize base template class against one of {DOCI,FullCI,GenCI}Wfn +class PlaceholderObjective : public Objective { +public: + using Objective::nproj; // # of determinants in P space + using Objective::nconn; // # of determinants in S space + using Objective::nparam; // # of FanCI parameters + using Objective::ovlp; // Overlap vector + using Objective::d_ovlp; // Overlap gradient matrix + + // Declare variables you want to store to faciliate the computation + // of {d_,}overlap here: + // std::size_t nrow; + // std::size_t ncol; + // std::vector part_list; + // ... + // ... + +public: + // Keep in mind the {DOCI,FullCI,GenCI}Wfn class names in + // the arguments below depend on the template specialization + + // C++ constructor + PlaceholderObjective(const SparseOp &, const FullCIWfn &, + const std::size_t = 0UL, const long * = nullptr, const double * = nullptr, + const std::size_t = 0UL, const long * = nullptr, const double * = nullptr); + + // Python constructor + PlaceholderObjective(const SparseOp &, const FullCIWfn &, + const pybind11::object, const pybind11::object, + const pybind11::object, const pybind11::object); + + // C++ copy constructor + PlaceholderObjective(const PlaceholderObjective &); + + // C++ move constructor + PlaceholderObjective(PlaceholderObjective &&) noexcept; + + // Initializer for {d_,}overlap variables + void init_overlap(const FullCIWfn &); + + // Overlap function + virtual void overlap(const size_t, const double *x, double *y); + + // Overlap gradient function + virtual void d_overlap(const size_t, const double *x, double *y); +}; + } // namespace pyci diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 6be94ce..9d36b72 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1440,6 +1440,39 @@ apig_objective.def(py::init> placeholder_objective(m, "PlaceholderObjective"); + +// Class documentation +placeholder_objective.doc() = R"""( +Placeholder objective class. +)"""; + +// Initializer (keep in mind the Wfn argument should be the right class) +placeholder_objective.def(py::init(), +R"""( +Initialize the Placeholder objective instance. + Parameters ---------- op : pyci.sparse_op diff --git a/pyci/src/placeholder.cpp b/pyci/src/placeholder.cpp new file mode 100644 index 0000000..89fc8c1 --- /dev/null +++ b/pyci/src/placeholder.cpp @@ -0,0 +1,75 @@ +/* This file is part of PyCI. + * + * PyCI is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * PyCI is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyCI. If not, see . */ + +#include + +namespace pyci { + +// See apig.cpp for reference + +PlaceholderObjective::PlaceholderObjective(const SparseOp &op_, const FullCIWfn &wfn_, + const std::size_t n_detcons_, + const long *idx_detcons_, + const double *val_detcons_, + const std::size_t n_paramcons_, + const long *idx_paramcons_, + const double *val_paramcons_) +: Objective::Objective(op_, wfn_, n_detcons_, idx_detcons_, val_detcons_, n_paramcons_, idx_paramcons_, val_paramcons_) +{ + init_overlap(wfn_); +} + +PlaceholderObjective::PlaceholderObjective(const SparseOp &op_, const FullCIWfn &wfn_, + const pybind11::object idx_detcons_, + const pybind11::object val_detcons_, + const pybind11::object idx_paramcons_, + const pybind11::object val_paramcons_) +: Objective::Objective(op_, wfn_, idx_detcons_, val_detcons_, idx_paramcons_, val_paramcons_) +{ + init_overlap(wfn_); +} + +PlaceholderObjective::PlaceholderObjective(const PlaceholderObjective &obj) +: Objective::Objective(obj) +{ + return; +} + +PlaceholderObjective::PlaceholderObjective(PlaceholderObjective &&obj) noexcept +: Objective::Objective(obj){ + return; +} + +void PlaceholderObjective::init_overlap(const FullCIWfn &wfn_) +{ + // Initialize your class-specific variables here + return; +} + +void PlaceholderObjective::overlap(const size_t ndet, const double *x, double *y) +{ + // x == parameters p_j + // y == overlap vector σ_i + return; +} + +void PlaceholderObjective::d_overlap(const size_t ndet, const double *x, double *y) +{ + // x == parameters p_j + // y == unwrapped overlap objective ∂σ_i/∂p_j + return; +} + +} // namespace pyci From 73ec79c757001def74a6e03c344005d40b233aca Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 11 Nov 2024 17:23:51 -0500 Subject: [PATCH 002/197] updated for AP1roGSDGeneralized_sen-o wavefunction --- pyci/fanci/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/fanci/__init__.py b/pyci/fanci/__init__.py index b89b56c..16a6a7c 100644 --- a/pyci/fanci/__init__.py +++ b/pyci/fanci/__init__.py @@ -10,7 +10,7 @@ "AP1roG", "DetRatio", "pCCDS", - "Placeholder", + "AP1roGeneralizedSeno", ] @@ -19,4 +19,4 @@ from .ap1rog import AP1roG from .detratio import DetRatio from .pccds import pCCDS -from .placeholder import Placeholder +from .ap1rogen import AP1roGeneralizedSeno From 0bd7f8635019f3e09620926222424a7c6d061602 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 11 Nov 2024 17:32:10 -0500 Subject: [PATCH 003/197] renamed file for AP1roGSDGeneralized_sen-o --- pyci/fanci/{placeholder.py => ap1rogen.py} | 55 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) rename pyci/fanci/{placeholder.py => ap1rogen.py} (58%) diff --git a/pyci/fanci/placeholder.py b/pyci/fanci/ap1rogen.py similarity index 58% rename from pyci/fanci/placeholder.py rename to pyci/fanci/ap1rogen.py index 8367ba5..335f82a 100644 --- a/pyci/fanci/placeholder.py +++ b/pyci/fanci/ap1rogen.py @@ -1,5 +1,5 @@ r""" -FanCI Placeholder module. +FanCI AP1roGeneralizedseno module for AP1roGSDGeneralized_sen-o wavefunction. """ @@ -9,16 +9,16 @@ import pyci -from ..pyci import PlaceholderObjective +from ..pyci import AP1roGeneralizedSenoObjective from .fanci import FanCI __all___ = [ - "Placeholder", + "AP1roGeneralizedSeno", ] -class Placeholder(FanCI): +class AP1roGeneralizedSeno(FanCI): r""" DOC """ @@ -26,7 +26,8 @@ class Placeholder(FanCI): def __init__( self, ham: pyci.hamiltonian, - nocc: int, + nocc_up: int, + nocc_dn: int, nproj: int = None, wfn: pyci.fullci_wfn = None, **kwargs: Any, @@ -53,9 +54,53 @@ def __init__( if not isinstance(ham, pyci.hamiltonian): raise TypeError(f"Invalid `ham` type `{type(ham)}`; must be `pyci.hamiltonian`") + nocc = nocc_up + nocc_dn + nparam = nocc_up * (ham.nbasis - nocc_up) + 1 #less params considering we added singles as well + nproj = nparam if nproj is None else nproj + + if wfn is None: + wfn = pyci.doci_wfn(ham.nbasis, nocc_up, nocc_dn) + print("\nCreated doci wfn instance for placeholder") + + wfn.add_excited_dets(1) # add pair excited determinants + + print("\nCreating fci wfn") + wfn = pyci.fullci_wfn(wfn) + pyci.add_excitations(wfn, 1) # add singles + elif not isinstance(wfn, pyci.fullci_wfn): + raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.fullci_wfn`") + elif wfn.nocc_up != nocc_up or wfn.nocc_dn != nocc_dn: + raise ValueError(f"wfn.nocc_{{up, dn}} does not match `nocc_{{up, dn}}={nocc_up, nocc_dn}` parameter") + + # Initialize base class + print("\nInitializing base class") FanCI.__init__(self, ham, wfn, nproj, nparam, **kwargs) + # Assign reference occupations + #ref_occs_up = np.arange(nocc_up, dtype=pyci.c_long) + #ref_occs_dn = np.arange(nocc_dn, dtype=pyci.c_long) + + # Save sub-class-specific attributes + #self._ref_occs = [ref_occs_up, ref_occs_dn] + + # Initiazlize C++ extension + try: + norm_det = kwargs["norm_det"] + idx_det_cons = np.asarray([elem[0] for elem in norm_det], dtype=int) + det_cons = np.asarray([elem[1] for elem in norm_det], dtype=int) + except KeyError: + idx_det_cons = None + det_cons = None + + try: + norm_param = kwargs["norm_param"] + idx_param_cons = np.asarray([elem[0] for elem in norm_param], dtype=int) + param_cons = np.asarray([elem[1] for elem in norm_param], dtype=int) + except KeyError: + idx_param_cons = None + param_cons = None + self._cext = PlaceholderObjective( self._ci_op, self._wfn, idx_det_cons=idx_det_cons, det_cons=det_cons, From 54c7e43932a78d1c365a2d850dd9b0895d32d12c Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 11 Nov 2024 18:29:19 -0500 Subject: [PATCH 004/197] Add AP1roGeneralizedSenoObjective to pyci.h --- pyci/include/pyci.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 5f78bd0..1cc5500 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -799,20 +799,22 @@ class APIGObjective : public Objective { virtual void d_overlap(const size_t, const double *x, double *y); }; -// Specialize base template class against one of {DOCI,FullCI,GenCI}Wfn -class PlaceholderObjective : public Objective { +// Specialize base template class for AP1roGSDGeneralized_sen-o against GenCI Wfn +class AP1roGeneralizedSenoObjective : public Objective { public: - using Objective::nproj; // # of determinants in P space - using Objective::nconn; // # of determinants in S space - using Objective::nparam; // # of FanCI parameters - using Objective::ovlp; // Overlap vector - using Objective::d_ovlp; // Overlap gradient matrix + using Objective::nproj; // # of determinants in P space + using Objective::nconn; // # of determinants in S space + using Objective::nparam; // # of FanCI parameters + using Objective::ovlp; // Overlap vector + using Objective::d_ovlp; // Overlap gradient matrix // Declare variables you want to store to faciliate the computation // of {d_,}overlap here: - // std::size_t nrow; - // std::size_t ncol; - // std::vector part_list; + std::size_t nrow; + std::size_t ncol; + std::vector nexc_list; + std::vector hole_list; + std::vector part_list; // ... // ... @@ -821,23 +823,23 @@ class PlaceholderObjective : public Objective { // the arguments below depend on the template specialization // C++ constructor - PlaceholderObjective(const SparseOp &, const FullCIWfn &, + AP1roGeneralizedSenoObjective(const SparseOp &, const GenCIWfn &, const std::size_t = 0UL, const long * = nullptr, const double * = nullptr, const std::size_t = 0UL, const long * = nullptr, const double * = nullptr); // Python constructor - PlaceholderObjective(const SparseOp &, const FullCIWfn &, + AP1roGeneralizedSenoObjective(const SparseOp &, const GenCIWfn &, const pybind11::object, const pybind11::object, const pybind11::object, const pybind11::object); // C++ copy constructor - PlaceholderObjective(const PlaceholderObjective &); + AP1roGeneralizedSenoObjective(const AP1roGeneralizedSenoObjective &); // C++ move constructor - PlaceholderObjective(PlaceholderObjective &&) noexcept; + AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&) noexcept; // Initializer for {d_,}overlap variables - void init_overlap(const FullCIWfn &); + void init_overlap(const GenCIWfn &); // Overlap function virtual void overlap(const size_t, const double *x, double *y); From 78bb5e206943bdf2c0bae8bcd900400802e08122 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 11 Nov 2024 18:47:49 -0500 Subject: [PATCH 005/197] Declare & define Python class based on the AP1roGeneralizedSenoObjective in binding.cpp --- pyci/src/binding.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 9d36b72..b3b3d13 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1460,18 +1460,18 @@ param_cons : np.ndarray(Np, dtype=pyci.c_double) py::arg("op"), py::arg("wfn"), py::arg("idx_det_cons") = py::none(), py::arg("det_cons") = py::none(), py::arg("idx_param_cons") = py::none(), py::arg("param_cons") = py::none()); -// Declare Python class based on PlaceholderObjective -py::class_> placeholder_objective(m, "PlaceholderObjective"); +// Declare Python class based on AP1roGeneralizedSenoObjective +py::class_> ap1rogen_objective(m, "AP1roGeneralizedSenoObjective"); // Class documentation -placeholder_objective.doc() = R"""( -Placeholder objective class. +ap1rogen_objective.doc() = R"""( +AP1roGSDGeneralized_sen-o objective class. )"""; // Initializer (keep in mind the Wfn argument should be the right class) -placeholder_objective.def(py::init(), +ap1rogen_objective.def(py::init(), R"""( -Initialize the Placeholder objective instance. +Initialize the AP1roGSDGeneralized_sen-o objective instance. Parameters ---------- From 0a54be702d34874ba4dcd7b3b441c18979dc38c5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 11 Nov 2024 22:17:10 -0500 Subject: [PATCH 006/197] Generate GenCIwfn using FullCIwfn --- pyci/fanci/ap1rogen.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index 335f82a..7f27cf4 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -26,10 +26,9 @@ class AP1roGeneralizedSeno(FanCI): def __init__( self, ham: pyci.hamiltonian, - nocc_up: int, - nocc_dn: int, + nocc: int, nproj: int = None, - wfn: pyci.fullci_wfn = None, + wfn: pyci.genci_wfn = None, **kwargs: Any, ) -> None: r""" @@ -43,7 +42,7 @@ def __init__( Number of occupied orbitals. nproj : int, optional Number of determinants in projection ("P") space. - wfn : pyci.fullci_wfn, optional + wfn : pyci.genci_wfn, optional If specified, this PyCI wave function defines the projection ("P") space. kwargs : Any, optional Additional keyword arguments for base FanCI class. @@ -54,23 +53,27 @@ def __init__( if not isinstance(ham, pyci.hamiltonian): raise TypeError(f"Invalid `ham` type `{type(ham)}`; must be `pyci.hamiltonian`") - nocc = nocc_up + nocc_dn - nparam = nocc_up * (ham.nbasis - nocc_up) + 1 #less params considering we added singles as well + nparam = nocc * (ham.nbasis - nocc) + (2 * nocc) * (2 * (ham.nbasis - nocc)) + 1 #less params considering we added singles as well nproj = nparam if nproj is None else nproj if wfn is None: - wfn = pyci.doci_wfn(ham.nbasis, nocc_up, nocc_dn) - print("\nCreated doci wfn instance for placeholder") + wfn = pyci.genci_wfn(ham.nbasis, nocc, 0) + print("\nCreated GenCI wfn instance for AP1roGSDGeneralized_sen-o.") wfn.add_excited_dets(1) # add pair excited determinants print("\nCreating fci wfn") wfn = pyci.fullci_wfn(wfn) - pyci.add_excitations(wfn, 1) # add singles - elif not isinstance(wfn, pyci.fullci_wfn): - raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.fullci_wfn`") - elif wfn.nocc_up != nocc_up or wfn.nocc_dn != nocc_dn: - raise ValueError(f"wfn.nocc_{{up, dn}} does not match `nocc_{{up, dn}}={nocc_up, nocc_dn}` parameter") + pyci.add_excitations(wfn, 1) + + print("\nCreating GenCI wfn") + wfn = pyci.genci_wfn(wfn) + occ_array = wfn.to_occ_array() + print("\noccsd_array: ", len(occ_array), "\n", occ_array) + elif not isinstance(wfn, pyci.genci_wfn): + raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.genci_wfn`") + elif wfn.nocc_up != nocc or wfn.nocc = nocc: + raise ValueError(f"wfn.nocc_{{up, dn}} does not match `nocc={nocc}` parameter") # Initialize base class From b7400c670fe3ab2aaa7e1e749857136e0278c6a1 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 12 Nov 2024 15:14:37 -0500 Subject: [PATCH 007/197] Add Generalized_sen-o Singles to GenCI wfn --- pyci/fanci/ap1rogen.py | 52 +++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index 7f27cf4..9af89d8 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -11,6 +11,7 @@ from ..pyci import AP1roGeneralizedSenoObjective from .fanci import FanCI +import pdb __all___ = [ @@ -55,25 +56,53 @@ def __init__( nparam = nocc * (ham.nbasis - nocc) + (2 * nocc) * (2 * (ham.nbasis - nocc)) + 1 #less params considering we added singles as well nproj = nparam if nproj is None else nproj + print("\n nparam, nproj", nparam, nproj) if wfn is None: - wfn = pyci.genci_wfn(ham.nbasis, nocc, 0) - print("\nCreated GenCI wfn instance for AP1roGSDGeneralized_sen-o.") - + wfn = pyci.doci_wfn(ham.nbasis, nocc, nocc) + print("\nCreated DOCI wfn instance for AP1roGSDGeneralized_sen-o.") wfn.add_excited_dets(1) # add pair excited determinants print("\nCreating fci wfn") wfn = pyci.fullci_wfn(wfn) - pyci.add_excitations(wfn, 1) + print("wfn.nocc, wfn.nocc_up, wfn.nocc_dn: ", wfn.nocc, wfn.nocc_up, wfn.nocc_dn) + occ_array = wfn.to_occ_array() + det_array = wfn.to_det_array() + print(f"\nFor FCI {len(occ_array)} det & corresponding occ_array:") + for i, j in zip(det_array, occ_array): + print(i, j) print("\nCreating GenCI wfn") wfn = pyci.genci_wfn(wfn) + print("wfn.nocc, wfn.nocc_up, wfn.nocc_dn: ", wfn.nocc, wfn.nocc_up, wfn.nocc_dn) occ_array = wfn.to_occ_array() - print("\noccsd_array: ", len(occ_array), "\n", occ_array) + det_array = wfn.to_det_array() + print("\nFor GenCI wfn det_array: ", len(det_array), "\n", det_array) + #for det, occ in zip(det_array, occ_array): + # print(det, bin(int(det)), occ) + + # Generate the bitstring + bitstring = ((1 << wfn.nocc //2) - 1) << ham.nbasis | (1 << wfn.nocc//2) - 1 + # Convert to binary string with leading zeros + nb = ham.nbasis + bit_str = format(bitstring, f'0{2 * nb}b') + unocc = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '0'] + occ = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '1'] + # Adding non-spin-preserving alpha -> beta singles + for i in occ: + for a in unocc: + exc_str = _excite_det(i, a, int(bit_str,2)) + print("i, a, exc_str", i, a, exc_str, format(exc_str, f'0{2*nb}b')) + wfn.add_det(np.array(exc_str, dtype=pyci.c_ulong)) + + det_array = wfn.to_det_array() + print("\nFor GenCI wfn det_array after adding Gen_sen-o S:", len(det_array), "\n", det_array) + elif not isinstance(wfn, pyci.genci_wfn): raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.genci_wfn`") - elif wfn.nocc_up != nocc or wfn.nocc = nocc: - raise ValueError(f"wfn.nocc_{{up, dn}} does not match `nocc={nocc}` parameter") + #elif wfn.nocc_up != nocc or wfn.nocc != nocc: + elif wfn.nocc != nocc: + raise ValueError(f"wfn.nocc does not match `nocc={nocc}` parameter") # Initialize base class @@ -104,7 +133,7 @@ def __init__( idx_param_cons = None param_cons = None - self._cext = PlaceholderObjective( + self._cext = AP1roGeneralizedSenoObjective( self._ci_op, self._wfn, idx_det_cons=idx_det_cons, det_cons=det_cons, idx_param_cons=idx_param_cons, param_cons=param_cons, @@ -181,3 +210,10 @@ def compute_jacobian(self, x: np.ndarray) -> np.ndarray: """ return self._cext.jacobian(self._ci_op, x) + + +def _excite_det(i: int, a: int, bitstring: int): + bitstring &= ~(1 << i) + bitstring |= (1 << a) + #pdb.set_trace() + return bitstring From c69462db5159df43215a5f2bf21cad112aa8b8fb Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 12 Nov 2024 15:23:00 -0500 Subject: [PATCH 008/197] Fix indexing error; update k increment from nword2 to nword --- pyci/src/genciwfn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/genciwfn.cpp b/pyci/src/genciwfn.cpp index b3d3f44..182210b 100644 --- a/pyci/src/genciwfn.cpp +++ b/pyci/src/genciwfn.cpp @@ -14,7 +14,7 @@ * along with PyCI. If not, see . */ #include - +#include namespace pyci { GenCIWfn::GenCIWfn(const GenCIWfn &wfn) : OneSpinWfn(wfn) { @@ -39,7 +39,7 @@ GenCIWfn::GenCIWfn(const FullCIWfn &wfn) : OneSpinWfn(wfn.nbasis * 2, wfn.nocc, occs_dn[j] += wfn.nbasis; fill_det(wfn.nocc, occs_up, &dets[k]); dict[rank_det(&dets[k])] = i; - k += wfn.nword2; + k += wfn.nword; } } From aa9a922baa6d693b086444f1271d614a1d6b5a8e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 12:16:36 -0500 Subject: [PATCH 009/197] Add NonSingletCI class derived from GenCIWfn class --- pyci/__init__.py | 1 + pyci/src/binding.cpp | 126 ++++++++++++++++++++++++++++++++++++++ pyci/src/nonsingletci.cpp | 58 ++++++++++++++++++ 3 files changed, 185 insertions(+) create mode 100644 pyci/src/nonsingletci.cpp diff --git a/pyci/__init__.py b/pyci/__init__.py index 36e9675..57e5ad0 100644 --- a/pyci/__init__.py +++ b/pyci/__init__.py @@ -45,6 +45,7 @@ "doci_wfn", "fullci_wfn", "genci_wfn", + "nonsingletci_wfn", "sparse_op", "get_num_threads", "set_num_threads", diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index b3b3d13..cab287f 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -877,6 +877,113 @@ genci_wfn.def(py::init>() genci_wfn.def(py::init>(), py::arg("nbasis"), py::arg("nocc_up"), py::arg("nocc_dn"), py::arg("array")); +/* +Section: NonSingletCI wave function class +*/ + +py::class_ nonsingletci_wfn(m, "nonsingletci_wfn"); + +nonsingletci_wfn.doc() = R"""( +Non-singlet CI wave function base class. +)"""; + +nonsingletci_wfn.def(py::init(), R"""( +Initialize a Non-singlet CI wave function. + +Parameters +---------- +wfn : (pyci.doci_wfn | pyci.fullci_wfn | pyci.genci_wfn | pyci.nonsingletci_wfn) + Wave function from which to copy data. + +or + +Parameters +---------- +filename : TextIO + Filename of binary file from which to load wave function. + +or + +Parameters +---------- +nbasis : int + Number of spatial orbital functions. +nocc_up : int + Number of occupied spin-up orbitals. +nocc_dn : int + Number of occupied spin-down orbitals. + +)""", + py::arg("wfn")); + +nonsingletci_wfn.def(py::init(), py::arg("wfn")); + +nonsingletci_wfn.def(py::init(), py::arg("wfn")); + +nonsingletci_wfn.def(py::init(), py::arg("filename")); + +nonsingletci_wfn.def(py::init(), py::arg("nbasis"), py::arg("nocc_up"), + py::arg("nocc_dn")); + +nonsinglet_wfn.def(py::init>(), py::arg("nbasis"), + py::arg("nocc_up"), py::arg("nocc_dn"), py::arg("array")); + +nonsingletci_wfn.def(py::init>(), py::arg("nbasis"), + py::arg("nocc_up"), py::arg("nocc_dn"), py::arg("array")); + +/* +Section: Sparse CI matrix operator class +*/ + +py::class_ sparse_op(m, "sparse_op"); + +sparse_op.doc() = R"""( +Sparse matrix operator class. +)"""; + +sparse_op.def_readonly("ecore", &SparseOp::ecore, R"""( +Constant (or "zero-particle") integral. + +Returns +------- +ecore : float + Constant (or "zero-particle") integral. + +)"""); + +sparse_op.def_readonly("symmetric", &SparseOp::symmetric, R"""( +Whether the sparse matrix operator is symmetric/Hermitian. + +Returns +------- +symmetric : bool + Whether the sparse matrix operator is symmetric/Hermitian. + +)"""); + +sparse_op.def_readonly("size", &SparseOp::size, R"""( +Number of non-zero matrix elements. + +Returns +------- +size : int + Number of non-zero matrix elements. + +)"""); + +sparse_op.def_readonly("shape", &SparseOp::shape, R"""( +Shape of the matrix. + +Returns +------- +nrow : int + Number of rows. +ncol : int + Number of columns. + +)"""); + +sparse_op.def_property_readonly("dtype", &SparseOp::dtype, R"""( /* Section: Sparse CI matrix operator class */ @@ -1400,6 +1507,25 @@ genci_objective.def("objective", &Objective::py_objective, DOCSTRING_O genci_objective.def("jacobian", &Objective::py_jacobian, DOCSTRING_JACOBIAN, py::arg("op"), py::arg("x")); + +py::class_> nonsingletci_objective(m, "NonSingletCIObjective"); + +genci_objective.doc() = R"""( +NonSingletCI-FanCI objective class. +)"""; + +nonsingletci_objective.def("overlap", &Objective::py_overlap, DOCSTRING_OVERLAP, + py::arg("x")); + +nonsingletci_objective.def("d_overlap", &Objective::py_d_overlap, DOCSTRING_D_OVERLAP, + py::arg("x")); + +nonsingletci_objective.def("objective", &Objective::py_objective, DOCSTRING_OBJECTIVE, + py::arg("op"), py::arg("x")); + +nonsingletci_objective.def("jacobian", &Objective::py_jacobian, DOCSTRING_JACOBIAN, + py::arg("op"), py::arg("x")); + py::class_> ap1rog_objective(m, "AP1roGObjective"); ap1rog_objective.doc() = R"""( diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp new file mode 100644 index 0000000..5614c46 --- /dev/null +++ b/pyci/src/nonsingletci.cpp @@ -0,0 +1,58 @@ +/* This file is part of PyCI. + * + * PyCI is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * PyCI is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyCI. If not, see . */ + +#include + +namespace pyci { + +NonSingletCI::NonSingletCI(const NonSingletCI &wfn) : GenCIWfn(wfn) { +} + +NonSingletCI::NonSingletCI(NonSingletCI &&wfn) noexcept : GenCIWfn(wfn) { +} + +NonSingletCI::NonSingletCI(const DOCIWfn &wfn) : GenCIWfn(wfn){ +} + +NonSingletCI::NonSingletCI(const FullCIWfn &wfn) : GenCIWfn(wfn){ +} + +NonSingletCI::NonSingletCI(const std::string &filename) : GenCIWfn(filename) { +} + +NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd) : GenCIWfn(nb, nu, nd) { +} + +NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const long n, const ulong *ptr) + : GenCIWfn(nb, nu, nd, n, ptr) { +} + +NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const long n, const long *ptr) + : GenCIWfn(nb, nu, nd, n, ptr) { +} + +NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Array array) + : NonSingletCI(nb, nu, nd, array.request().shape[0], +} + +NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Array array) + : NonSingletCI(nb, nu, nd, array.request().shape[0], +} + + +} //namespace pyci + + + From 4137d19bbe4dc5c4369836b6a6478901380b2bf0 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 12:36:07 -0500 Subject: [PATCH 010/197] Add NonSingletCI class derived from GenCIWfn class --- pyci/include/pyci.h | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 1cc5500..166f86e 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -173,6 +173,7 @@ struct TwoSpinWfn; struct DOCIWfn; struct FullCIWfn; struct GenCIWfn; +struct NonSingletCI; struct SparseOp; /* Number of threads global variable. */ @@ -612,6 +613,47 @@ struct GenCIWfn final : public OneSpinWfn { GenCIWfn(const long, const long, const long, const Array); }; +struct NonSingletCI final : public OneSpinWfn { +public: + using Wfn::maxrank_dn; + using Wfn::maxrank_up; + using Wfn::nbasis; + using Wfn::ndet; + using Wfn::nocc; + using Wfn::nocc_dn; + using Wfn::nocc_up; + using Wfn::nvir; + using Wfn::nvir_dn; + using Wfn::nvir_up; + using Wfn::nword; + using Wfn::nword2; + +protected: + using Wfn::dets; + using Wfn::dict; + +public: + NonSingletCI(const NonSingletCI &); + + NonSingletCI(NonSingletCI &&) noexcept; + + NonSingletCI(const DOCIWfn &); + + NonSingletCI(const FullCIWfn &); + + NonSingletCI(const std::string &); + + NonSingletCI(const long, const long, const long); + + NonSingletCI(const long, const long, const long, const long, const ulong *); + + NonSingletCI(const long, const long, const long, const long, const long *); + + NonSingletCI(const long, const long, const long, const Array); + + NonSingletCI(const long, const long, const long, const Array); +}; + /* Sparse matrix operator class. */ struct SparseOp final { @@ -638,6 +680,8 @@ struct SparseOp final { SparseOp(const SQuantOp &, const GenCIWfn &, const long, const long, const bool); + SparseOp(const SQuantOp &, const NonSingletCI &, const long, const long, const bool); + pybind11::object dtype(void) const; const double *data_ptr(const long) const; @@ -680,6 +724,8 @@ struct SparseOp final { void add_row(const SQuantOp &, const FullCIWfn &, const long, ulong *, long *, long *); void add_row(const SQuantOp &, const GenCIWfn &, const long, ulong *, long *, long *); + + void add_row(const SQuantOp &, const NonSingletCI &, const long, ulong *, long *, long *); }; /* FanCI objective classes. */ From 42e7b9ea2730cdda8ed19bddc732cec335f96c32 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 12:39:33 -0500 Subject: [PATCH 011/197] Add NonSingletCI class derived from GenCIWfn class --- pyci/src/binding.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index cab287f..c60b4bb 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -925,7 +925,7 @@ nonsingletci_wfn.def(py::init(), py::arg("filename")); nonsingletci_wfn.def(py::init(), py::arg("nbasis"), py::arg("nocc_up"), py::arg("nocc_dn")); -nonsinglet_wfn.def(py::init>(), py::arg("nbasis"), +nonsingletci_wfn.def(py::init>(), py::arg("nbasis"), py::arg("nocc_up"), py::arg("nocc_dn"), py::arg("array")); nonsingletci_wfn.def(py::init>(), py::arg("nbasis"), @@ -992,7 +992,7 @@ py::class_ sparse_op(m, "sparse_op"); sparse_op.doc() = R"""( Sparse matrix operator class. -)"""; +)"""); sparse_op.def_readonly("ecore", &SparseOp::ecore, R"""( Constant (or "zero-particle") integral. From 809a5104fe6298303bb87e9b914f302435d58f76 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 12:49:57 -0500 Subject: [PATCH 012/197] Add NonSingletCI class derived from GenCIWfn class --- pyci/src/binding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index c60b4bb..23c0983 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1510,7 +1510,7 @@ genci_objective.def("jacobian", &Objective::py_jacobian, DOCSTRING_JAC py::class_> nonsingletci_objective(m, "NonSingletCIObjective"); -genci_objective.doc() = R"""( +nonsingletci_objective.doc() = R"""( NonSingletCI-FanCI objective class. )"""; From 90c04a25996276293de809d1f0fef61d8c5f1792 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 12:56:56 -0500 Subject: [PATCH 013/197] Add NonSingletCI class derived from GenCIWfn class --- pyci/include/pyci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 166f86e..413fd5f 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -613,7 +613,7 @@ struct GenCIWfn final : public OneSpinWfn { GenCIWfn(const long, const long, const long, const Array); }; -struct NonSingletCI final : public OneSpinWfn { +struct NonSingletCI final : public GenCIWfn { public: using Wfn::maxrank_dn; using Wfn::maxrank_up; From 33582b020449ce6eee3896dd9b0eac52d792610f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 13:02:57 -0500 Subject: [PATCH 014/197] Remove final keyword from GenCIWfn to allow inheritance for NonSingletCI --- pyci/include/pyci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 413fd5f..a9d9557 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -572,7 +572,7 @@ struct FullCIWfn final : public TwoSpinWfn { FullCIWfn(const long, const long, const long, const Array); }; -struct GenCIWfn final : public OneSpinWfn { +struct GenCIWfn : public OneSpinWfn { public: using Wfn::maxrank_dn; using Wfn::maxrank_up; From cd16c02ba36dc9d675248f10f4c3dee6d1490b6e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 13:58:54 -0500 Subject: [PATCH 015/197] Add NonSingletCI class derived from GenCIWfn class --- pyci/src/nonsingletci.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 5614c46..5f2785d 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -45,10 +45,12 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const lo NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Array array) : NonSingletCI(nb, nu, nd, array.request().shape[0], + reinterpret_cast(array.request().ptr)) { } NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Array array) : NonSingletCI(nb, nu, nd, array.request().shape[0], + reinterpret_cast(array.request().ptr)) { } From 9a2e708087fb57fcbf05e1eb728233af71ae9d1e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Fri, 15 Nov 2024 10:20:42 -0500 Subject: [PATCH 016/197] Add fill_hartreefock_det --- pyci/src/nonsingletci.cpp | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 5f2785d..b692d5b 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -53,6 +53,54 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar reinterpret_cast(array.request().ptr)) { } + +void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ + long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvir_up, e); + AlignedVector det(nword); + + AlignedVector occs(nocc); + AlignedVector occs_up(nocc_up); + AlignedVector occs_dn(nocc_dn); + AlignedVector occs_pairs(nocc_up); + + AlignedVector virs(nvir); + AlignedVector virs_up(nvir_up); + AlignedVector virs_dn(nvir_dn); + AlignedVector virs_pairs(nocc_up); + + AlignedVector occinds(e + 1); + AlignedVector virinds(e + 1); + +} + + +void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { + /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ + long i = 0; + long nb = nb/2; + long nocc_beta = std::min(nocc, nb); + long nocc_alpha = std::min(0L, nocc - nb); + + // First, handle beta spins + while (nocc_beta >= Size()){ + det[i++] = Max(); + nocc_beta -= Size(); + } + + if (nocc_beta) { + det[i] = (1UL << nocc_beta) -1; + i++; + } + + // Fill alpha spins (second half) + while (nocc_alpha >= Size()){ + det[i++] = Max(); + nocc_alpha -= Size(); + } + + if (nocc_alpha) { + det[i] = (1UL << nocc) - 1; + } } //namespace pyci From 519b071dcc1f235dbd5076a30445e9880525bfe5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 18 Nov 2024 15:50:39 -0500 Subject: [PATCH 017/197] Add function to excited dets --- pyci/src/nonsingletci.cpp | 123 +++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index b692d5b..bb55ea6 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -53,24 +53,139 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar reinterpret_cast(array.request().ptr)) { } +AlignedVector> NonSingletCI::orb_pairs() const { + AlignedVector> pairs; + pairs.reserve(nbasis); + for (long i = 0; i < nbasis; ++i) { + pairs.emblace_back(i, i + nbasis); + } + return pairs; +} + void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ - long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvir_up, e); + //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvir_up, e); AlignedVector det(nword); AlignedVector occs(nocc); AlignedVector occs_up(nocc_up); AlignedVector occs_dn(nocc_dn); - AlignedVector occs_pairs(nocc_up); + AlignedVector> occs_pairs; AlignedVector virs(nvir); AlignedVector virs_up(nvir_up); AlignedVector virs_dn(nvir_dn); - AlignedVector virs_pairs(nocc_up); + AlignedVector> virs_pairs; AlignedVector occinds(e + 1); AlignedVector virinds(e + 1); + fill_occs(nword, rdet, &occs[0]); + fill_virs(nword, nbasis, rdet, &virs[0]); + + + + // Generate list of up & dn indices for ocs & virs + for (int i : occs) { + if (i < nbasis) occ_up.push_back(i); + else occ_dn.push_back(i); + } + for (int a : virs) { + if (a < nbasis) virs_up.push_back(i); + else virs_dn.push_back(i); + } + // Create an unordered set for fast lookup of occupied down-orbitals + std::unordered_set occ_dn_set(occ_dn.begin(), occ_dn.end()); + // Generate occ_pairs + for (int i : occ_up) { + if (occ_dn_set.find(i + nbasis) != occ_dn_set.end()) { + occ_pairs.push_back({i, i + nbasis}); + } + } + // Create an unordered set for fast looup of virtual orbitals + std::unordered_set virs_set(virs.begin(), virs.end()); + // form virtual pairs + for (int a : virs) { + if (virs_set.find(a + nbasis) != virs_set.end()) { + virs_pairs.push_back({a, a + nbasis}); + } + } + + // Handle excitation order 1 + if (n == 1) { + for (long occ : occ_up) { + for (long vir : vir_up) { + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + excite_det(occ, vir, &det[0]) + add_det(&det[0]) + } + } + for (long occ : occ_dn) { + for (long vir : vir_up) { + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + excite_det(occ, vir, &det[0]) + add_det(&det[0]) + } + } + return ; + } + + + + //// Handle excitation order 2 + //if (e == 2){ + // for (const auto& occ_pair : occ_pairs){ + // for (const auto& vir_pair : vir_pairs){ + // long o_up = occ_pair.first; + // long o_dn = occ_pair.second; + // long v_up = vir_pair.first; + // long v_dn = vir_pair.second; + // + // std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + // excite_det(o_up, v_up, &det[0]) + // excite_det(o_dn, v_dn, &det[0]) + // add_det(&det[0]) + // + // } + // } + //} + + // Handle excitation orders >= 2 + // Loop over possible values of d (number of pair excitations) + for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ + // Number of single excitations + long num_singles = e - 2 * d; + + // Apply d pair excitations + if (d > 0) { + for (long i = 0; i < d; ++i) { + const auto& occ_pair = occ_pairs[i]; + const auto& vir_pair = vir_pairs[i]; + + long o_up = occ_pair.first; + long o_dn = occ_pair.second; + long v_up = vir_pair.first; + long v_dn = vir_pair.second; + + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + + excite_det(o_up, v_up, &det[0]) + excite_det(o_dn, v_dn, &det[0]) + add_det(&det[0]) + } + } + // Apply num_singles single excitations + if (num_singles > 0) { + for (long i = 0; i < num_singles; ++i){ + long occ = (i % 2 == 0) ? occ_up[i % occ_up.size()] : occ_dn[i % occ_dn.size()]; + for (long vir : virs) { + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + excite_det(occ, vir, det); + } + } + } + } + } @@ -102,6 +217,8 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { det[i] = (1UL << nocc) - 1; } + +void NonSingletCI::p } //namespace pyci From 720337f3e7e6c65579f739825386fc5e104b2d88 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 18 Nov 2024 15:53:31 -0500 Subject: [PATCH 018/197] Include fill hartreefock det function --- pyci/include/pyci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index a9d9557..e9bac8d 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -652,6 +652,8 @@ struct NonSingletCI final : public GenCIWfn { NonSingletCI(const long, const long, const long, const Array); NonSingletCI(const long, const long, const long, const Array); + + void fill_hartreefock_det(long, long, ulong *); }; /* Sparse matrix operator class. */ From 3624eb691ad2821e63d2df3aa32ab6c9f09e4248 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 18 Nov 2024 20:42:38 -0500 Subject: [PATCH 019/197] Add print statements for debug --- pyci/excitation_ci.py | 2 ++ pyci/fanci/fanci.py | 3 +++ pyci/src/fullciwfn.cpp | 7 ++++++ pyci/src/onespinwfn.cpp | 51 +++++++++++++++++++++++++++++++++++++++-- pyci/src/twospinwfn.cpp | 12 +++++++++- 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/pyci/excitation_ci.py b/pyci/excitation_ci.py index 1554bf1..ef50097 100644 --- a/pyci/excitation_ci.py +++ b/pyci/excitation_ci.py @@ -35,5 +35,7 @@ def add_excitations(wfn, *excitations, ref=None): Default is the Hartree-Fock determinant. """ + print("Inside excitation_ci/add_excitations") for e in excitations: + print(f"Adding {e}-excited determinants...") wfn.add_excited_dets(e, ref=ref) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index 4d81ac7..d9c1ed5 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -682,8 +682,10 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: # Fill wfn with P space determinants in excitation order until len(wfn) >= nproj; # only add Hartree-Fock det. (zero order excitation) if wfn is empty # for nexc in range(bool(len(wfn)), e_max + 1): + print(f"e_max: {e_max}, len(wfn) before filling: {len(wfn)}") for nexc in range(e_max + 1): if len(wfn) >= nproj: + print("Breaking filling as len(wfn) >= nproj") break pyci.add_excitations(wfn, nexc) @@ -708,6 +710,7 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: wfn = wfn.__class__(wfn.nbasis, wfn.nocc_up, wfn.nocc_dn, wfn.to_det_array(nproj)) # Fill wfn with S space determinants + print("\nAdding S space determinants") for det in wfn.to_det_array(nproj): pyci.add_excitations(wfn, *connections, ref=det) diff --git a/pyci/src/fullciwfn.cpp b/pyci/src/fullciwfn.cpp index b532611..2162423 100644 --- a/pyci/src/fullciwfn.cpp +++ b/pyci/src/fullciwfn.cpp @@ -14,6 +14,7 @@ * along with PyCI. If not, see . */ #include +#include namespace pyci { @@ -24,14 +25,20 @@ FullCIWfn::FullCIWfn(FullCIWfn &&wfn) noexcept : TwoSpinWfn(wfn) { } FullCIWfn::FullCIWfn(const DOCIWfn &wfn) : TwoSpinWfn(wfn.nbasis, wfn.nocc_up, wfn.nocc_dn) { + std::cout << "Initializing FullCIWfn from DOCIWfn" << std::endl; ndet = wfn.ndet; + std::cout << "Number of determinants: " << ndet << std::endl; dets.resize(wfn.ndet * nword2); + std::cout << "Resized dets array to: " << (wfn.ndet * nword2) << std::endl; dict.clear(); + std::cout << "Cleared dictionary" << std::endl; for (long i = 0; i < wfn.ndet; ++i) { std::memcpy(&dets[i * wfn.nword2], wfn.det_ptr(i), sizeof(ulong) * wfn.nword); std::memcpy(&dets[i * wfn.nword2 + wfn.nword], wfn.det_ptr(i), sizeof(ulong) * wfn.nword); dict[rank_det(&dets[i * wfn.nword2])] = i; + std::cout << "Processed determinant " << i << std::endl; } + std::cout << "Finished initializing FullCIWfn from DOCIWfn" << std::endl; } FullCIWfn::FullCIWfn(const std::string &filename) : TwoSpinWfn(filename) { diff --git a/pyci/src/onespinwfn.cpp b/pyci/src/onespinwfn.cpp index 4cba643..c671640 100644 --- a/pyci/src/onespinwfn.cpp +++ b/pyci/src/onespinwfn.cpp @@ -14,7 +14,8 @@ * along with PyCI. If not, see . */ #include - +#include +#include namespace pyci { OneSpinWfn::OneSpinWfn(const OneSpinWfn &wfn) : Wfn(wfn) { @@ -218,6 +219,12 @@ void OneSpinWfn::add_all_dets(long nthread) { void OneSpinWfn::add_excited_dets(const ulong *rdet, const long e) { long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvir_up, e); + std::cout << "Inside onespinwfn/add_excited_dets" << std::endl; + std::cout << "no: " << no << ", nv: " << nv << ", nword: " << nword << std::endl; + std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; + std::cout << "e: " << e << std::endl; + std::cout << "rdet: " << *rdet << std::endl; + AlignedVector det(nword); AlignedVector occs(nocc_up); AlignedVector virs(nvir_up); @@ -225,6 +232,19 @@ void OneSpinWfn::add_excited_dets(const ulong *rdet, const long e) { AlignedVector virinds(e + 1); fill_occs(nword, rdet, &occs[0]); fill_virs(nword, nbasis, rdet, &virs[0]); + + std::cout << "occs: "; + for (const auto& elem : occs) { + std::cout << elem << " "; + } + std::cout << std::endl; + + std::cout << "virs: "; + for (const auto& elem : virs) { + std::cout << elem << " "; + } + std::cout << std::endl; + for (k = 0; k < e; ++k) virinds[k] = k; virinds[e] = nvir_up + 1; @@ -233,9 +253,36 @@ void OneSpinWfn::add_excited_dets(const ulong *rdet, const long e) { occinds[k] = k; occinds[e] = nocc_up + 1; for (j = 0; j < no; ++j) { + std::cout << "virinds: "; + for (const auto& elem : virinds) { + std::cout << elem << " "; + } + std::cout << std::endl; + + std::cout << "occinds: "; + for (const auto& elem : occinds) { + std::cout << elem << " "; + } + std::cout << std::endl; + + // Print determinant before excite_det loop + std::cout << "Determinant before excite_det loop: "; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << std::endl; + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - for (k = 0; k < e; ++k) + for (k = 0; k < e; ++k) { excite_det(occs[occinds[k]], virs[virinds[k]], &det[0]); + } + + // Print determinant after excite_det loop + std::cout << "Determinant after excite_det loop: "; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << std::endl; add_det(&det[0]); next_colex(&occinds[0]); } diff --git a/pyci/src/twospinwfn.cpp b/pyci/src/twospinwfn.cpp index def18ef..7f269d2 100644 --- a/pyci/src/twospinwfn.cpp +++ b/pyci/src/twospinwfn.cpp @@ -14,6 +14,7 @@ * along with PyCI. If not, see . */ #include +#include namespace pyci { @@ -249,8 +250,12 @@ void TwoSpinWfn::add_excited_dets(const ulong *rdet, const long e_up, const long add_det(rdet); return; } + std::cout << "Inside twospin/add_excited_dets " << std::endl; + std::cout << "Calling OneSpinWfn to add_excited_dets in wfn_up " << std::endl; OneSpinWfn wfn_up(nbasis, nocc_up, nocc_up); wfn_up.add_excited_dets(&rdet[0], e_up); + + std::cout << "Calling OneSpinWfn to add_excited_dets in wfn_up " << std::endl; OneSpinWfn wfn_dn(nbasis, nocc_dn, nocc_dn); wfn_dn.add_excited_dets(&rdet[nword], e_dn); AlignedVector det(nword2); @@ -325,6 +330,8 @@ long TwoSpinWfn::py_add_occs(const Array occs) { long TwoSpinWfn::py_add_excited_dets(const long exc, const pybind11::object ref) { AlignedVector v_ref; ulong *ptr; + std::cout << "Inside twospin/py_add_excited_dets " << std::endl; + std::cout << "exc: " << exc << std::endl; if (ref.is(pybind11::none())) { v_ref.resize(nword2); ptr = &v_ref[0]; @@ -337,8 +344,11 @@ long TwoSpinWfn::py_add_excited_dets(const long exc, const pybind11::object ref) long maxdn = (nocc_dn < nvir_dn) ? nocc_dn : nvir_dn; long a = (exc < maxup) ? exc : maxup; long b = exc - a; - while ((a >= 0) && (b <= maxdn)) + while ((a >= 0) && (b <= maxdn)){ + std::cout << "Callling twospin/add_excited_dets with " << std::endl; + std::cout << "a: " << a << " b: " << b << std::endl; add_excited_dets(ptr, a--, b++); + } return ndet - ndet_old; } From cc7efdd099c624798b8b3d71c09a47a2a3855cc1 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 20 Nov 2024 15:59:52 -0500 Subject: [PATCH 020/197] Remove unnecessary function forming orb pairs --- pyci/src/nonsingletci.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index bb55ea6..825c888 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -53,14 +53,6 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar reinterpret_cast(array.request().ptr)) { } -AlignedVector> NonSingletCI::orb_pairs() const { - AlignedVector> pairs; - pairs.reserve(nbasis); - for (long i = 0; i < nbasis; ++i) { - pairs.emblace_back(i, i + nbasis); - } - return pairs; -} void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ From 211d945fb24b7bd75d265f1e800e9a31c37838d4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 20 Nov 2024 16:19:42 -0500 Subject: [PATCH 021/197] Add function add_excited_dets & its Py binding --- pyci/include/pyci.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index e9bac8d..b226bdd 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -654,6 +654,10 @@ struct NonSingletCI final : public GenCIWfn { NonSingletCI(const long, const long, const long, const Array); void fill_hartreefock_det(long, long, ulong *); + + void add_excited_dets(const ulong *, const long); + + long py_add_excited_dets(const long, const pybind11::object); }; /* Sparse matrix operator class. */ From 50e78d07b379257c1704afd03c8bc0b1ac4a5c95 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 20 Nov 2024 16:31:49 -0500 Subject: [PATCH 022/197] Add py_add_excited_dets --- pyci/src/nonsingletci.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 825c888..a435626 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -210,7 +210,19 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { } -void NonSingletCI::p +void NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object ref) { + AlignedVector v_ref; + ulong *ptr; + if (ref.is(pybind11::none())) { + v_ref.resize(nword) + ptr = &v_ref[0] + fill_hartreefock_det(nbasis,nocc, ptr); + } else + ptr = reinterpret_cast(ref.cast>().request().ptr); + long ndet_old = ndet; + add_excited_dets(ptr, exc); + return ndet - ndet_old; +} } //namespace pyci From 4f893180105ce907500fe2577f4df96d7ed3db81 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 14:27:15 -0500 Subject: [PATCH 023/197] Remove unnecessary file --- pyci/src/placeholder.cpp | 75 ---------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 pyci/src/placeholder.cpp diff --git a/pyci/src/placeholder.cpp b/pyci/src/placeholder.cpp deleted file mode 100644 index 89fc8c1..0000000 --- a/pyci/src/placeholder.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* This file is part of PyCI. - * - * PyCI is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * PyCI is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with PyCI. If not, see . */ - -#include - -namespace pyci { - -// See apig.cpp for reference - -PlaceholderObjective::PlaceholderObjective(const SparseOp &op_, const FullCIWfn &wfn_, - const std::size_t n_detcons_, - const long *idx_detcons_, - const double *val_detcons_, - const std::size_t n_paramcons_, - const long *idx_paramcons_, - const double *val_paramcons_) -: Objective::Objective(op_, wfn_, n_detcons_, idx_detcons_, val_detcons_, n_paramcons_, idx_paramcons_, val_paramcons_) -{ - init_overlap(wfn_); -} - -PlaceholderObjective::PlaceholderObjective(const SparseOp &op_, const FullCIWfn &wfn_, - const pybind11::object idx_detcons_, - const pybind11::object val_detcons_, - const pybind11::object idx_paramcons_, - const pybind11::object val_paramcons_) -: Objective::Objective(op_, wfn_, idx_detcons_, val_detcons_, idx_paramcons_, val_paramcons_) -{ - init_overlap(wfn_); -} - -PlaceholderObjective::PlaceholderObjective(const PlaceholderObjective &obj) -: Objective::Objective(obj) -{ - return; -} - -PlaceholderObjective::PlaceholderObjective(PlaceholderObjective &&obj) noexcept -: Objective::Objective(obj){ - return; -} - -void PlaceholderObjective::init_overlap(const FullCIWfn &wfn_) -{ - // Initialize your class-specific variables here - return; -} - -void PlaceholderObjective::overlap(const size_t ndet, const double *x, double *y) -{ - // x == parameters p_j - // y == overlap vector σ_i - return; -} - -void PlaceholderObjective::d_overlap(const size_t ndet, const double *x, double *y) -{ - // x == parameters p_j - // y == unwrapped overlap objective ∂σ_i/∂p_j - return; -} - -} // namespace pyci From 15221d934a404fc13d3dd5bf454d4226e6c03ed7 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 14:31:43 -0500 Subject: [PATCH 024/197] Add print statements in ap1rog.cpp 'init_overlap' & 'overlap' function --- pyci/src/ap1rog.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pyci/src/ap1rog.cpp b/pyci/src/ap1rog.cpp index 93f1138..99b4926 100644 --- a/pyci/src/ap1rog.cpp +++ b/pyci/src/ap1rog.cpp @@ -60,6 +60,9 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) nrow = wfn_.nocc_up; ncol = wfn_.nbasis - wfn_.nocc_up; + std::cout << "nconn, nparam: " << nconn << "," << nparam << ", nrow: " << nrow << ", ncol: " << ncol << std::endl; + + ovlp.resize(nconn); d_ovlp.resize(nconn * nparam); @@ -74,18 +77,31 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) const ulong *det = wfn_.det_ptr(idet); ulong word, hword, pword; std::size_t h, p, nexc = 0; + + std::cout << "idet: " << idet << std::endl; + for (std::size_t iword = 0; iword != nword; ++iword) { word = rdet[iword] ^ det[iword]; hword = word & rdet[iword]; pword = word & det[iword]; + std::cout << "word: " << word << ", hword: " << hword << ", pword: " << pword << std::endl; while (hword) { h = Ctz(hword); p = Ctz(pword); hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; + + std::cout << "h: " << h << ", p: " << p << std::endl; + std::cout << "hole_list: " << hole_list[idet * wfn_.nocc_up + nexc] << ", part_list: " << part_list[idet * wfn_.nocc_up + nexc] << std::endl; + hword &= ~(1UL << h); pword &= ~(1UL << p); ++nexc; + std::cout << "hword" << hword << std::endl; + std::cout << "pword" << pword << std::endl; + std::cout << "nexc: " << nexc << std::endl; + std::cout << "nexc_list: " << nexc_list[idet] << std::endl; + } } nexc_list[idet] = nexc; @@ -113,6 +129,8 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Iterate over c = pow(2, m) submatrices (equal to (1 << m)) submatrices. */ c = 1UL << m; + std::cout << "c: " << c << std::endl; + std::cout << "m: " << m << std::endl; /* Loop over columns of submatrix; compute product of row sums. */ for (k = 0; k < c; ++k) { @@ -125,7 +143,13 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Add element to row sum if the row index is in the characteristic * * vector of the submatrix, which is the binary vector given by k. */ + std::cout << "j, k: " << j << "," << k << std::endl; + std::cout << "1UL << j: " << 1UL << j << std::endl; + std::size_t xpq = k & (1UL << j); + std::cout << "k &(1UL << j)" << xpq << std::endl; if (k & (1UL << j)) { + + std::cout << "ncol * hlist[i] + plist[j]: " << ncol * hlist[i] + plist[j] << std::endl; rowsum += x[ncol * hlist[i] + plist[j]]; } } @@ -135,6 +159,8 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { } /* Add term multiplied by the parity of the characteristic vector. */ + std::cout << "rowsumprod: " << rowsumprod << std::endl; + std::cout << "(__builtin_popcountll(k) & 1) << 1: " << (__builtin_popcountll(k) & 1) << std::endl; out += rowsumprod * (1 - ((__builtin_popcountll(k) & 1) << 1)); } From 7bbc50705ffdabeebdd84b11e9db05fd066f4e37 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 14:32:33 -0500 Subject: [PATCH 025/197] Fix typos --- pyci/src/nonsingletci.cpp | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index a435626..46094e8 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -55,19 +55,19 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar -void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ - //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvir_up, e); +void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ + //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); AlignedVector det(nword); AlignedVector occs(nocc); AlignedVector occs_up(nocc_up); AlignedVector occs_dn(nocc_dn); - AlignedVector> occs_pairs; + AlignedVector> occ_pairs; AlignedVector virs(nvir); AlignedVector virs_up(nvir_up); AlignedVector virs_dn(nvir_dn); - AlignedVector> virs_pairs; + AlignedVector> vir_pairs; AlignedVector occinds(e + 1); AlignedVector virinds(e + 1); @@ -78,17 +78,17 @@ void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ // Generate list of up & dn indices for ocs & virs for (int i : occs) { - if (i < nbasis) occ_up.push_back(i); - else occ_dn.push_back(i); + if (i < nbasis) occs_up.push_back(i); + else occs_dn.push_back(i); } for (int a : virs) { - if (a < nbasis) virs_up.push_back(i); - else virs_dn.push_back(i); + if (a < nbasis) virs_up.push_back(a); + else virs_dn.push_back(a); } // Create an unordered set for fast lookup of occupied down-orbitals - std::unordered_set occ_dn_set(occ_dn.begin(), occ_dn.end()); + std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); // Generate occ_pairs - for (int i : occ_up) { + for (int i : occs_up) { if (occ_dn_set.find(i + nbasis) != occ_dn_set.end()) { occ_pairs.push_back({i, i + nbasis}); } @@ -99,24 +99,24 @@ void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ // form virtual pairs for (int a : virs) { if (virs_set.find(a + nbasis) != virs_set.end()) { - virs_pairs.push_back({a, a + nbasis}); + vir_pairs.push_back({a, a + nbasis}); } } // Handle excitation order 1 - if (n == 1) { - for (long occ : occ_up) { - for (long vir : vir_up) { + if (e == 1) { + for (long occ : occs_up) { + for (long vir : virs_up) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(occ, vir, &det[0]) - add_det(&det[0]) + excite_det(occ, vir, &det[0]); + add_det(&det[0]); } } - for (long occ : occ_dn) { - for (long vir : vir_up) { + for (long occ : occs_dn) { + for (long vir : virs_up) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(occ, vir, &det[0]) - add_det(&det[0]) + excite_det(occ, vir, &det[0]); + add_det(&det[0]); } } return ; @@ -161,18 +161,18 @@ void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(o_up, v_up, &det[0]) - excite_det(o_dn, v_dn, &det[0]) - add_det(&det[0]) + excite_det(o_up, v_up, &det[0]); + excite_det(o_dn, v_dn, &det[0]); + add_det(&det[0]); } } // Apply num_singles single excitations if (num_singles > 0) { for (long i = 0; i < num_singles; ++i){ - long occ = (i % 2 == 0) ? occ_up[i % occ_up.size()] : occ_dn[i % occ_dn.size()]; + long occ = (i % 2 == 0) ? occs_up[i % occs_up.size()] : occs_dn[i % occs_dn.size()]; for (long vir : virs) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(occ, vir, det); + excite_det(occ, vir, &det[0]); } } } @@ -184,7 +184,7 @@ void NonSingletCI:add_excited_dets(const ulong *rdet, const long e){ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ long i = 0; - long nb = nb/2; + long nb = nb2/2; long nocc_beta = std::min(nocc, nb); long nocc_alpha = std::min(0L, nocc - nb); @@ -204,18 +204,18 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { det[i++] = Max(); nocc_alpha -= Size(); } - if (nocc_alpha) { det[i] = (1UL << nocc) - 1; } +} -void NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object ref) { +long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object ref) { AlignedVector v_ref; ulong *ptr; if (ref.is(pybind11::none())) { - v_ref.resize(nword) - ptr = &v_ref[0] + v_ref.resize(nword); + ptr = &v_ref[0]; fill_hartreefock_det(nbasis,nocc, ptr); } else ptr = reinterpret_cast(ref.cast>().request().ptr); From 4165d9fb243e6a1556dac3b26cae967a9224e1ee Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 14:52:49 -0500 Subject: [PATCH 026/197] Correc the base class mention for AP1roGeneralizedSeno Objective --- pyci/include/pyci.h | 18 +++++++++--------- pyci/src/binding.cpp | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index b226bdd..c3f28c4 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -852,13 +852,13 @@ class APIGObjective : public Objective { }; // Specialize base template class for AP1roGSDGeneralized_sen-o against GenCI Wfn -class AP1roGeneralizedSenoObjective : public Objective { +class AP1roGeneralizedSenoObjective : public Objective { public: - using Objective::nproj; // # of determinants in P space - using Objective::nconn; // # of determinants in S space - using Objective::nparam; // # of FanCI parameters - using Objective::ovlp; // Overlap vector - using Objective::d_ovlp; // Overlap gradient matrix + using Objective::nproj; // # of determinants in P space + using Objective::nconn; // # of determinants in S space + using Objective::nparam; // # of FanCI parameters + using Objective::ovlp; // Overlap vector + using Objective::d_ovlp; // Overlap gradient matrix // Declare variables you want to store to faciliate the computation // of {d_,}overlap here: @@ -875,12 +875,12 @@ class AP1roGeneralizedSenoObjective : public Objective { // the arguments below depend on the template specialization // C++ constructor - AP1roGeneralizedSenoObjective(const SparseOp &, const GenCIWfn &, + AP1roGeneralizedSenoObjective(const SparseOp &, const NonSingletCI &, const std::size_t = 0UL, const long * = nullptr, const double * = nullptr, const std::size_t = 0UL, const long * = nullptr, const double * = nullptr); // Python constructor - AP1roGeneralizedSenoObjective(const SparseOp &, const GenCIWfn &, + AP1roGeneralizedSenoObjective(const SparseOp &, const NonSingletCI &, const pybind11::object, const pybind11::object, const pybind11::object, const pybind11::object); @@ -891,7 +891,7 @@ class AP1roGeneralizedSenoObjective : public Objective { AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&) noexcept; // Initializer for {d_,}overlap variables - void init_overlap(const GenCIWfn &); + void init_overlap(const NonSingletCI &); // Overlap function virtual void overlap(const size_t, const double *x, double *y); diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 23c0983..ecdf3bd 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1587,7 +1587,7 @@ param_cons : np.ndarray(Np, dtype=pyci.c_double) py::arg("idx_param_cons") = py::none(), py::arg("param_cons") = py::none()); // Declare Python class based on AP1roGeneralizedSenoObjective -py::class_> ap1rogen_objective(m, "AP1roGeneralizedSenoObjective"); +py::class_> ap1rogen_objective(m, "AP1roGeneralizedSenoObjective"); // Class documentation ap1rogen_objective.doc() = R"""( @@ -1595,7 +1595,7 @@ AP1roGSDGeneralized_sen-o objective class. )"""; // Initializer (keep in mind the Wfn argument should be the right class) -ap1rogen_objective.def(py::init(), +ap1rogen_objective.def(py::init(), R"""( Initialize the AP1roGSDGeneralized_sen-o objective instance. From 7550c22b1a46de3567304b53457b66b016746111 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 10:28:38 -0500 Subject: [PATCH 027/197] Update the fill_hartreefock_det function --- pyci/src/nonsingletci.cpp | 44 +++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 46094e8..3f64b36 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -182,31 +182,35 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { - /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ + /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ long i = 0; long nb = nb2/2; - long nocc_beta = std::min(nocc, nb); - long nocc_alpha = std::min(0L, nocc - nb); - - // First, handle beta spins - while (nocc_beta >= Size()){ - det[i++] = Max(); - nocc_beta -= Size(); - } - - if (nocc_beta) { - det[i] = (1UL << nocc_beta) -1; - i++; + // FIXME: The code is assuming nocc is even + long nocc_beta = nocc/2; //std::min(nocc, nb); + long nocc_alpha = nocc/2; //std::min(0L, nocc - nb); + long num_ulongs = (nb2 + Size() - 1) / Size(); + det.resize(num_ulongs, 0UL); + + std::cout << "Inside nonsingletci/fill_hartreefock_det" << std::endl; + std::cout << "nb: " << nb << std::endl; + std::cout << "nocc: " << nocc << std::endl; + std::cout << "nocc_beta: " << nocc_beta << std::endl; + std::cout << "nocc_alpha: " << nocc_alpha << std::endl; + + for (long i = 0; i < nocc_beta; ++i) { + long bit_index = nb - nocc_beta + i; + det[bit_index / Size()] |= 1UL << (bit_index % Size()); } - - // Fill alpha spins (second half) - while (nocc_alpha >= Size()){ - det[i++] = Max(); - nocc_alpha -= Size(); + + for (long i = 0; i < nocc_alpha; ++i) { + long bit_index = nb2 - nocc_alpha + i; + det[bit_index / Size()] |= 1UL << (bit_index % Size()); } - if (nocc_alpha) { - det[i] = (1UL << nocc) - 1; + std::cout << "det: "; + for (int i = 0; i < num_ulongs; ++i) { + std::cout << det[i] << " "; } + std::cout << std::endl; } From 22b44ca4beee851cc3633c7d470cbc3c9d8b9870 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 10:39:39 -0500 Subject: [PATCH 028/197] Update add_excited_dets for exc order >=2 --- pyci/src/nonsingletci.cpp | 252 +++++++++++++++++++++++++------------- 1 file changed, 165 insertions(+), 87 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 3f64b36..4712f9f 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -54,131 +54,209 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar } - void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ + std::cout << "Inside nonsingletci/add_excited_dets" << std::endl; //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); AlignedVector det(nword); AlignedVector occs(nocc); - AlignedVector occs_up(nocc_up); - AlignedVector occs_dn(nocc_dn); + AlignedVector occs_up(occs.size()); + AlignedVector occs_dn(occs.size()); AlignedVector> occ_pairs; - AlignedVector virs(nvir); - AlignedVector virs_up(nvir_up); - AlignedVector virs_dn(nvir_dn); + AlignedVector virs(nbasis - nocc); + AlignedVector virs_up(virs.size()); + AlignedVector virs_dn(virs.size()); AlignedVector> vir_pairs; AlignedVector occinds(e + 1); AlignedVector virinds(e + 1); fill_occs(nword, rdet, &occs[0]); fill_virs(nword, nbasis, rdet, &virs[0]); - - + + int up_idx = 0, dn_idx = 0; + std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; + std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; + std::cout << "e: " << e << std::endl; + std::cout << "rdet: " << *rdet << std::endl; + std::cout << "occs: "; + for (const auto& elem : occs) { + std::cout << elem << " "; + } + std::cout << std::endl; + + std::cout << "virs: "; + for (const auto& elem : virs) { + std::cout << elem << " "; + } + std::cout << std::endl; // Generate list of up & dn indices for ocs & virs for (int i : occs) { - if (i < nbasis) occs_up.push_back(i); - else occs_dn.push_back(i); + if (i < nbasis/2) occs_up[up_idx++] = i; + else occs_dn[dn_idx++] = i; + } + + // Resize vectors to actual size + occs_up.resize(up_idx); + occs_dn.resize(dn_idx); + + std::cout << "occs_up: "; + for (const auto& elem : occs_up) { + std::cout << elem << " "; + } + std::cout << std::endl; + + std::cout << "occs_dn: "; + for (const auto& elem : occs_dn) { + std::cout << elem << " "; } + std::cout << std::endl; + + up_idx = 0; + dn_idx = 0; for (int a : virs) { - if (a < nbasis) virs_up.push_back(a); - else virs_dn.push_back(a); + if (a < nbasis/2) virs_up[up_idx++] = a; + else virs_dn[dn_idx++] = a; + } + // Resize vectors to actual size + virs_up.resize(up_idx); + virs_dn.resize(dn_idx); + + std::cout << "virs_up: "; + for (const auto& elem : virs_up) { + std::cout << elem << " "; } + std::cout << std::endl; + std::cout << "virs_dn: "; + for (const auto& elem : virs_dn) { + std::cout << elem << " "; + } + std::cout << std::endl; + // Create an unordered set for fast lookup of occupied down-orbitals std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); // Generate occ_pairs for (int i : occs_up) { - if (occ_dn_set.find(i + nbasis) != occ_dn_set.end()) { - occ_pairs.push_back({i, i + nbasis}); + if (occ_dn_set.find(i + nbasis/2) != occ_dn_set.end()) { + occ_pairs.push_back({i, i + nbasis/2}); } } - + std::cout << "occ_pairs: "; + for (const auto& elem : occ_pairs) { + std::cout << elem.first << " " << elem.second << std::endl; + } // Create an unordered set for fast looup of virtual orbitals std::unordered_set virs_set(virs.begin(), virs.end()); // form virtual pairs - for (int a : virs) { - if (virs_set.find(a + nbasis) != virs_set.end()) { - vir_pairs.push_back({a, a + nbasis}); - } - } - - // Handle excitation order 1 - if (e == 1) { - for (long occ : occs_up) { - for (long vir : virs_up) { - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(occ, vir, &det[0]); - add_det(&det[0]); - } - } - for (long occ : occs_dn) { - for (long vir : virs_up) { - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(occ, vir, &det[0]); - add_det(&det[0]); - } - } - return ; - } - - - - //// Handle excitation order 2 - //if (e == 2){ - // for (const auto& occ_pair : occ_pairs){ - // for (const auto& vir_pair : vir_pairs){ - // long o_up = occ_pair.first; - // long o_dn = occ_pair.second; - // long v_up = vir_pair.first; - // long v_dn = vir_pair.second; - // - // std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - // excite_det(o_up, v_up, &det[0]) - // excite_det(o_dn, v_dn, &det[0]) - // add_det(&det[0]) - // - // } - // } - //} + for (int a : virs) { + if (virs_set.find(a + nbasis/2) != virs_set.end()) { + vir_pairs.push_back({a, a + nbasis/2}); + } + } + std::cout << "vir_pairs: "; + for (const auto& elem : vir_pairs) { + std::cout << elem.first << " " << elem.second << std::endl; + } + // Handle excitation order 1 + if (e == 1) { + std::cout << "Handling excitation order 1" << std::endl; + std::cout << "Determinants of excitation order 1" << std::endl; + for (long occ : occs) { + for (long vir : virs) { + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + excite_det(occ, vir, &det[0]); + add_det(&det[0]); + // Print determinant after excite_det loop + + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << std::endl; + } + std::cout << std::endl; + } + std::cout << std::endl; + return ; + } + // Handle excitation orders >= 2 - // Loop over possible values of d (number of pair excitations) + // Iterate over possible (d,s) pairs: d pair excitations and s single excitations + std::cout << "Handling excitation order >= 2" << std::endl; for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ - // Number of single excitations - long num_singles = e - 2 * d; + long s = e - 2 * d; + std::cout << "d: " << d << ", num_singles" << s << std::endl; + if (s > occ_pairs.size() - d) continue; // Not enough pairs for singles - // Apply d pair excitations - if (d > 0) { - for (long i = 0; i < d; ++i) { - const auto& occ_pair = occ_pairs[i]; - const auto& vir_pair = vir_pairs[i]; + // Generate all combinations of d pairs + std::vector> pair_combinations; + std::vector pair_indices(occ_pairs.size()); + std::iota(pair_indices.begin(), pair_indices.end(), 0); + + do { + std::vector combination(pair_indices.begin(), pair_indices.begin() + d); + pair_combinations.push_back(combination); + } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); + + // Process each combination of d pairs + for (const auto& pair_comb: pair_combinations) { + std::vector> used_occ_pairs; + std::vector used_virtuals; + + // Apply pair excitations + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + for (long idx : pair_comb) { + const auto& occ_pair = occ_pairs[idx]; + const auto& vir_pair = vir_pairs[idx]; + + excite_det(occ_pair.first, vir_pair.first, &det[0]); + excite_det(occ_pair.second, vir_pair.second, &det[0]); + + used_occ_pairs.push_back(occ_pair); + used_virtuals.push_back(vir_pair.first); + used_virtuals.push_back(vir_pair.second); + } - long o_up = occ_pair.first; - long o_dn = occ_pair.second; - long v_up = vir_pair.first; - long v_dn = vir_pair.second; + //Exclude used pairs and virtual orbitals + std::vector> remaining_occ_indices; + for (long i = 0; i < occ_pairs.size(); ++i) { + if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { + remaining_occ_indices.push_back(i); + } + } + + // Generate all combinations of s singles + std::vector> single_combinations; + std::vector single_indices(remaining_occ_indices.size()); + std::iota(single_indices.begin(), single_indices.end(), 0); + + do { + std::vector combination(single_indices.begin(), single_indices.begin() + s); + single_combinations.push_back(combination); + } while (std::next_permutation(single_indices.begin(), single_indices.end())); + // Process each combination of s singles + for (const auto& single_comb : single_combinations) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - - excite_det(o_up, v_up, &det[0]); - excite_det(o_dn, v_dn, &det[0]); - add_det(&det[0]); - } - } - // Apply num_singles single excitations - if (num_singles > 0) { - for (long i = 0; i < num_singles; ++i){ - long occ = (i % 2 == 0) ? occs_up[i % occs_up.size()] : occs_dn[i % occs_dn.size()]; - for (long vir : virs) { - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - excite_det(occ, vir, &det[0]); + + // Apply single excitations + for (long idx : single_comb) { + long occ_idx = remaining_occ_indices[idx]; + long occ = occ_pairs[occ_idx].first; // Use the first of the remaining occ_pair + for (long vir: virs) { + if (std::find(used_virtuals.begin(), used_virtuals.end(), vir) != used_virtuals.end()) continue; + excite_det(occ, vir, &det[0]); + } } + add_det(&det[0]); } } - } - + + + } } + void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { @@ -224,7 +302,7 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re } else ptr = reinterpret_cast(ref.cast>().request().ptr); long ndet_old = ndet; - add_excited_dets(ptr, exc); + add_excited_dets(ptr, exc); return ndet - ndet_old; } } //namespace pyci From 5b56062de2dc7b85a3020d2e936d01b32bf026bf Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 11:10:24 -0500 Subject: [PATCH 029/197] Update add_excited_dets exc_order >=2 --- pyci/src/nonsingletci.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 4712f9f..396a31a 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -14,6 +14,7 @@ * along with PyCI. If not, see . */ #include +#include namespace pyci { @@ -187,7 +188,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ long s = e - 2 * d; std::cout << "d: " << d << ", num_singles" << s << std::endl; - if (s > occ_pairs.size() - d) continue; // Not enough pairs for singles + if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles // Generate all combinations of d pairs std::vector> pair_combinations; @@ -219,10 +220,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } //Exclude used pairs and virtual orbitals - std::vector> remaining_occ_indices; - for (long i = 0; i < occ_pairs.size(); ++i) { + std::vector remaining_occ_indices; + for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - remaining_occ_indices.push_back(i); + remaining_occ_indices.push_back(static_cast(i)); } } @@ -261,13 +262,12 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ - long i = 0; long nb = nb2/2; // FIXME: The code is assuming nocc is even long nocc_beta = nocc/2; //std::min(nocc, nb); long nocc_alpha = nocc/2; //std::min(0L, nocc - nb); long num_ulongs = (nb2 + Size() - 1) / Size(); - det.resize(num_ulongs, 0UL); + std::cout << "Inside nonsingletci/fill_hartreefock_det" << std::endl; std::cout << "nb: " << nb << std::endl; From 218e1e29528edda227d63db6a960e23f1958368b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 26 Nov 2024 13:10:38 -0500 Subject: [PATCH 030/197] Add methods to NonSingletCI Python binding for fill_hartreefock_det and add_excited_dets --- pyci/src/binding.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index ecdf3bd..0792581 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -931,6 +931,36 @@ nonsingletci_wfn.def(py::init>(), py::arg("nbasis"), py::arg("nocc_up"), py::arg("nocc_dn"), py::arg("array")); +nonsingletci_wfn.def("fill_hartreefock_det", &NonSingletCI::fill_hartreefock_det, R"""( +Fill the Hartree-Fock determinant in the given ptr. + +Parameters +---------- +nb2 : int + Number of basis functions for total number of spin orbitals. + Because of the way GenCI handles bit strings, it will be + nonsingletci_wfn.nbasis = ham.nbasis * 2. +nocc : int + Total number of occupied orbitals. +det : array + Pointer to the array where the Hartree-Fock determinant will be stored. +)""", + py::arg("nb2"), py::arg("nocc"), py::arg("det")); + +nonsingletci_wfn.def("add_excited_dets", &NonSingletCI::py_add_excited_dets, R"""( +Add excited determinants to the wave function. + +Parameters +---------- +exc : int + Excitation order. +ref : numpy.ndarray, default=None + Reference determinant. Default is the Hartree-Fock determinant. + +)""", + py::arg("exc"), py::arg("ref") = py::none()); + + /* Section: Sparse CI matrix operator class */ From 37d3269957fbf63cf1d908b49322718f10d51ebc Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 13:40:15 -0500 Subject: [PATCH 031/197] Change bit_index for alpha spins in fill_hartreefock_det --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 396a31a..d0cc4d5 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -281,7 +281,7 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { } for (long i = 0; i < nocc_alpha; ++i) { - long bit_index = nb2 - nocc_alpha + i; + long bit_index = i; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } std::cout << "det: "; From 3f9bfced3d448e0461e120e43dc7b34aa2727621 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 13:53:17 -0500 Subject: [PATCH 032/197] Add print statements --- pyci/src/nonsingletci.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index d0cc4d5..fd2a8c8 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -275,12 +275,16 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { std::cout << "nocc_beta: " << nocc_beta << std::endl; std::cout << "nocc_alpha: " << nocc_alpha << std::endl; + std::cout << "Filling beta spin orbitals" << std::endl; for (long i = 0; i < nocc_beta; ++i) { long bit_index = nb - nocc_beta + i; + std::cout << "bit_index: " << bit_index << std::endl; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } + std::cout << "Filling alpha spin orbitals" << std::endl; for (long i = 0; i < nocc_alpha; ++i) { + std::cout << "bit_index: " << i << std::endl;: long bit_index = i; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } From 3ad8e4fe581738350ef34e2ff3e573558a20e9b3 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 13:55:15 -0500 Subject: [PATCH 033/197] Fix typo --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index fd2a8c8..e908de4 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -284,7 +284,7 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { std::cout << "Filling alpha spin orbitals" << std::endl; for (long i = 0; i < nocc_alpha; ++i) { - std::cout << "bit_index: " << i << std::endl;: + std::cout << "bit_index: " << i << std::endl; long bit_index = i; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } From 40f139cf1326fb4fe9747a1121dba93abba0d548 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 13:58:37 -0500 Subject: [PATCH 034/197] Fix bit_index for beta in fill_hartreefock_det --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index e908de4..227f669 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -277,7 +277,7 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { std::cout << "Filling beta spin orbitals" << std::endl; for (long i = 0; i < nocc_beta; ++i) { - long bit_index = nb - nocc_beta + i; + long bit_index = nb + i; std::cout << "bit_index: " << bit_index << std::endl; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } From 0b39487db500324d1050e81863fd469434fb4be6 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 14:46:18 -0500 Subject: [PATCH 035/197] add correct if conditions in add_excited_dets --- pyci/src/nonsingletci.cpp | 138 ++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 65 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 227f669..eb9aa9b 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -160,7 +160,15 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << elem.first << " " << elem.second << std::endl; } - // Handle excitation order 1 + + // Handle excitation order 0 + if (e == 0) { + std::cout << "Handling excitation order 0" << std::endl; + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + add_det(&det[0]); + return ; + } + // Handle excitation order 1 if (e == 1) { std::cout << "Handling excitation order 1" << std::endl; std::cout << "Determinants of excitation order 1" << std::endl; @@ -183,78 +191,78 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Handle excitation orders >= 2 - // Iterate over possible (d,s) pairs: d pair excitations and s single excitations - std::cout << "Handling excitation order >= 2" << std::endl; - for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ - long s = e - 2 * d; - std::cout << "d: " << d << ", num_singles" << s << std::endl; - if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles - - // Generate all combinations of d pairs - std::vector> pair_combinations; - std::vector pair_indices(occ_pairs.size()); - std::iota(pair_indices.begin(), pair_indices.end(), 0); - - do { - std::vector combination(pair_indices.begin(), pair_indices.begin() + d); - pair_combinations.push_back(combination); - } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); - - // Process each combination of d pairs - for (const auto& pair_comb: pair_combinations) { - std::vector> used_occ_pairs; - std::vector used_virtuals; - - // Apply pair excitations - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - for (long idx : pair_comb) { - const auto& occ_pair = occ_pairs[idx]; - const auto& vir_pair = vir_pairs[idx]; - - excite_det(occ_pair.first, vir_pair.first, &det[0]); - excite_det(occ_pair.second, vir_pair.second, &det[0]); - - used_occ_pairs.push_back(occ_pair); - used_virtuals.push_back(vir_pair.first); - used_virtuals.push_back(vir_pair.second); - } - - //Exclude used pairs and virtual orbitals - std::vector remaining_occ_indices; - for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { - if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - remaining_occ_indices.push_back(static_cast(i)); - } - } + if (e >= 2) { + // Iterate over possible (d,s) pairs: d pair excitations and s single excitations + std::cout << "Handling excitation order >= 2" << std::endl; + for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ + long s = e - 2 * d; + std::cout << "d: " << d << ", num_singles" << s << std::endl; + if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles + + // Generate all combinations of d pairs + std::vector> pair_combinations; + std::vector pair_indices(occ_pairs.size()); + std::iota(pair_indices.begin(), pair_indices.end(), 0); + + do { + std::vector combination(pair_indices.begin(), pair_indices.begin() + d); + pair_combinations.push_back(combination); + } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); + + // Process each combination of d pairs + for (const auto& pair_comb: pair_combinations) { + std::vector> used_occ_pairs; + std::vector used_virtuals; + + // Apply pair excitations + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + for (long idx : pair_comb) { + const auto& occ_pair = occ_pairs[idx]; + const auto& vir_pair = vir_pairs[idx]; - // Generate all combinations of s singles - std::vector> single_combinations; - std::vector single_indices(remaining_occ_indices.size()); - std::iota(single_indices.begin(), single_indices.end(), 0); + excite_det(occ_pair.first, vir_pair.first, &det[0]); + excite_det(occ_pair.second, vir_pair.second, &det[0]); - do { - std::vector combination(single_indices.begin(), single_indices.begin() + s); - single_combinations.push_back(combination); - } while (std::next_permutation(single_indices.begin(), single_indices.end())); + used_occ_pairs.push_back(occ_pair); + used_virtuals.push_back(vir_pair.first); + used_virtuals.push_back(vir_pair.second); + } - // Process each combination of s singles - for (const auto& single_comb : single_combinations) { - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + //Exclude used pairs and virtual orbitals + std::vector remaining_occ_indices; + for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { + if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { + remaining_occ_indices.push_back(static_cast(i)); + } + } - // Apply single excitations - for (long idx : single_comb) { - long occ_idx = remaining_occ_indices[idx]; - long occ = occ_pairs[occ_idx].first; // Use the first of the remaining occ_pair - for (long vir: virs) { - if (std::find(used_virtuals.begin(), used_virtuals.end(), vir) != used_virtuals.end()) continue; - excite_det(occ, vir, &det[0]); + // Generate all combinations of s singles + std::vector> single_combinations; + std::vector single_indices(remaining_occ_indices.size()); + std::iota(single_indices.begin(), single_indices.end(), 0); + + do { + std::vector combination(single_indices.begin(), single_indices.begin() + s); + single_combinations.push_back(combination); + } while (std::next_permutation(single_indices.begin(), single_indices.end())); + + // Process each combination of s singles + for (const auto& single_comb : single_combinations) { + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + + // Apply single excitations + for (long idx : single_comb) { + long occ_idx = remaining_occ_indices[idx]; + long occ = occ_pairs[occ_idx].first; // Use the first of the remaining occ_pair + for (long vir: virs) { + if (std::find(used_virtuals.begin(), used_virtuals.end(), vir) != used_virtuals.end()) continue; + excite_det(occ, vir, &det[0]); + } } + add_det(&det[0]); } - add_det(&det[0]); } } - - } } From b3a0497cc278579028b9a0be3b1cc63c2da0c14e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 15:06:05 -0500 Subject: [PATCH 036/197] check number of pairs in occ_pairs in add_excited_dets --- pyci/src/nonsingletci.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index eb9aa9b..e9dabd3 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -170,7 +170,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Handle excitation order 1 if (e == 1) { - std::cout << "Handling excitation order 1" << std::endl; + std::cout << "-----Handling excitation order 1-----" << std::endl; std::cout << "Determinants of excitation order 1" << std::endl; for (long occ : occs) { for (long vir : virs) { @@ -193,11 +193,13 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Handle excitation orders >= 2 if (e >= 2) { // Iterate over possible (d,s) pairs: d pair excitations and s single excitations - std::cout << "Handling excitation order >= 2" << std::endl; + std::cout << "--------Handling excitation order >= 2--------" << std::endl; for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ long s = e - 2 * d; - std::cout << "d: " << d << ", num_singles" << s << std::endl; - if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles + std::cout << "d: " << d << ", num_singles: " << s << std::endl; + long num_pairs = occ_pairs.size(); + //if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles + if (s > num_pairs - d) continue; // Not enough pairs for singles // Generate all combinations of d pairs std::vector> pair_combinations; From 3416769275089a0f9d83ed8188b57c12e67cd72d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 15:22:30 -0500 Subject: [PATCH 037/197] Add avaialble_pairs variable in add_excited_dets exc>=2 --- pyci/src/nonsingletci.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index e9dabd3..6af9e0e 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -198,8 +198,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ long s = e - 2 * d; std::cout << "d: " << d << ", num_singles: " << s << std::endl; long num_pairs = occ_pairs.size(); + std::cout << "num_pairs: " << num_pairs << std::endl; + long available_pairs = num_pairs - d; //if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles - if (s > num_pairs - d) continue; // Not enough pairs for singles + if (s > available_pairs) continue; // Not enough pairs for singles // Generate all combinations of d pairs std::vector> pair_combinations; From 3e066343d190a0f675c128fe473f0ed9cca6d750 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 15:28:59 -0500 Subject: [PATCH 038/197] Print to check the if condition for s in add_excited_dets order >=2 --- pyci/src/nonsingletci.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 6af9e0e..37517b5 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -200,9 +200,12 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ long num_pairs = occ_pairs.size(); std::cout << "num_pairs: " << num_pairs << std::endl; long available_pairs = num_pairs - d; - //if (s > static_cast(occ_pairs.size()) - d) continue; // Not enough pairs for singles - if (s > available_pairs) continue; // Not enough pairs for singles + // Not enough pairs for singles + if (s > available_pairs) { + std::cout << "Not enough pairs for singles" << std::endl; + continue; + } // Generate all combinations of d pairs std::vector> pair_combinations; std::vector pair_indices(occ_pairs.size()); From 6b03678dad176a8d7e2cddeb7ff63557f20e5bef Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 17:56:10 -0500 Subject: [PATCH 039/197] Updated a new algorithm for exc>=2 in add_excited_dets --- pyci/src/nonsingletci.cpp | 197 +++++++++++++++++++++++++++----------- 1 file changed, 140 insertions(+), 57 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 37517b5..c12c8fe 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -55,6 +55,28 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar } +// Function to generate combinations +std::vector> generate_combinations(long n, long k) { + std::vector> combinations; + if (k > n) return combinations; + + std:vector indices(n); + std:iota(indices.begin(), indices.end(), 0); + + std::vector mask(n, false); + std::fill(mask.begin(), mask.begin() + k, true); + + do { + std::vector combination; + for (long i = 0; i < n; ++i) { + if (mask[i]) combination.push_back(indices[i]); + } + combinations.push_back(combination); + } while (std::prev_permutation(mask.begin(), mask.end())); + + return combinations; +} + void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Inside nonsingletci/add_excited_dets" << std::endl; //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); @@ -191,84 +213,82 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Handle excitation orders >= 2 + long num_pairs = occ_pairs.size(); + std::cout << "num_pairs: " << num_pairs << std::endl; if (e >= 2) { // Iterate over possible (d,s) pairs: d pair excitations and s single excitations std::cout << "--------Handling excitation order >= 2--------" << std::endl; - for (long d = 0; d <= std::min(e/2, static_cast(occ_pairs.size())); ++d){ - long s = e - 2 * d; - std::cout << "d: " << d << ", num_singles: " << s << std::endl; - long num_pairs = occ_pairs.size(); - std::cout << "num_pairs: " << num_pairs << std::endl; - long available_pairs = num_pairs - d; + + std::vector> pair_combinations; + for (long d = 0; d <= std::min(e/2, num_pairs); ++d){ + long num_singles = e - 2 * d; + pair_combinations.push_back(generate_combinations(num_pairs, d)); + + std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; // Not enough pairs for singles - if (s > available_pairs) { + if (s > (num_pairs - d)) { std::cout << "Not enough pairs for singles" << std::endl; continue; } - // Generate all combinations of d pairs - std::vector> pair_combinations; - std::vector pair_indices(occ_pairs.size()); - std::iota(pair_indices.begin(), pair_indices.end(), 0); - - do { - std::vector combination(pair_indices.begin(), pair_indices.begin() + d); - pair_combinations.push_back(combination); - } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); - - // Process each combination of d pairs - for (const auto& pair_comb: pair_combinations) { - std::vector> used_occ_pairs; - std::vector used_virtuals; - // Apply pair excitations + // Process pair combinations for current d + for (const auto& pair_comb : pair_combinations[d]) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - for (long idx : pair_comb) { - const auto& occ_pair = occ_pairs[idx]; - const auto& vir_pair = vir_pairs[idx]; + std::vector remaining_occ_indices; + std::vector used_virs; - excite_det(occ_pair.first, vir_pair.first, &det[0]); - excite_det(occ_pair.second, vir_pair.second, &det[0]); + if (d > 0) { + for (long idx : pair_comb) { + const auto& occ_pair = occ_pairs[idx]; + const auto& vir_pair = vir_pairs[idx]; - used_occ_pairs.push_back(occ_pair); - used_virtuals.push_back(vir_pair.first); - used_virtuals.push_back(vir_pair.second); - } + excite_det(occ_pair.first, vir_pair.first, &det[0]); + excite_det(occ_pair.second, vir_pair.second, &det[0]); - //Exclude used pairs and virtual orbitals - std::vector remaining_occ_indices; - for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { - if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - remaining_occ_indices.push_back(static_cast(i)); + used_virs.push_back(vir_pair.first); + used_virs.push_back(vir_pair.second); + } + + // Determine remaining occupied indices + for (long i = 0; i < num_pairs; ++i) { + if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { + remaining_occ_indices.push_back(i); + } + } + } else { + // If d == 0, then all pairs are available for singles + for (long i = 0; i < num_pairs; ++i) { + remaining_occ_indices.push_back(i); } } - // Generate all combinations of s singles - std::vector> single_combinations; - std::vector single_indices(remaining_occ_indices.size()); - std::iota(single_indices.begin(), single_indices.end(), 0); - - do { - std::vector combination(single_indices.begin(), single_indices.begin() + s); - single_combinations.push_back(combination); - } while (std::next_permutation(single_indices.begin(), single_indices.end())); - - // Process each combination of s singles - for (const auto& single_comb : single_combinations) { - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - - // Apply single excitations - for (long idx : single_comb) { - long occ_idx = remaining_occ_indices[idx]; - long occ = occ_pairs[occ_idx].first; // Use the first of the remaining occ_pair - for (long vir: virs) { - if (std::find(used_virtuals.begin(), used_virtuals.end(), vir) != used_virtuals.end()) continue; - excite_det(occ, vir, &det[0]); + // Process single combinations for current num_singles + if (num_singles > 0) { + auto single_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); + for (const auto& single_comb : single_combinations) { + // Do NOT reset det here; use the alredy existed det from pair excitations + AlignedVector temp_det(nword); + std::memcpy(&temp_det[0], det, sizeof(ulong) * nword); + + // Apply single excitations + for (long idx : single_comb) { + long occ_idx = remaining_occ_indices[idx]; + long occ = occ_pairs[occ_idx].first; + + for (long vir : virs) { + if (std::find(used_virs.begin(), used_virs.end(), vir) != used_virs.end()) continue; + excite_det(occ, vir, &temp_det[0]); + } + } } + add_det(&det[0]); } + } else { add_det(&det[0]); } } + } } } @@ -328,3 +348,66 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re +// // // Generate all combinations of d pairs +// std::vector> pair_combinations; +// std::vector pair_indices(occ_pairs.size()); +// std::iota(pair_indices.begin(), pair_indices.end(), 0); + +// do { +// std::vector combination(pair_indices.begin(), pair_indices.begin() + d); +// pair_combinations.push_back(combination); +// } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); + +// // Process each combination of d pairs +// for (const auto& pair_comb: pair_combinations) { +// std::vector> used_occ_pairs; +// std::vector used_virtuals; + +// // Apply pair excitations +// std::memcpy(&det[0], rdet, sizeof(ulong) * nword); +// for (long idx : pair_comb) { +// const auto& occ_pair = occ_pairs[idx]; +// const auto& vir_pair = vir_pairs[idx]; + +// excite_det(occ_pair.first, vir_pair.first, &det[0]); +// excite_det(occ_pair.second, vir_pair.second, &det[0]); + +// used_occ_pairs.push_back(occ_pair); +// used_virtuals.push_back(vir_pair.first); +// used_virtuals.push_back(vir_pair.second); +// } + +// //Exclude used pairs and virtual orbitals +// std::vector remaining_occ_indices; +// for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { +// if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { +// remaining_occ_indices.push_back(static_cast(i)); +// } +// } + +// // Generate all combinations of s singles +// std::vector> single_combinations; +// std::vector single_indices(remaining_occ_indices.size()); +// std::iota(single_indices.begin(), single_indices.end(), 0); + +// do { +// std::vector combination(single_indices.begin(), single_indices.begin() + s); +// single_combinations.push_back(combination); +// } while (std::next_permutation(single_indices.begin(), single_indices.end())); + +// // Process each combination of s singles +// for (const auto& single_comb : single_combinations) { +// std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + +// // Apply single excitations +// for (long idx : single_comb) { +// long occ_idx = remaining_occ_indices[idx]; +// long occ = occ_pairs[occ_idx].first; // Use the first of the remaining occ_pair +// for (long vir: virs) { +// if (std::find(used_virtuals.begin(), used_virtuals.end(), vir) != used_virtuals.end()) continue; +// excite_det(occ, vir, &det[0]); +// } +// } +// add_det(&det[0]); +// } +// } \ No newline at end of file From 28270dd3f7edad1968a7e865f6fcddc2ed4c765d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:04:32 -0500 Subject: [PATCH 040/197] Fix typos --- pyci/src/nonsingletci.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index c12c8fe..2c8f232 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -60,8 +60,8 @@ std::vector> generate_combinations(long n, long k) { std::vector> combinations; if (k > n) return combinations; - std:vector indices(n); - std:iota(indices.begin(), indices.end(), 0); + std::vector indices(n); + std::iota(indices.begin(), indices.end(), 0); std::vector mask(n, false); std::fill(mask.begin(), mask.begin() + k, true); @@ -227,7 +227,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; // Not enough pairs for singles - if (s > (num_pairs - d)) { + if (num_singles > (num_pairs - d)) { std::cout << "Not enough pairs for singles" << std::endl; continue; } From 4bf0287bc85ee91180defe33f29cec900e0aec0f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:04:56 -0500 Subject: [PATCH 041/197] Add entry for generate_combinations function for NonSingletCI --- pyci/include/pyci.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index c3f28c4..b2252b3 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -655,6 +655,8 @@ struct NonSingletCI final : public GenCIWfn { void fill_hartreefock_det(long, long, ulong *); + std::vector> generate_combinations(long, long); + void add_excited_dets(const ulong *, const long); long py_add_excited_dets(const long, const pybind11::object); From 34d1d4665448251aa6999c57baf60703729b7d6c Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:18:41 -0500 Subject: [PATCH 042/197] fix typos { } --- pyci/src/nonsingletci.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 2c8f232..56a8048 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -279,18 +279,18 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (long vir : virs) { if (std::find(used_virs.begin(), used_virs.end(), vir) != used_virs.end()) continue; excite_det(occ, vir, &temp_det[0]); - } } - } + } add_det(&det[0]); } } else { add_det(&det[0]); } } - } - } + + } + } @@ -341,7 +341,7 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re } else ptr = reinterpret_cast(ref.cast>().request().ptr); long ndet_old = ndet; - add_excited_dets(ptr, exc); + add_excited_dets(ptr, exc); return ndet - ndet_old; } } //namespace pyci From 69d44575b51d4e84ae1d48667b258c321dac63fa Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:27:53 -0500 Subject: [PATCH 043/197] Change type of pair_combinations in add_excited_dets --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 56a8048..3b638f2 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -219,7 +219,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Iterate over possible (d,s) pairs: d pair excitations and s single excitations std::cout << "--------Handling excitation order >= 2--------" << std::endl; - std::vector> pair_combinations; + std::vector>> pair_combinations; for (long d = 0; d <= std::min(e/2, num_pairs); ++d){ long num_singles = e - 2 * d; pair_combinations.push_back(generate_combinations(num_pairs, d)); From 548602aa9472adb58d282387eec70a12d23064a8 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:32:26 -0500 Subject: [PATCH 044/197] Fix det input in num_singles>0 case in add_excited_dets --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 3b638f2..d992960 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -269,7 +269,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (const auto& single_comb : single_combinations) { // Do NOT reset det here; use the alredy existed det from pair excitations AlignedVector temp_det(nword); - std::memcpy(&temp_det[0], det, sizeof(ulong) * nword); + std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); // Apply single excitations for (long idx : single_comb) { From dabfb0bc256b9b7bfaf1f0bf262711d8d38661b0 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:39:25 -0500 Subject: [PATCH 045/197] Fix the generate_combinations definition --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index d992960..e8ee22d 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -56,7 +56,7 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar // Function to generate combinations -std::vector> generate_combinations(long n, long k) { +std::vector> pyci::NonSingletCI::generate_combinations(long n, long k) { std::vector> combinations; if (k > n) return combinations; From 74ba20bd0db2a4854f9d1cccbd9b9f4070e205dc Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 18:45:48 -0500 Subject: [PATCH 046/197] Add Print statements --- pyci/src/nonsingletci.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index e8ee22d..19896fc 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -248,6 +248,13 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ used_virs.push_back(vir_pair.first); used_virs.push_back(vir_pair.second); + + std::cout << "Determinant after pair excitation of" << std::endl; + std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; + std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } } // Determine remaining occupied indices @@ -279,11 +286,14 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (long vir : virs) { if (std::find(used_virs.begin(), used_virs.end(), vir) != used_virs.end()) continue; excite_det(occ, vir, &temp_det[0]); + std::cout << "Exciting singles from " << occ << " to " << vir << std::endl; } - } + } + // Add the fully excited determinant (pair + singles) add_det(&det[0]); } } else { + // If num_singles == 0, directly add determinant after pair excitations add_det(&det[0]); } } From d3d187d818f8184da31db3d8b6d8116ec5848e37 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 19:03:01 -0500 Subject: [PATCH 047/197] Add print statements --- pyci/src/nonsingletci.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 19896fc..911a2bb 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -291,6 +291,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Add the fully excited determinant (pair + singles) add_det(&det[0]); + // Print determinant after single excitations + std::cout << "Determinant after single excitation" << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } } } else { // If num_singles == 0, directly add determinant after pair excitations From a43c8b1e1baa613fd759fba5cd678b76d00ee29b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 19:06:09 -0500 Subject: [PATCH 048/197] Corrected the input det for add_det for S>0 case in add_excited_dets --- pyci/src/nonsingletci.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 911a2bb..bcc8fba 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -290,11 +290,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } } // Add the fully excited determinant (pair + singles) - add_det(&det[0]); + add_det(&temp_det[0]); // Print determinant after single excitations std::cout << "Determinant after single excitation" << std::endl; for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; + std::cout << temp_det[k] << " "; } } } else { From 5b343ab9057eefac10f0aabdd9e72a33213d6558 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 20:22:58 -0500 Subject: [PATCH 049/197] Update S>0 case in add_excited_dets --- pyci/src/nonsingletci.cpp | 110 ++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index bcc8fba..91b0d33 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -222,7 +222,6 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::vector>> pair_combinations; for (long d = 0; d <= std::min(e/2, num_pairs); ++d){ long num_singles = e - 2 * d; - pair_combinations.push_back(generate_combinations(num_pairs, d)); std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; @@ -232,74 +231,81 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ continue; } + // Generate pair combinations + pair_combinations.push_back(generate_combinations(num_pairs, d)); + // Process pair combinations for current d for (const auto& pair_comb : pair_combinations[d]) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); std::vector remaining_occ_indices; std::vector used_virs; - if (d > 0) { - for (long idx : pair_comb) { - const auto& occ_pair = occ_pairs[idx]; - const auto& vir_pair = vir_pairs[idx]; - - excite_det(occ_pair.first, vir_pair.first, &det[0]); - excite_det(occ_pair.second, vir_pair.second, &det[0]); - - used_virs.push_back(vir_pair.first); - used_virs.push_back(vir_pair.second); - - std::cout << "Determinant after pair excitation of" << std::endl; - std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; - std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } + for (long idx : pair_comb) { + const auto& occ_pair = occ_pairs[idx]; + const auto& vir_pair = vir_pairs[idx]; + + excite_det(occ_pair.first, vir_pair.first, &det[0]); + excite_det(occ_pair.second, vir_pair.second, &det[0]); + + used_virs.push_back(vir_pair.first); + used_virs.push_back(vir_pair.second); + + std::cout << "Determinant after pair excitation of" << std::endl; + std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; + std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; } + } - // Determine remaining occupied indices - for (long i = 0; i < num_pairs; ++i) { - if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - remaining_occ_indices.push_back(i); - } - } - } else { - // If d == 0, then all pairs are available for singles - for (long i = 0; i < num_pairs; ++i) { + // Determine remaining occupied indices + for (long i = 0; i < num_pairs; ++i) { + if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { remaining_occ_indices.push_back(i); } } - + // Process single combinations for current num_singles - if (num_singles > 0) { - auto single_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); - for (const auto& single_comb : single_combinations) { - // Do NOT reset det here; use the alredy existed det from pair excitations - AlignedVector temp_det(nword); - std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); - - // Apply single excitations - for (long idx : single_comb) { - long occ_idx = remaining_occ_indices[idx]; - long occ = occ_pairs[occ_idx].first; - - for (long vir : virs) { - if (std::find(used_virs.begin(), used_virs.end(), vir) != used_virs.end()) continue; - excite_det(occ, vir, &temp_det[0]); - std::cout << "Exciting singles from " << occ << " to " << vir << std::endl; + auto single_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); + std::cout << "single_combinations: " << std::endl; + + for (const auto& single_comb : single_combinations) { + // Do NOT reset det here; use the alredy existed det from pair excitations + AlignedVector temp_det(nword); + std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); + + // Apply single excitations + for (long idx : single_comb) { + long occ_idx = remaining_occ_indices[idx]; + long occ = occ_pairs[occ_idx].first; + + for (long vir : virs) { + if (std::find(used_virs.begin(), used_virs.end(), vir) != used_virs.end()) continue; + + // Apply single excitation + AlignedVector single_det(nword); + std::memcpy(&single_det[0], &temp_det[0], sizeof(ulong) * nword); + excite_det(occ, vir, &single_det[0]); + std::cout << "Exciting singles from " << occ << " to " << vir << std::endl; + // Add the fully excited determinant (pair + singles) + add_det(&temp_det[0]); + // Print determinant after single excitations + std::cout << "Determinant after single excitation" << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << temp_det[k] << " "; } } - // Add the fully excited determinant (pair + singles) - add_det(&temp_det[0]); - // Print determinant after single excitations - std::cout << "Determinant after single excitation" << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << temp_det[k] << " "; - } } - } else { + + } + if (s== 0){ // If num_singles == 0, directly add determinant after pair excitations add_det(&det[0]); + // Print determinant after single excitations + std::cout << "Determinant for s=0" << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << temp_det[k] << " "; + } } } } From 89fc9b854ac394a4a8441ba8c7d7e5738319c17b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 20:24:36 -0500 Subject: [PATCH 050/197] Update S>0 case in add_excited_dets --- pyci/src/nonsingletci.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 91b0d33..5d3a073 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -292,13 +292,13 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Print determinant after single excitations std::cout << "Determinant after single excitation" << std::endl; for (int k = 0; k < nword; ++k) { - std::cout << temp_det[k] << " "; + std::cout << det[k] << " "; } } } } - if (s== 0){ + if (num_singles == 0){ // If num_singles == 0, directly add determinant after pair excitations add_det(&det[0]); // Print determinant after single excitations From d838fe42b2a3cf82d5bf42b183ce2d2c86333c73 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 20:26:46 -0500 Subject: [PATCH 051/197] Update S>0 case in add_excited_dets --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 5d3a073..1b70e86 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -304,7 +304,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Print determinant after single excitations std::cout << "Determinant for s=0" << std::endl; for (int k = 0; k < nword; ++k) { - std::cout << temp_det[k] << " "; + std::cout << det[k] << " "; } } } From f25db319f17e872887f8c2e56b079b74175b8c98 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 14:20:52 -0500 Subject: [PATCH 052/197] Change base class from GenCIWfn to NonSingletCI --- pyci/fanci/ap1rogen.py | 48 ++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index 9af89d8..a407042 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -29,7 +29,8 @@ def __init__( ham: pyci.hamiltonian, nocc: int, nproj: int = None, - wfn: pyci.genci_wfn = None, + wfn: pyci.nonsingletci_wfn = None, + fill: str = 'excitation', **kwargs: Any, ) -> None: r""" @@ -43,8 +44,9 @@ def __init__( Number of occupied orbitals. nproj : int, optional Number of determinants in projection ("P") space. - wfn : pyci.genci_wfn, optional + wfn : pyci.nonsingletci_wfn If specified, this PyCI wave function defines the projection ("P") space. + fill : kwargs : Any, optional Additional keyword arguments for base FanCI class. @@ -72,34 +74,34 @@ def __init__( for i, j in zip(det_array, occ_array): print(i, j) - print("\nCreating GenCI wfn") - wfn = pyci.genci_wfn(wfn) + print("\nCreating NonSingletCI wfn") + wfn = pyci.nonsingletci_wfn(wfn) print("wfn.nocc, wfn.nocc_up, wfn.nocc_dn: ", wfn.nocc, wfn.nocc_up, wfn.nocc_dn) occ_array = wfn.to_occ_array() det_array = wfn.to_det_array() - print("\nFor GenCI wfn det_array: ", len(det_array), "\n", det_array) + print("\nFor NonSingletCI wfn det_array: ", len(det_array), "\n", det_array) #for det, occ in zip(det_array, occ_array): # print(det, bin(int(det)), occ) - # Generate the bitstring - bitstring = ((1 << wfn.nocc //2) - 1) << ham.nbasis | (1 << wfn.nocc//2) - 1 - # Convert to binary string with leading zeros - nb = ham.nbasis - bit_str = format(bitstring, f'0{2 * nb}b') - unocc = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '0'] - occ = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '1'] - # Adding non-spin-preserving alpha -> beta singles - for i in occ: - for a in unocc: - exc_str = _excite_det(i, a, int(bit_str,2)) - print("i, a, exc_str", i, a, exc_str, format(exc_str, f'0{2*nb}b')) - wfn.add_det(np.array(exc_str, dtype=pyci.c_ulong)) + ## Generate the bitstring + #bitstring = ((1 << wfn.nocc //2) - 1) << ham.nbasis | (1 << wfn.nocc//2) - 1 + ## Convert to binary string with leading zeros + #nb = ham.nbasis + #bit_str = format(bitstring, f'0{2 * nb}b') + #unocc = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '0'] + #occ = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '1'] + ## Adding non-spin-preserving alpha -> beta singles + #for i in occ: + # for a in unocc: + # exc_str = _excite_det(i, a, int(bit_str,2)) + # print("i, a, exc_str", i, a, exc_str, format(exc_str, f'0{2*nb}b')) + # wfn.add_det(np.array(exc_str, dtype=pyci.c_ulong)) + # + #det_array = wfn.to_det_array() + #print("\nFor GenCI wfn det_array after adding Gen_sen-o S:", len(det_array), "\n", det_array) - det_array = wfn.to_det_array() - print("\nFor GenCI wfn det_array after adding Gen_sen-o S:", len(det_array), "\n", det_array) - - elif not isinstance(wfn, pyci.genci_wfn): - raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.genci_wfn`") + elif not isinstance(wfn, pyci.nonsingletci_wfn): + raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.nonsingletci_wfn`") #elif wfn.nocc_up != nocc or wfn.nocc != nocc: elif wfn.nocc != nocc: raise ValueError(f"wfn.nocc does not match `nocc={nocc}` parameter") From 4bb2bf2309ddad540f3f2b7291df5ade8475019a Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 14:42:13 -0500 Subject: [PATCH 053/197] Change base class from GenCIWfn to NonSingletCI --- pyci/src/ap1rogen.cpp | 215 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 pyci/src/ap1rogen.cpp diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp new file mode 100644 index 0000000..52ca364 --- /dev/null +++ b/pyci/src/ap1rogen.cpp @@ -0,0 +1,215 @@ +/* This file is part of PyCI. + * + * PyCI is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * PyCI is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with PyCI. If not, see . */ + +#include + +namespace pyci { + +// See apig.cpp for reference + +// Constructor with Raw Pointers + +// call to the base class constructor fullciwfn with the provided parameters +AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_, const NonSingletCI &wfn_, + const std::size_t n_detcons_, + const long *idx_detcons_, + const double *val_detcons_, + const std::size_t n_paramcons_, + const long *idx_paramcons_, + const double *val_paramcons_) +: Objective::Objective(op_, wfn_, n_detcons_, idx_detcons_, val_detcons_, n_paramcons_, idx_paramcons_, val_paramcons_) +{ + init_overlap(wfn_); +} +// call to initizlize the overlap related data + +// Constructor with pybind11 objects +AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_, const NonSingletCI &wfn_, + const pybind11::object idx_detcons_, + const pybind11::object val_detcons_, + const pybind11::object idx_paramcons_, + const pybind11::object val_paramcons_) +: Objective::Objective(op_, wfn_, idx_detcons_, val_detcons_, idx_paramcons_, val_paramcons_) +{ + init_overlap(wfn_); +} +// Copy Constructor +// obj is the constant reference to another object to be copied +AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGeneralizedSenoObjective &obj) +: Objective::Objective(obj), nrow(obj.nrow), ncol(obj.ncol), + nexc_list(obj.nexc_list), hole_list(obj.hole_list), part_list(obj.part_list) +{ + return; +} + +// Move constructor +// obj is the rvalue reference to another object to be moved +AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&obj) noexcept +: Objective::Objective(obj), nrow(std::exchange(obj.nrow, 0)), ncol(std::exchange(obj.ncol, 0)), + nexc_list(std::move(obj.nexc_list)), hole_list(std::move(obj.hole_list)), part_list(std::move(obj.part_list)) +{ + return; +} + +void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) +{ + // Initialize your class-specific variables here + // init_Overlap objective for the AP1roGSDspin_sen-o + //nparam = 2 * wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); //paired-doubles + alpha singles + //nparam += wfn_.nocc_dn * (wfn_.nbasis - wfn_.nocc_dn); // beta singles + nparam = wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); + nrow = wfn_.nocc_up; + ncol = wfn_.nbasis - wfn_.nocc_up; + + ovlp.resize(wfn_.ndet); + d_ovlp.resize(wfn_.ndet * nparam); + + nexc_list.resize(nconn); + hole_list.resize(wfn_.nocc * nconn); //list of all holes + part_list.resize(wfn_.nocc * nconn); //list of all particles + + std::size_t nword = (ulong)wfn_.nword; + + for (std::size_t idet = 0; idet != nconn; ++idet) + { + std::vector rdet(wfn_.nword); + fill_hartreefock_det(wfn_.nocc, &rdet[0]); + const ulong *det = wfn_.det_ptr(idet); + ulong word, hword, pword; + // Initialize your class-specific variables here + std::size_t h, p, nexc = 0; + for (std::size_t iword = 0; iword != nword; ++iword) + { + word = rdet[iword] ^ det[iword]; //str for excitation + hword = word & rdet[iword]; //str for hole + pword = word & det[iword]; //str for particle + while(hword){ + h = Ctz(hword); + p = Ctz(pword); + hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); + part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; + hword &= ~(1UL << h); + pword &= ~(1UL << p); + ++nexc; + } + } + nexc_list[idet] = nexc; + } +} + +void AP1roGeneralizedSenoObjective::overlap(const size_t ndet, const double *x, double *y) +{ + // x == parameters p_j + // y == overlap vector σ_i + std::size_t m, i, j, k, c; + std::size_t *hlist, *plist; + double rowsum, rowsumprod, out; + + for (std::size_t idet =0; idet != ndet; ++idet) + { + m = nexc_list[idet]; + if (m == 0) { + y[idet] = 1; + continue; + } + + hlist = &hole_list[idet * nrow]; + plist = &part_list[idet * nrow]; + + out = 0; + c = 1UL << m; + + for (k=0; k < c; ++k) + { + rowsumprod = 1.0; + for (i = 0; i < m; ++i) + { + rowsum = 1.0; + for (j = 0; j < m; ++j) + { + if (k & (1UL << j)) + { + rowsum *= x[ncol * hlist[j] + plist[i]]; + } } + rowsumprod += rowsum; + } + out += rowsumprod * (1 - ((__builtin_popcount(k) & 1) << 1)); + } + y[idet] = out * ((m % 2 == 1) ? -1 : 1); + } +} + +void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y) +{ + // x == parameters p_j + // y == unwrapped overlap objective ∂σ_i/∂p_j + + std::size_t m, n, i, j, k, c; + std::size_t *hlist, *plist; + double rowsum, rowsumprod, out; + + for (std::size_t idet = 0; idet != ndet; ++idet){ + for (std::size_t iparam = 0; iparam != nparam; ++iparam){ + hlist = &hole_list[idet * nrow]; + plist = &part_list[idet * nrow]; + + m = nexc_list[idet]; + if (m == 0){ + y[ndet * iparam + idet] = 0; + continue; + } + + std::vector rows; + std::vector cols; + for (i = 0; i < m; ++i){ + if (hlist[i] != iparam / ncol){ + rows.push_back(hlist[i]); + } + if (plist[i] != iparam % ncol){ + cols.push_back(plist[i]); + } + } + m = rows.size(); + n = cols.size(); + if (m == 0 && n == 0) { + y[ndet * iparam + idet] = 1; + continue; + } else if (m == nexc_list[idet] || n == nexc_list[idet] || m != n) { + y[ndet * iparam + idet] = 0; + continue; + } + out = 0; + + c = 1UL << m; + for (k = 0; k < c; ++k){ + rowsumprod = 1.0; + for (i = 0; i < m; ++i){ + rowsum = 1.0; + for (j = 0; j < m; ++j){ + if (k & (1UL << j)){ + rowsum *= x[ncol * hlist[j] + plist[i]]; + } + } + rowsumprod *= rowsum; + } + out += rowsumprod * (1 - ((__builtin_popcountll(k) & 1) << 1)); + } + y[ndet * iparam + idet] = out * ((m % 2 == 1) ? -1 : 1); + + } + } +} + +} // namespace pyci From 04abc32da5a2cb27d2d63d3ae7c47c04f8ba0930 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 14 Nov 2024 14:47:08 -0500 Subject: [PATCH 054/197] Change base class from GenCIWfn to NonSingletCI --- pyci/src/binding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 0792581..7f6996b 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1634,7 +1634,7 @@ Parameters op : pyci.sparse_op Sparse operator instance with ``nproj`` rows ("P" space) and ``nconn`` columns ("S" space). wfn : pyci.doci_wfn - DOCI wave function with ``nconn`` determinants. + NonSingletCI wave function with ``nconn`` determinants. The first ``nproj`` determinants should correspond to the "S" space. idx_det_cons : np.ndarray(Nd, dtype=pyci.c_long) The indices of the determinants on which constraints should be placed. From a5df30c00f03dda5c3c753df8f6442ba7f242f69 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 13:46:16 -0500 Subject: [PATCH 055/197] update nparam value --- pyci/src/ap1rogen.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 52ca364..c54b09d 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -67,9 +67,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { // Initialize your class-specific variables here // init_Overlap objective for the AP1roGSDspin_sen-o - //nparam = 2 * wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); //paired-doubles + alpha singles - //nparam += wfn_.nocc_dn * (wfn_.nbasis - wfn_.nocc_dn); // beta singles - nparam = wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); + nparam = 2 * wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); //paired-doubles + alpha singles + nparam += wfn_.nocc_dn * (wfn_.nbasis - wfn_.nocc_dn); // beta singles nrow = wfn_.nocc_up; ncol = wfn_.nbasis - wfn_.nocc_up; From f7f69229885f4dd376780038d80fa930f1b9c6c5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 15:49:34 -0500 Subject: [PATCH 056/197] Add explicit instantiation for Objective template --- pyci/src/fanci.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyci/src/fanci.cpp b/pyci/src/fanci.cpp index c5f9f10..9b20ea4 100644 --- a/pyci/src/fanci.cpp +++ b/pyci/src/fanci.cpp @@ -258,4 +258,6 @@ template class Objective; template class Objective; +template class Objective; + } // namespace pyci From edd8ff833211aa15d74b81e49886a668674351b3 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 16:06:29 -0500 Subject: [PATCH 057/197] Add import nonsingletci_wfn --- pyci/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/__init__.py b/pyci/__init__.py index 57e5ad0..5fda201 100644 --- a/pyci/__init__.py +++ b/pyci/__init__.py @@ -18,7 +18,7 @@ from .pyci import __version__, c_long, c_ulong, c_double, sparse_op from .pyci import secondquant_op, wavefunction, one_spin_wfn, two_spin_wfn -from .pyci import doci_wfn, fullci_wfn, genci_wfn, sparse_op +from .pyci import doci_wfn, fullci_wfn, genci_wfn, nonsingletci_wfn, sparse_op from .pyci import get_num_threads, set_num_threads, popcnt, ctz from .pyci import compute_overlap, compute_rdms, compute_transition_rdms from .pyci import add_hci, compute_enpt2 From fcaa583762505b7974f66aa717488d13e42ee486 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 21 Nov 2024 16:14:14 -0500 Subject: [PATCH 058/197] add print statement --- pyci/src/ap1rog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyci/src/ap1rog.cpp b/pyci/src/ap1rog.cpp index 99b4926..022ee7e 100644 --- a/pyci/src/ap1rog.cpp +++ b/pyci/src/ap1rog.cpp @@ -79,8 +79,11 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) std::size_t h, p, nexc = 0; std::cout << "idet: " << idet << std::endl; - + std::cout << "nword: " << nword << std::endl; + for (std::size_t iword = 0; iword != nword; ++iword) { + std::cout << "rdet[iword]: " << rdet[iword] << std::endl; + std::cout << "det[iword]: " << det[iword] << std::endl; word = rdet[iword] ^ det[iword]; hword = word & rdet[iword]; pword = word & det[iword]; From fba094e353a66d6a026b1f8cf581b1271e4b1fea Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 24 Nov 2024 21:39:39 -0500 Subject: [PATCH 059/197] Add print statements --- pyci/src/ap1rogen.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index c54b09d..b753138 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -65,12 +65,17 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSen void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { + std::cout << "Inside init_overlap" << std::endl; // Initialize your class-specific variables here // init_Overlap objective for the AP1roGSDspin_sen-o nparam = 2 * wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); //paired-doubles + alpha singles + std::cout << "nparam (doubles + S_alpha): " << nparam << std::endl; nparam += wfn_.nocc_dn * (wfn_.nbasis - wfn_.nocc_dn); // beta singles + std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; nrow = wfn_.nocc_up; ncol = wfn_.nbasis - wfn_.nocc_up; + std::cout << "nrow: " << nrow << ", ncol: " << ncol << std::endl; + std::cout << "nconn: " << nconn << std::endl; ovlp.resize(wfn_.ndet); d_ovlp.resize(wfn_.ndet * nparam); @@ -85,6 +90,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { std::vector rdet(wfn_.nword); fill_hartreefock_det(wfn_.nocc, &rdet[0]); + std::cout << "After fill_hartreefock_det rdet:" << rdet << std::endl; const ulong *det = wfn_.det_ptr(idet); ulong word, hword, pword; // Initialize your class-specific variables here @@ -101,6 +107,11 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; hword &= ~(1UL << h); pword &= ~(1UL << p); + std::cout << "hword" << hword << std::endl; + std::cout << "pword" << pword << std::endl; + std::cout << "nexc: " << nexc << std::endl; + std::cout << "hole_list: " << hole_list[idet * wfn_.nocc_up + nexc] << std::endl; + std::cout << "part_list: " << part_list[idet * wfn_.nocc_up + nexc] << std::endl; ++nexc; } } From 2fd9a1a666614894ae86d0ea48a548274c97f8b7 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 24 Nov 2024 21:40:23 -0500 Subject: [PATCH 060/197] Add print statements --- pyci/src/ap1rog.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/pyci/src/ap1rog.cpp b/pyci/src/ap1rog.cpp index 022ee7e..bed5cab 100644 --- a/pyci/src/ap1rog.cpp +++ b/pyci/src/ap1rog.cpp @@ -82,7 +82,7 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) std::cout << "nword: " << nword << std::endl; for (std::size_t iword = 0; iword != nword; ++iword) { - std::cout << "rdet[iword]: " << rdet[iword] << std::endl; + std::cout << "rdet[" << iword << "]: " << rdet[iword] << std::endl; std::cout << "det[iword]: " << det[iword] << std::endl; word = rdet[iword] ^ det[iword]; hword = word & rdet[iword]; @@ -94,7 +94,7 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; - std::cout << "h: " << h << ", p: " << p << std::endl; + std::cout << "nexc: " << nexc << ",h: " << h << ", p: " << p << std::endl; std::cout << "hole_list: " << hole_list[idet * wfn_.nocc_up + nexc] << ", part_list: " << part_list[idet * wfn_.nocc_up + nexc] << std::endl; hword &= ~(1UL << h); @@ -132,8 +132,8 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Iterate over c = pow(2, m) submatrices (equal to (1 << m)) submatrices. */ c = 1UL << m; - std::cout << "c: " << c << std::endl; - std::cout << "m: " << m << std::endl; + std::cout << "idet" << idet << std::endl; + std::cout <<"c: " << c << ", m: " << m << std::endl; /* Loop over columns of submatrix; compute product of row sums. */ for (k = 0; k < c; ++k) { @@ -146,24 +146,26 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Add element to row sum if the row index is in the characteristic * * vector of the submatrix, which is the binary vector given by k. */ - std::cout << "j, k: " << j << "," << k << std::endl; - std::cout << "1UL << j: " << 1UL << j << std::endl; + std::cout << "k: " << k << std::endl; + std::cout << "i, j: " << i << "," << j << std::endl; + //std::cout << "1UL << j: " << 1UL << j << std::endl; std::size_t xpq = k & (1UL << j); - std::cout << "k &(1UL << j)" << xpq << std::endl; + std::cout << "k &(1UL << j): " << xpq << std::endl; if (k & (1UL << j)) { - + std::cout << "hlist[i], plist[j]: " << hlist[i] << "," << plist[j] << std::endl; std::cout << "ncol * hlist[i] + plist[j]: " << ncol * hlist[i] + plist[j] << std::endl; rowsum += x[ncol * hlist[i] + plist[j]]; + std::cout << "rowsum: " << rowsum << std::endl; } } /* Update product of row sums. */ rowsumprod *= rowsum; + std::cout << "rowsumprod: " << rowsumprod << std::endl; } /* Add term multiplied by the parity of the characteristic vector. */ - std::cout << "rowsumprod: " << rowsumprod << std::endl; - std::cout << "(__builtin_popcountll(k) & 1) << 1: " << (__builtin_popcountll(k) & 1) << std::endl; + std::cout << "\n(__builtin_popcountll(k) & 1) << 1: " << (__builtin_popcountll(k) & 1) << std::endl; out += rowsumprod * (1 - ((__builtin_popcountll(k) & 1) << 1)); } From 4b2f55efef6954417fbe4c624293275c99f962f4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 24 Nov 2024 22:14:58 -0500 Subject: [PATCH 061/197] Add function call for nonsingletci.add_excited_dets --- pyci/fanci/fanci.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index d9c1ed5..e6e9e39 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -687,7 +687,10 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: if len(wfn) >= nproj: print("Breaking filling as len(wfn) >= nproj") break - pyci.add_excitations(wfn, nexc) + if isinstance(wfn, pyci.nonsingletci_wfn): + wfn.add_excited_dets(det, *connections) + else: + pyci.add_excitations(wfn, nexc) elif fill == "seniority": # Fill with determinants in increasing-seniority order @@ -712,6 +715,9 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: # Fill wfn with S space determinants print("\nAdding S space determinants") for det in wfn.to_det_array(nproj): - pyci.add_excitations(wfn, *connections, ref=det) + if isinstance(wfn, pyci.nonsingletci_wfn): + wfn.add_excited_dets(det, *connections, ref=det) + else: + pyci.add_excitations(wfn, *connections, ref=det) return wfn From aacd142649229150afee9bd05c5a931c16ef5d40 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 24 Nov 2024 22:17:21 -0500 Subject: [PATCH 062/197] Add print statements --- pyci/src/ap1rogen.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index b753138..0ec39fa 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,7 +14,7 @@ * along with PyCI. If not, see . */ #include - +#include namespace pyci { // See apig.cpp for reference @@ -90,7 +90,14 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { std::vector rdet(wfn_.nword); fill_hartreefock_det(wfn_.nocc, &rdet[0]); - std::cout << "After fill_hartreefock_det rdet:" << rdet << std::endl; + std::cout << "After fill_hartreefock_det rdet:" << std::endl; + + // Print the contents of rdet + for (const auto& val : rdet) { + std::cout << val << " "; + } + std::cout << std::endl; + const ulong *det = wfn_.det_ptr(idet); ulong word, hword, pword; // Initialize your class-specific variables here From 60b7d22515eca9399acd40f6f0694c90987ed3ec Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 26 Nov 2024 12:44:09 -0500 Subject: [PATCH 063/197] Revert "Add function call for nonsingletci.add_excited_dets" This reverts commit 9093d94922bef8313917b8d6d18704a1952bc1a0. --- pyci/fanci/fanci.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index e6e9e39..d9c1ed5 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -687,10 +687,7 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: if len(wfn) >= nproj: print("Breaking filling as len(wfn) >= nproj") break - if isinstance(wfn, pyci.nonsingletci_wfn): - wfn.add_excited_dets(det, *connections) - else: - pyci.add_excitations(wfn, nexc) + pyci.add_excitations(wfn, nexc) elif fill == "seniority": # Fill with determinants in increasing-seniority order @@ -715,9 +712,6 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: # Fill wfn with S space determinants print("\nAdding S space determinants") for det in wfn.to_det_array(nproj): - if isinstance(wfn, pyci.nonsingletci_wfn): - wfn.add_excited_dets(det, *connections, ref=det) - else: - pyci.add_excitations(wfn, *connections, ref=det) + pyci.add_excitations(wfn, *connections, ref=det) return wfn From c068a1820cca4977c1d23a6f83318cce3506b745 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 21:10:08 -0500 Subject: [PATCH 064/197] Revert "Revert "Add function call for nonsingletci.add_excited_dets"" This reverts commit 60b7d22515eca9399acd40f6f0694c90987ed3ec. --- pyci/fanci/fanci.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index d9c1ed5..e6e9e39 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -687,7 +687,10 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: if len(wfn) >= nproj: print("Breaking filling as len(wfn) >= nproj") break - pyci.add_excitations(wfn, nexc) + if isinstance(wfn, pyci.nonsingletci_wfn): + wfn.add_excited_dets(det, *connections) + else: + pyci.add_excitations(wfn, nexc) elif fill == "seniority": # Fill with determinants in increasing-seniority order @@ -712,6 +715,9 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: # Fill wfn with S space determinants print("\nAdding S space determinants") for det in wfn.to_det_array(nproj): - pyci.add_excitations(wfn, *connections, ref=det) + if isinstance(wfn, pyci.nonsingletci_wfn): + wfn.add_excited_dets(det, *connections, ref=det) + else: + pyci.add_excitations(wfn, *connections, ref=det) return wfn From bd4fe4524980961c3ec8537e51e833e6863f2ff0 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 21:20:57 -0500 Subject: [PATCH 065/197] update the logic for s>0 in add_excited_dets --- pyci/src/nonsingletci.cpp | 92 ++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 1b70e86..6ddd3d8 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -219,7 +219,6 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Iterate over possible (d,s) pairs: d pair excitations and s single excitations std::cout << "--------Handling excitation order >= 2--------" << std::endl; - std::vector>> pair_combinations; for (long d = 0; d <= std::min(e/2, num_pairs); ++d){ long num_singles = e - 2 * d; @@ -232,14 +231,14 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Generate pair combinations + std::vector>> pair_combinations; pair_combinations.push_back(generate_combinations(num_pairs, d)); // Process pair combinations for current d for (const auto& pair_comb : pair_combinations[d]) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - std::vector remaining_occ_indices; + std::vector used_virs; - for (long idx : pair_comb) { const auto& occ_pair = occ_pairs[idx]; const auto& vir_pair = vir_pairs[idx]; @@ -259,41 +258,74 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Determine remaining occupied indices + std::vector remaining_occ_indices; for (long i = 0; i < num_pairs; ++i) { if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { remaining_occ_indices.push_back(i); } } + + std::vector remaining_virs; + for (long i = 0; i < virs.size(); ++i) { + if (std::find(used_virtuals.begin(), used_virtuals.end(), virs[i]) == used_virtuals.end()) { + remaining_virs.push_back(virs[i]); + } + } // Process single combinations for current num_singles - auto single_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); - std::cout << "single_combinations: " << std::endl; + auto occ_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); + auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); + + // Print occ_combinations and vir_combinations for debugging + std::cout << "Available occ_pairs for singles: "; + for (const auto& idx : remaining_occ_indices) { + std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + } + std::cout << std::endl; - for (const auto& single_comb : single_combinations) { - // Do NOT reset det here; use the alredy existed det from pair excitations - AlignedVector temp_det(nword); - std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); - - // Apply single excitations - for (long idx : single_comb) { - long occ_idx = remaining_occ_indices[idx]; - long occ = occ_pairs[occ_idx].first; - - for (long vir : virs) { - if (std::find(used_virs.begin(), used_virs.end(), vir) != used_virs.end()) continue; - - // Apply single excitation - AlignedVector single_det(nword); - std::memcpy(&single_det[0], &temp_det[0], sizeof(ulong) * nword); - excite_det(occ, vir, &single_det[0]); - std::cout << "Exciting singles from " << occ << " to " << vir << std::endl; - // Add the fully excited determinant (pair + singles) - add_det(&temp_det[0]); - // Print determinant after single excitations - std::cout << "Determinant after single excitation" << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } + std::cout << "Available virs for singles: "; + for (const auto& vir : remaining_virs) { + std::cout << vir << " "; + } + std::cout << std::endl; + + std::cout << "Generated occ_combinations: " << std::endl; + for (const auto& occ_comb : occ_combinations) { + std::cout << "("; + for (const auto& occ_idx : occ_comb) { + std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; + } + std::cout << ")" << std::endl; + } + std::cout << "Generated vir_combinations: " << std::endl; + for (const auto& vir_comb : vir_combinations) { + std::cout << "("; + for (const auto& vir_idx : vir_comb) { + std::cout << remaining_virs[vir_idx] << " "; + } + std::cout << ")" << std::endl; + } + + + for (const auto& occ_comb : occ_combinations) { + for (const auto& vir_comb : vir_combinations) { + // Do NOT reset det here; use the alredy existed det from pair excitations + AlignedVector temp_det(nword); + std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); + + // Apply single excitations + for (long idx = 0; idx < num_singles; ++idx){ + long occ_idx = remaining_occ_indices[occ_comb[idx]]; + long occ = occ_pairs[occ_idx].first; + long vir = remaining_virs[vir_comb[idx]]; + excite_det(occ, vir, &temp_det[0]); + std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; + } + add_det(&temp_det[0]); + // Print determinant after single excitations + std::cout << "Determinant for single combination" << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << temp_det[k] << " "; } } From 60ca2ad24a9b0ba12429273905c26020a4aab50b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 27 Nov 2024 21:22:58 -0500 Subject: [PATCH 066/197] fix typos --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 6ddd3d8..d3297f5 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -267,7 +267,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::vector remaining_virs; for (long i = 0; i < virs.size(); ++i) { - if (std::find(used_virtuals.begin(), used_virtuals.end(), virs[i]) == used_virtuals.end()) { + if (std::find(used_virs.begin(), used_virs.end(), virs[i]) == used_virs.end()) { remaining_virs.push_back(virs[i]); } } From 18886587c8ce6450290f67ee13d039b26e44fe87 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 11:48:30 -0500 Subject: [PATCH 067/197] Revert to the orignial add_excitation calls in fill_wavefunction function --- pyci/fanci/fanci.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index e6e9e39..d9c1ed5 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -687,10 +687,7 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: if len(wfn) >= nproj: print("Breaking filling as len(wfn) >= nproj") break - if isinstance(wfn, pyci.nonsingletci_wfn): - wfn.add_excited_dets(det, *connections) - else: - pyci.add_excitations(wfn, nexc) + pyci.add_excitations(wfn, nexc) elif fill == "seniority": # Fill with determinants in increasing-seniority order @@ -715,9 +712,6 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: # Fill wfn with S space determinants print("\nAdding S space determinants") for det in wfn.to_det_array(nproj): - if isinstance(wfn, pyci.nonsingletci_wfn): - wfn.add_excited_dets(det, *connections, ref=det) - else: - pyci.add_excitations(wfn, *connections, ref=det) + pyci.add_excitations(wfn, *connections, ref=det) return wfn From 16edbbdbbaf31a78d6c41f05828a5486e833c253 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 11:51:55 -0500 Subject: [PATCH 068/197] Add print statements --- pyci/src/nonsingletci.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index d3297f5..dbd35a0 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -327,6 +327,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (int k = 0; k < nword; ++k) { std::cout << temp_det[k] << " "; } + std::cout << std::endl; } } @@ -338,6 +339,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (int k = 0; k < nword; ++k) { std::cout << det[k] << " "; } + std::cout << std::endl; } } } From 79ec98c2a566e66e20979fe8015f8a03e72f98f5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 11:58:06 -0500 Subject: [PATCH 069/197] Add print statements --- pyci/src/nonsingletci.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index dbd35a0..9afe7ec 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -233,6 +233,14 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Generate pair combinations std::vector>> pair_combinations; pair_combinations.push_back(generate_combinations(num_pairs, d)); + std::cout << "Generated pair_combinations: " << std::endl; + for (const auto& pair_comb : pair_combinations[0]) { + std::cout << "("; + for (const auto& idx : pair_comb) { + std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + } + std::cout << ")" << std::endl; + } // Process pair combinations for current d for (const auto& pair_comb : pair_combinations[d]) { @@ -264,6 +272,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ remaining_occ_indices.push_back(i); } } + std::cout << "Remaining occ_indices: "; + for (const auto& idx : remaining_occ_indices) { + std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + } + std::cout << std::endl; std::vector remaining_virs; for (long i = 0; i < virs.size(); ++i) { @@ -271,7 +284,12 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ remaining_virs.push_back(virs[i]); } } - + std::cout << "Remaining virs: "; + for (const auto& vir : remaining_virs) { + std::cout << vir << " "; + } + std::cout << std::endl; + // Process single combinations for current num_singles auto occ_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); From 778b25b761b4379c6b480877144708be8ff377e5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 12:08:07 -0500 Subject: [PATCH 070/197] Try an input with *2 in occ_combinations for singles in add_excited_dets --- pyci/src/nonsingletci.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 9afe7ec..d41f321 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -289,9 +289,9 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << vir << " "; } std::cout << std::endl; - + // Process single combinations for current num_singles - auto occ_combinations = generate_combinations(remaining_occ_indices.size(), num_singles); + auto occ_combinations = generate_combinations(remaining_occ_indices.size()*2, num_singles); auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); // Print occ_combinations and vir_combinations for debugging From 86828d9ba4ca2c0c22f18b425193a68b5fa12f34 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 12:22:05 -0500 Subject: [PATCH 071/197] Add generate_cartesian_product function to form occ_pairs for sen-o singles --- pyci/include/pyci.h | 6 ++- pyci/src/nonsingletci.cpp | 105 +++++++++++++++++++++++++++++--------- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index b2252b3..7309117 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -653,10 +653,12 @@ struct NonSingletCI final : public GenCIWfn { NonSingletCI(const long, const long, const long, const Array); + std::vector> generate_combinations(long, long); + + std::vector> generate_cartesian_product(const std::vector>&, long); + void fill_hartreefock_det(long, long, ulong *); - std::vector> generate_combinations(long, long); - void add_excited_dets(const ulong *, const long); long py_add_excited_dets(const long, const pybind11::object); diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index d41f321..2e3715b 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -54,10 +54,49 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar reinterpret_cast(array.request().ptr)) { } +// Function to generate cartesian product from a vector of pairs +// In our case: this function is used to generate all possible combinations of +// occupied orbitals to excite from for singles given pair of occupied orbitals in ref det +std::vector> NonSingletCI::generate_cartesian_product( + const std::vector>& pairs, long k) { + std::vector> result; -// Function to generate combinations -std::vector> pyci::NonSingletCI::generate_combinations(long n, long k) { + long num_pairs = pairs.size(); + if (k > num_pairs) return result; + std::vector> temp_combinations = {{}}; + + + for (const auto& pair: pairs) { + std::vector> new_result; + + // For each combination in the current result, + // extend it with elements of the pair + for (const auto& combination: result) { + if (combination.size() > NonSingletCI::generate_combinations(long n, long k) { std::vector> combinations; + if (k > n) return combinations; std::vector indices(n); @@ -235,15 +274,13 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ pair_combinations.push_back(generate_combinations(num_pairs, d)); std::cout << "Generated pair_combinations: " << std::endl; for (const auto& pair_comb : pair_combinations[0]) { - std::cout << "("; for (const auto& idx : pair_comb) { std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - } - std::cout << ")" << std::endl; + } } // Process pair combinations for current d - for (const auto& pair_comb : pair_combinations[d]) { + for (const auto& pair_comb : pair_combinations[0]) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); std::vector used_virs; @@ -265,16 +302,31 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } } - // Determine remaining occupied indices - std::vector remaining_occ_indices; + // // Determine remaining occupied indices + // std::vector remaining_occ_indices; + // for (long i = 0; i < num_pairs; ++i) { + // if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { + // remaining_occ_indices.push_back(i); + // } + // } + // std::cout << "Remaining occ_indices: "; + // for (const auto& idx : remaining_occ_indices) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // std::cout << std::endl; + + // Determine remaining occupied pairs + std::vector> remaining_occ_pairs; for (long i = 0; i < num_pairs; ++i) { if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - remaining_occ_indices.push_back(i); + remaining_occ_pairs.push_back(occ_pairs[i]); } } - std::cout << "Remaining occ_indices: "; - for (const auto& idx : remaining_occ_indices) { - std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + + //Print remaining occ_pairs for debugging + std::cout << "Remaining occ_pairs: "; + for (const auto& occ_pair : remaining_occ_pairs) { + std::cout << "(" << occ_pair.first << ", " << occ_pair.second << ") "; } std::cout << std::endl; @@ -291,15 +343,15 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << std::endl; // Process single combinations for current num_singles - auto occ_combinations = generate_combinations(remaining_occ_indices.size()*2, num_singles); + auto occ_combinations = generate_cartesian_product(remaining_occ_pairs, num_singles); auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); // Print occ_combinations and vir_combinations for debugging - std::cout << "Available occ_pairs for singles: "; - for (const auto& idx : remaining_occ_indices) { - std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - } - std::cout << std::endl; + // std::cout << "Available occ_pairs for singles: "; + // for (const auto& idx : remaining_occ_indices) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // std::cout << std::endl; std::cout << "Available virs for singles: "; for (const auto& vir : remaining_virs) { @@ -307,14 +359,22 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; + // std::cout << "Generated occ_combinations: " << std::endl; + // for (const auto& occ_comb : occ_combinations) { + // std::cout << "("; + // for (const auto& occ_idx : occ_comb) { + // std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; + // } + // std::cout << ")" << std::endl; + // } + std::cout << "Generated occ_combinations: " << std::endl; for (const auto& occ_comb : occ_combinations) { - std::cout << "("; for (const auto& occ_idx : occ_comb) { - std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; + std::cout << "(" << occ_pairs[occ_idx].first << ", " << occ_pairs[occ_idx].second << ") "; } - std::cout << ")" << std::endl; } + std::cout << "Generated vir_combinations: " << std::endl; for (const auto& vir_comb : vir_combinations) { std::cout << "("; @@ -333,8 +393,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Apply single excitations for (long idx = 0; idx < num_singles; ++idx){ - long occ_idx = remaining_occ_indices[occ_comb[idx]]; - long occ = occ_pairs[occ_idx].first; + long occ = occ_comb[idx]; long vir = remaining_virs[vir_comb[idx]]; excite_det(occ, vir, &temp_det[0]); std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; From 12f7213c8204dfdc4e337874e0319c2ebec17884 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 13:34:31 -0500 Subject: [PATCH 072/197] Add print statements --- pyci/src/nonsingletci.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 2e3715b..b651ebf 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -72,7 +72,7 @@ std::vector> NonSingletCI::generate_cartesian_product( // For each combination in the current result, // extend it with elements of the pair for (const auto& combination: result) { - if (combination.size() > NonSingletCI::generate_cartesian_product( } // Move the new combination into the result temp_combinations = std::move(new_result); - } + std::cout << "temp_combinations: "; + // Filter out combinations that are not of size k for (const auto& combination: temp_combinations) { if (combination.size() == k) { @@ -90,6 +91,9 @@ std::vector> NonSingletCI::generate_cartesian_product( } } + // Debug output to ensure combinations are being generated + std::cout << "Generated " << result.size() << " combinations" << std::endl; + return result; } @@ -278,6 +282,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; } } + std::cout << std::endl; // Process pair combinations for current d for (const auto& pair_comb : pair_combinations[0]) { @@ -300,6 +305,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (int k = 0; k < nword; ++k) { std::cout << det[k] << " "; } + std::cout << std::endl; } // // Determine remaining occupied indices @@ -370,9 +376,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Generated occ_combinations: " << std::endl; for (const auto& occ_comb : occ_combinations) { - for (const auto& occ_idx : occ_comb) { - std::cout << "(" << occ_pairs[occ_idx].first << ", " << occ_pairs[occ_idx].second << ") "; + for (const auto& elem: occ_comb) { + std::cout << "(" << elem << ") "; } + std::cout << std::endl; } std::cout << "Generated vir_combinations: " << std::endl; From bb5f1f054cb1d57c623740f0f9a06c3ca8348343 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 28 Nov 2024 14:03:46 -0500 Subject: [PATCH 073/197] fix typos --- pyci/src/nonsingletci.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index b651ebf..2aab6b7 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -60,6 +60,9 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar std::vector> NonSingletCI::generate_cartesian_product( const std::vector>& pairs, long k) { std::vector> result; + std::cout << "Inside nonsingletci/generate_cartesian_product" << std::endl; + std::cout << "pairs.size(): " << pairs.size() << std::endl; + std::cout << "k: " << k << std::endl; long num_pairs = pairs.size(); if (k > num_pairs) return result; @@ -71,7 +74,7 @@ std::vector> NonSingletCI::generate_cartesian_product( // For each combination in the current result, // extend it with elements of the pair - for (const auto& combination: result) { + for (const auto& combination: temp_combinations) { if (combination.size() < k){ for (auto elem : {pair.first, pair.second}) { auto new_combination = combination; @@ -83,7 +86,7 @@ std::vector> NonSingletCI::generate_cartesian_product( // Move the new combination into the result temp_combinations = std::move(new_result); std::cout << "temp_combinations: "; - + } // Filter out combinations that are not of size k for (const auto& combination: temp_combinations) { if (combination.size() == k) { @@ -97,6 +100,7 @@ std::vector> NonSingletCI::generate_cartesian_product( return result; } + // Function to generate combinations, based on indices std::vector> NonSingletCI::generate_combinations(long n, long k) { std::vector> combinations; From 1abce911a695ee9939200efa67271642227541c4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sat, 30 Nov 2024 14:24:44 -0500 Subject: [PATCH 074/197] Fix double excitation to consider all possible occ_pair to vir_pair combinations --- pyci/src/nonsingletci.cpp | 298 ++++++++++++++++++++------------------ 1 file changed, 156 insertions(+), 142 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 2aab6b7..73a5540 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -64,8 +64,8 @@ std::vector> NonSingletCI::generate_cartesian_product( std::cout << "pairs.size(): " << pairs.size() << std::endl; std::cout << "k: " << k << std::endl; - long num_pairs = pairs.size(); - if (k > num_pairs) return result; + long nocc_pairs = pairs.size(); + if (k > nocc_pairs) return result; std::vector> temp_combinations = {{}}; @@ -260,180 +260,194 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Handle excitation orders >= 2 - long num_pairs = occ_pairs.size(); - std::cout << "num_pairs: " << num_pairs << std::endl; + long nocc_pairs = occ_pairs.size(); + long nvir_pairs = vir_pairs.size(); + std::cout << "nocc_pairs: " << nocc_pairs << std::endl; if (e >= 2) { // Iterate over possible (d,s) pairs: d pair excitations and s single excitations std::cout << "--------Handling excitation order >= 2--------" << std::endl; - for (long d = 0; d <= std::min(e/2, num_pairs); ++d){ + for (long d = 0; d <= std::min(e/2, nocc_pairs); ++d){ long num_singles = e - 2 * d; std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; // Not enough pairs for singles - if (num_singles > (num_pairs - d)) { + if (num_singles > (nocc_pairs - d)) { std::cout << "Not enough pairs for singles" << std::endl; continue; } - // Generate pair combinations - std::vector>> pair_combinations; - pair_combinations.push_back(generate_combinations(num_pairs, d)); - std::cout << "Generated pair_combinations: " << std::endl; - for (const auto& pair_comb : pair_combinations[0]) { - for (const auto& idx : pair_comb) { + // Generate occ pair combinations + std::vector>> opair_combinations; + opair_combinations.push_back(generate_combinations(nocc_pairs, d)); + std::cout << "Generated opair_combinations: " << std::endl; + for (const auto& opair_comb : opair_combinations[0]) { + for (const auto& idx : opair_comb) { std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; } } std::cout << std::endl; + std::vector>> vpair_combinations; + vpair_combinations.push_back(generate_combinations(nvir_pairs, d)); + std::cout << "Generated vpair_combinations: " << std::endl; + for (const auto& pair_comb : vpair_combinations[0]) { + for (const auto& idx : pair_comb) { + std::cout << "(" << vir_pairs[idx].first << ", " << vir_pairs[idx].second << ") "; + } + } + std::cout << std::endl; + // Process pair combinations for current d - for (const auto& pair_comb : pair_combinations[0]) { - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - - std::vector used_virs; - for (long idx : pair_comb) { - const auto& occ_pair = occ_pairs[idx]; - const auto& vir_pair = vir_pairs[idx]; + for (const auto& opair_comb : opair_combinations[0]) { + for (const auto& vpair_comb : vpair_combinations[0]) { + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + + + std::vector used_virs; + for (long idx = 0; idx < d; ++idx) { + const auto& occ_pair = occ_pairs[opair_comb[idx]]; + const auto& vir_pair = vir_pairs[vpair_comb[idx]]; - excite_det(occ_pair.first, vir_pair.first, &det[0]); - excite_det(occ_pair.second, vir_pair.second, &det[0]); + excite_det(occ_pair.first, vir_pair.first, &det[0]); + excite_det(occ_pair.second, vir_pair.second, &det[0]); - used_virs.push_back(vir_pair.first); - used_virs.push_back(vir_pair.second); - - std::cout << "Determinant after pair excitation of" << std::endl; - std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; - std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; + used_virs.push_back(vir_pair.first); + used_virs.push_back(vir_pair.second); + + std::cout << "Determinant after pair excitation of" << std::endl; + std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; + std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << std::endl; } - std::cout << std::endl; - } - // // Determine remaining occupied indices - // std::vector remaining_occ_indices; - // for (long i = 0; i < num_pairs; ++i) { - // if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - // remaining_occ_indices.push_back(i); - // } - // } - // std::cout << "Remaining occ_indices: "; - // for (const auto& idx : remaining_occ_indices) { - // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - // } - // std::cout << std::endl; - - // Determine remaining occupied pairs - std::vector> remaining_occ_pairs; - for (long i = 0; i < num_pairs; ++i) { - if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { - remaining_occ_pairs.push_back(occ_pairs[i]); - } - } + // // Determine remaining occupied indices + // std::vector remaining_occ_indices; + // for (long i = 0; i < nocc_pairs; ++i) { + // if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { + // remaining_occ_indices.push_back(i); + // } + // } + // std::cout << "Remaining occ_indices: "; + // for (const auto& idx : remaining_occ_indices) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // std::cout << std::endl; + if (num_singles > 0) { + // Determine remaining occupied pairs + std::vector> remaining_occ_pairs; + for (long i = 0; i < nocc_pairs; ++i) { + if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { + remaining_occ_pairs.push_back(occ_pairs[i]); + } + } - //Print remaining occ_pairs for debugging - std::cout << "Remaining occ_pairs: "; - for (const auto& occ_pair : remaining_occ_pairs) { - std::cout << "(" << occ_pair.first << ", " << occ_pair.second << ") "; - } - std::cout << std::endl; + //Print remaining occ_pairs for debugging + std::cout << "Remaining occ_pairs: "; + for (const auto& occ_pair : remaining_occ_pairs) { + std::cout << "(" << occ_pair.first << ", " << occ_pair.second << ") "; + } + std::cout << std::endl; - std::vector remaining_virs; - for (long i = 0; i < virs.size(); ++i) { - if (std::find(used_virs.begin(), used_virs.end(), virs[i]) == used_virs.end()) { - remaining_virs.push_back(virs[i]); - } - } - std::cout << "Remaining virs: "; - for (const auto& vir : remaining_virs) { - std::cout << vir << " "; - } - std::cout << std::endl; + std::vector remaining_virs; + for (long i = 0; i < virs.size(); ++i) { + if (std::find(used_virs.begin(), used_virs.end(), virs[i]) == used_virs.end()) { + remaining_virs.push_back(virs[i]); + } + } + std::cout << "Remaining virs: "; + for (const auto& vir : remaining_virs) { + std::cout << vir << " "; + } + std::cout << std::endl; - // Process single combinations for current num_singles - auto occ_combinations = generate_cartesian_product(remaining_occ_pairs, num_singles); - auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); - - // Print occ_combinations and vir_combinations for debugging - // std::cout << "Available occ_pairs for singles: "; - // for (const auto& idx : remaining_occ_indices) { - // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - // } - // std::cout << std::endl; - - std::cout << "Available virs for singles: "; - for (const auto& vir : remaining_virs) { - std::cout << vir << " "; - } - std::cout << std::endl; + // Process single combinations for current num_singles + auto occ_combinations = generate_cartesian_product(remaining_occ_pairs, num_singles); + auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); + + // Print occ_combinations and vir_combinations for debugging + // std::cout << "Available occ_pairs for singles: "; + // for (const auto& idx : remaining_occ_indices) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // std::cout << std::endl; + + std::cout << "Available virs for singles: "; + for (const auto& vir : remaining_virs) { + std::cout << vir << " "; + } + std::cout << std::endl; - // std::cout << "Generated occ_combinations: " << std::endl; - // for (const auto& occ_comb : occ_combinations) { - // std::cout << "("; - // for (const auto& occ_idx : occ_comb) { - // std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; - // } - // std::cout << ")" << std::endl; - // } - - std::cout << "Generated occ_combinations: " << std::endl; - for (const auto& occ_comb : occ_combinations) { - for (const auto& elem: occ_comb) { - std::cout << "(" << elem << ") "; - } - std::cout << std::endl; - } - - std::cout << "Generated vir_combinations: " << std::endl; - for (const auto& vir_comb : vir_combinations) { - std::cout << "("; - for (const auto& vir_idx : vir_comb) { - std::cout << remaining_virs[vir_idx] << " "; - } - std::cout << ")" << std::endl; - } + // std::cout << "Generated occ_combinations: " << std::endl; + // for (const auto& occ_comb : occ_combinations) { + // std::cout << "("; + // for (const auto& occ_idx : occ_comb) { + // std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; + // } + // std::cout << ")" << std::endl; + // } + + std::cout << "Generated occ_combinations: " << std::endl; + for (const auto& occ_comb : occ_combinations) { + for (const auto& elem: occ_comb) { + std::cout << "(" << elem << ") "; + } + std::cout << std::endl; + } + + std::cout << "Generated vir_combinations: " << std::endl; + for (const auto& vir_comb : vir_combinations) { + std::cout << "("; + for (const auto& vir_idx : vir_comb) { + std::cout << remaining_virs[vir_idx] << " "; + } + std::cout << ")" << std::endl; + } - - for (const auto& occ_comb : occ_combinations) { - for (const auto& vir_comb : vir_combinations) { - // Do NOT reset det here; use the alredy existed det from pair excitations - AlignedVector temp_det(nword); - std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); - // Apply single excitations - for (long idx = 0; idx < num_singles; ++idx){ - long occ = occ_comb[idx]; - long vir = remaining_virs[vir_comb[idx]]; - excite_det(occ, vir, &temp_det[0]); - std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; + for (const auto& occ_comb : occ_combinations) { + for (const auto& vir_comb : vir_combinations) { + // Do NOT reset det here; use the alredy existed det from pair excitations + AlignedVector temp_det(nword); + std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); + + // Apply single excitations + for (long idx = 0; idx < num_singles; ++idx){ + long occ = occ_comb[idx]; + long vir = remaining_virs[vir_comb[idx]]; + excite_det(occ, vir, &temp_det[0]); + std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; + } + add_det(&temp_det[0]); + // Print determinant after single excitations + std::cout << "Determinant for single combination" << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << temp_det[k] << " "; + } + std::cout << std::endl; + } + } - add_det(&temp_det[0]); + } + else if (num_singles == 0){ + // If num_singles == 0, directly add determinant after pair excitations + add_det(&det[0]); // Print determinant after single excitations - std::cout << "Determinant for single combination" << std::endl; + std::cout << "Determinant for s=0" << std::endl; for (int k = 0; k < nword; ++k) { - std::cout << temp_det[k] << " "; + std::cout << det[k] << " "; } std::cout << std::endl; } - - } - if (num_singles == 0){ - // If num_singles == 0, directly add determinant after pair excitations - add_det(&det[0]); - // Print determinant after single excitations - std::cout << "Determinant for s=0" << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - } + } } } } - } @@ -492,23 +506,23 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re // // // Generate all combinations of d pairs -// std::vector> pair_combinations; +// std::vector> opair_combinations; // std::vector pair_indices(occ_pairs.size()); // std::iota(pair_indices.begin(), pair_indices.end(), 0); // do { // std::vector combination(pair_indices.begin(), pair_indices.begin() + d); -// pair_combinations.push_back(combination); +// opair_combinations.push_back(combination); // } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); // // Process each combination of d pairs -// for (const auto& pair_comb: pair_combinations) { +// for (const auto& opair_comb: opair_combinations) { // std::vector> used_occ_pairs; // std::vector used_virtuals; // // Apply pair excitations // std::memcpy(&det[0], rdet, sizeof(ulong) * nword); -// for (long idx : pair_comb) { +// for (long idx : opair_comb) { // const auto& occ_pair = occ_pairs[idx]; // const auto& vir_pair = vir_pairs[idx]; @@ -523,7 +537,7 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re // //Exclude used pairs and virtual orbitals // std::vector remaining_occ_indices; // for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { -// if (std::find(pair_comb.begin(), pair_comb.end(), i) == pair_comb.end()) { +// if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { // remaining_occ_indices.push_back(static_cast(i)); // } // } From e0f188789c99ec08901717b7eadb718640959db2 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 13:19:22 -0500 Subject: [PATCH 075/197] Cleanup the occs_up, _dn, virs_up, _dn vector code --- pyci/src/nonsingletci.cpp | 49 ++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 73a5540..193211d 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -54,6 +54,7 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar reinterpret_cast(array.request().ptr)) { } + // Function to generate cartesian product from a vector of pairs // In our case: this function is used to generate all possible combinations of // occupied orbitals to excite from for singles given pair of occupied orbitals in ref det @@ -130,13 +131,14 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ AlignedVector det(nword); AlignedVector occs(nocc); - AlignedVector occs_up(occs.size()); - AlignedVector occs_dn(occs.size()); - AlignedVector> occ_pairs; - AlignedVector virs(nbasis - nocc); - AlignedVector virs_up(virs.size()); - AlignedVector virs_dn(virs.size()); + AlignedVector occs_up, occs_dn, virs_up, virs_dn; + occs_up.reserve(occs.size()); + occs_dn.reserve(occs.size()); + virs_up.reserve(occs.size()); + virs_dn.reserve(occs.size()); + + AlignedVector> occ_pairs; AlignedVector> vir_pairs; AlignedVector occinds(e + 1); @@ -144,7 +146,20 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ fill_occs(nword, rdet, &occs[0]); fill_virs(nword, nbasis, rdet, &virs[0]); - int up_idx = 0, dn_idx = 0; + for (int i : occs) { + (i < nbasis / 2 ? occs_up : occs_dn).push_back(i); + } + + for (int a : virs) { + (a < nbasis / 2 ? virs_up : virs_dn).push_back(a); + } + + // Efficient resizing + occs_up.shrink_to_fit(); + occs_dn.shrink_to_fit(); + virs_up.shrink_to_fit(); + virs_dn.shrink_to_fit(); + std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; std::cout << "e: " << e << std::endl; @@ -161,15 +176,6 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; - // Generate list of up & dn indices for ocs & virs - for (int i : occs) { - if (i < nbasis/2) occs_up[up_idx++] = i; - else occs_dn[dn_idx++] = i; - } - - // Resize vectors to actual size - occs_up.resize(up_idx); - occs_dn.resize(dn_idx); std::cout << "occs_up: "; for (const auto& elem : occs_up) { @@ -183,15 +189,6 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; - up_idx = 0; - dn_idx = 0; - for (int a : virs) { - if (a < nbasis/2) virs_up[up_idx++] = a; - else virs_dn[dn_idx++] = a; - } - // Resize vectors to actual size - virs_up.resize(up_idx); - virs_dn.resize(dn_idx); std::cout << "virs_up: "; for (const auto& elem : virs_up) { @@ -567,4 +564,4 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re // } // add_det(&det[0]); // } -// } \ No newline at end of file +// } From 78a01b784940a5aa962c41e32045e98ab1f7458b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 14:21:06 -0500 Subject: [PATCH 076/197] Add is_hf_det bool flag, define and declare structure in pyci.h to store det & indices of params corresponding to the excitations wrt hf --- pyci/include/pyci.h | 11 +++++++++++ pyci/src/nonsingletci.cpp | 3 +++ 2 files changed, 14 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 7309117..0cdf04c 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -613,6 +613,13 @@ struct GenCIWfn : public OneSpinWfn { GenCIWfn(const long, const long, const long, const Array); }; +// Define structure to store det and excitation details +struct DetExcParamIndx { + AlignedVector det; + std::vector pair_inds; + std::vector single_inds; +}; + struct NonSingletCI final : public GenCIWfn { public: using Wfn::maxrank_dn; @@ -631,6 +638,10 @@ struct NonSingletCI final : public GenCIWfn { protected: using Wfn::dets; using Wfn::dict; + std::vector det_exc_param_indx; + +private: + bool is_hf_det; public: NonSingletCI(const NonSingletCI &); diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 193211d..882c291 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -492,8 +492,11 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re v_ref.resize(nword); ptr = &v_ref[0]; fill_hartreefock_det(nbasis,nocc, ptr); + + is_hf_det = true; } else ptr = reinterpret_cast(ref.cast>().request().ptr); + is_hf_det = false; long ndet_old = ndet; add_excited_dets(ptr, exc); return ndet - ndet_old; From 52b255e2405db59357aceb0a57bb92928d5c3f7d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 15:23:30 -0500 Subject: [PATCH 077/197] Add print functions to avoid lengthy repetative lines --- pyci/include/pyci.h | 4 + pyci/src/nonsingletci.cpp | 172 ++++++++++++++++++++------------------ 2 files changed, 94 insertions(+), 82 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 0cdf04c..8f54c93 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -640,6 +640,10 @@ struct NonSingletCI final : public GenCIWfn { using Wfn::dict; std::vector det_exc_param_indx; + template + void print_vector(const std::string&, const AlignedVector& ); + void print_pairs(const std::string&, const AlignedVector>&); + private: bool is_hf_det; diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 882c291..c12ce2c 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -125,6 +125,22 @@ std::vector> NonSingletCI::generate_combinations(long n, long return combinations; } +template +void NonSingletCI::print_vector(const std::string& name, const AlignedVector& vec) { + std::cout << name << ": "; + for (const auto& elem : vec) { + std::cout << elem << " "; + } + std::cout << std::endl; +} +void NonSingletCI::print_pairs(const std::string& label, const AlignedVector>& pairs) { + std::cout << label << ": "; + for (const auto& elem : pairs) { + std::cout << elem.first << " " << elem.second << " "; + } + std::cout << std::endl; +} + void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Inside nonsingletci/add_excited_dets" << std::endl; //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); @@ -140,6 +156,8 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ AlignedVector> occ_pairs; AlignedVector> vir_pairs; + occ_pairs.reserve(occs_up.size()); + vir_pairs.reserve(virs.size()); AlignedVector occinds(e + 1); AlignedVector virinds(e + 1); @@ -164,67 +182,32 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; std::cout << "e: " << e << std::endl; std::cout << "rdet: " << *rdet << std::endl; - std::cout << "occs: "; - for (const auto& elem : occs) { - std::cout << elem << " "; - } - std::cout << std::endl; - - std::cout << "virs: "; - for (const auto& elem : virs) { - std::cout << elem << " "; - } - std::cout << std::endl; - - - std::cout << "occs_up: "; - for (const auto& elem : occs_up) { - std::cout << elem << " "; - } - std::cout << std::endl; - - std::cout << "occs_dn: "; - for (const auto& elem : occs_dn) { - std::cout << elem << " "; - } - std::cout << std::endl; - - - std::cout << "virs_up: "; - for (const auto& elem : virs_up) { - std::cout << elem << " "; - } - std::cout << std::endl; - std::cout << "virs_dn: "; - for (const auto& elem : virs_dn) { - std::cout << elem << " "; - } - std::cout << std::endl; + print_vector("occs", occs); + print_vector("virs", virs); + print_vector("occs_up", occs_up); + print_vector("occs_dn", occs_dn); + print_vector("virs_up", virs_up); + print_vector("virs_dn", virs_dn); // Create an unordered set for fast lookup of occupied down-orbitals std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); - // Generate occ_pairs + std::unordered_set virs_set(virs.begin(), virs.end()); + + // Generate occ_pairs and vir_pairs for (int i : occs_up) { if (occ_dn_set.find(i + nbasis/2) != occ_dn_set.end()) { occ_pairs.push_back({i, i + nbasis/2}); } } - std::cout << "occ_pairs: "; - for (const auto& elem : occ_pairs) { - std::cout << elem.first << " " << elem.second << std::endl; - } - // Create an unordered set for fast looup of virtual orbitals - std::unordered_set virs_set(virs.begin(), virs.end()); - // form virtual pairs + for (int a : virs) { if (virs_set.find(a + nbasis/2) != virs_set.end()) { vir_pairs.push_back({a, a + nbasis/2}); } } - std::cout << "vir_pairs: "; - for (const auto& elem : vir_pairs) { - std::cout << elem.first << " " << elem.second << std::endl; - } + + print_pairs("occ_pairs", occ_pairs); + print_pairs("vir_pairs", vir_pairs); // Handle excitation order 0 @@ -342,13 +325,8 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ remaining_occ_pairs.push_back(occ_pairs[i]); } } + print_pairs("remaining_occ_pairs", remaining_occ_pairs); - //Print remaining occ_pairs for debugging - std::cout << "Remaining occ_pairs: "; - for (const auto& occ_pair : remaining_occ_pairs) { - std::cout << "(" << occ_pair.first << ", " << occ_pair.second << ") "; - } - std::cout << std::endl; std::vector remaining_virs; for (long i = 0; i < virs.size(); ++i) { @@ -356,37 +334,12 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ remaining_virs.push_back(virs[i]); } } - std::cout << "Remaining virs: "; - for (const auto& vir : remaining_virs) { - std::cout << vir << " "; - } - std::cout << std::endl; + print_vector("remaining_virs", remaining_virs); + // Process single combinations for current num_singles auto occ_combinations = generate_cartesian_product(remaining_occ_pairs, num_singles); auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); - - // Print occ_combinations and vir_combinations for debugging - // std::cout << "Available occ_pairs for singles: "; - // for (const auto& idx : remaining_occ_indices) { - // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - // } - // std::cout << std::endl; - - std::cout << "Available virs for singles: "; - for (const auto& vir : remaining_virs) { - std::cout << vir << " "; - } - std::cout << std::endl; - - // std::cout << "Generated occ_combinations: " << std::endl; - // for (const auto& occ_comb : occ_combinations) { - // std::cout << "("; - // for (const auto& occ_idx : occ_comb) { - // std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; - // } - // std::cout << ")" << std::endl; - // } std::cout << "Generated occ_combinations: " << std::endl; for (const auto& occ_comb : occ_combinations) { @@ -494,9 +447,10 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re fill_hartreefock_det(nbasis,nocc, ptr); is_hf_det = true; - } else + } else { ptr = reinterpret_cast(ref.cast>().request().ptr); is_hf_det = false; + } long ndet_old = ndet; add_excited_dets(ptr, exc); return ndet - ndet_old; @@ -568,3 +522,57 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re // add_det(&det[0]); // } // } + +// for (const auto& elem : occs) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + + // std::cout << "virs: "; + // for (const auto& elem : virs) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + + + // std::cout << "occs_up: "; + // for (const auto& elem : occs_up) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + + // std::cout << "occs_dn: "; + // for (const auto& elem : occs_dn) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + + + // std::cout << "virs_up: "; + // for (const auto& elem : virs_up) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + // std::cout << "virs_dn: "; + // for (const auto& elem : virs_dn) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + + + + // std::cout << "Generated occ_combinations: " << std::endl; + // for (const auto& occ_comb : occ_combinations) { + // std::cout << "("; + // for (const auto& occ_idx : occ_comb) { + // std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; + // } + // std::cout << ")" << std::endl; + // } + + // Print occ_combinations and vir_combinations for debugging + // std::cout << "Available occ_pairs for singles: "; + // for (const auto& idx : remaining_occ_indices) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // std::cout << std::endl; \ No newline at end of file From 0917ac7b65285dd74a10002dd74753cc27ddc873 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 15:37:22 -0500 Subject: [PATCH 078/197] Change vector type to AlignedVector for remaining_occ_pairs , remaining_virs --- pyci/src/nonsingletci.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index c12ce2c..1cf99ad 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -305,21 +305,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << std::endl; } - // // Determine remaining occupied indices - // std::vector remaining_occ_indices; - // for (long i = 0; i < nocc_pairs; ++i) { - // if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { - // remaining_occ_indices.push_back(i); - // } - // } - // std::cout << "Remaining occ_indices: "; - // for (const auto& idx : remaining_occ_indices) { - // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - // } - // std::cout << std::endl; + if (num_singles > 0) { // Determine remaining occupied pairs - std::vector> remaining_occ_pairs; + AlignedVector> remaining_occ_pairs; for (long i = 0; i < nocc_pairs; ++i) { if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { remaining_occ_pairs.push_back(occ_pairs[i]); @@ -328,7 +317,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ print_pairs("remaining_occ_pairs", remaining_occ_pairs); - std::vector remaining_virs; + AlignedVector remaining_virs; for (long i = 0; i < virs.size(); ++i) { if (std::find(used_virs.begin(), used_virs.end(), virs[i]) == used_virs.end()) { remaining_virs.push_back(virs[i]); @@ -575,4 +564,18 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re // for (const auto& idx : remaining_occ_indices) { // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; // } - // std::cout << std::endl; \ No newline at end of file + // std::cout << std::endl; + + + // // Determine remaining occupied indices + // std::vector remaining_occ_indices; + // for (long i = 0; i < nocc_pairs; ++i) { + // if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { + // remaining_occ_indices.push_back(i); + // } + // } + // std::cout << "Remaining occ_indices: "; + // for (const auto& idx : remaining_occ_indices) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // std::cout << std::endl; \ No newline at end of file From d3444c5f4eb292282e5251f66496865e9d3a05f5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 15:39:07 -0500 Subject: [PATCH 079/197] Change vector type to AlignedVector for generate_cartesian_product --- pyci/include/pyci.h | 2 +- pyci/src/nonsingletci.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 8f54c93..9c1594c 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -670,7 +670,7 @@ struct NonSingletCI final : public GenCIWfn { std::vector> generate_combinations(long, long); - std::vector> generate_cartesian_product(const std::vector>&, long); + std::vector> generate_cartesian_product(const AlignedVector>&, long); void fill_hartreefock_det(long, long, ulong *); diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 1cf99ad..c9d9c6b 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -59,7 +59,7 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar // In our case: this function is used to generate all possible combinations of // occupied orbitals to excite from for singles given pair of occupied orbitals in ref det std::vector> NonSingletCI::generate_cartesian_product( - const std::vector>& pairs, long k) { + const AlignedVector>& pairs, long k) { std::vector> result; std::cout << "Inside nonsingletci/generate_cartesian_product" << std::endl; std::cout << "pairs.size(): " << pairs.size() << std::endl; From 6b8301fb5c5aa2c517507bdcb983449880b96d65 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 16:09:41 -0500 Subject: [PATCH 080/197] Store dets & indices for params corresponding to excitations in case exc>=2 --- pyci/src/nonsingletci.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index c9d9c6b..cb33df9 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -232,8 +232,16 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << det[k] << " "; } std::cout << std::endl; - } + + // Structure to store determinant and indices of params + //corresponding to the pair-excitations & single-excitations + if (is_hf_det) { + DetExcParamIndx det_exc_param; + std::memcpy(&det_exc_param.det[0], &det[0], sizeof(ulong) * nword); + det_exc_param.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); + } std::cout << std::endl; + } } std::cout << std::endl; return ; @@ -283,6 +291,9 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (const auto& opair_comb : opair_combinations[0]) { for (const auto& vpair_comb : vpair_combinations[0]) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + if (is_hf_det) { + DetExcParamIndx det_exc; + } std::vector used_virs; @@ -303,6 +314,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << det[k] << " "; } std::cout << std::endl; + if (is_hf_det){ + det_exc.pair_inds.push_back(nvir_up * occ_pair.first + vir_pair.first); + } + } @@ -360,6 +375,9 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ long vir = remaining_virs[vir_comb[idx]]; excite_det(occ, vir, &temp_det[0]); std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; + if (is_hf_det) { + det_exc.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); + } } add_det(&temp_det[0]); // Print determinant after single excitations @@ -381,13 +399,15 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << det[k] << " "; } std::cout << std::endl; + } } } } - + return ; } } + From 6e0fa61efb32e9f7a18d677c927f6343eb5ee0a3 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 16:34:16 -0500 Subject: [PATCH 081/197] Add excitation details to the det_exc_param_indx vector --- pyci/src/nonsingletci.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index cb33df9..2cbe8c3 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -268,7 +268,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Generate occ pair combinations std::vector>> opair_combinations; - opair_combinations.push_back(generate_combinations(nocc_pairs, d)); + std::vector>> vpair_combinations; + opair_combinations.push_back(generate_combinations(nocc_pairs, d)); + vpair_combinations.push_back(generate_combinations(nvir_pairs, d)); + + std::cout << "Generated opair_combinations: " << std::endl; for (const auto& opair_comb : opair_combinations[0]) { for (const auto& idx : opair_comb) { @@ -277,8 +281,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; - std::vector>> vpair_combinations; - vpair_combinations.push_back(generate_combinations(nvir_pairs, d)); + std::cout << "Generated vpair_combinations: " << std::endl; for (const auto& pair_comb : vpair_combinations[0]) { for (const auto& idx : pair_comb) { @@ -291,9 +294,8 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (const auto& opair_comb : opair_combinations[0]) { for (const auto& vpair_comb : vpair_combinations[0]) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - if (is_hf_det) { - DetExcParamIndx det_exc; - } + DetExcParamIndx det_exc; + std::vector used_virs; @@ -386,6 +388,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << temp_det[k] << " "; } std::cout << std::endl; + if (is_hf_det) { + std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); + det_exc_param_indx.push_back(det_exc); + } } } @@ -399,7 +405,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << det[k] << " "; } std::cout << std::endl; - + if (is_hf_det) { + std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); + det_exc_param_indx.push_back(det_exc); + } } } } From 3c3a4209c87eef5796047d094922c8f1bd51a544 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 17:48:58 -0500 Subject: [PATCH 082/197] Correct variable type to size_t for variables with vector.size() --- pyci/include/pyci.h | 4 ++-- pyci/src/nonsingletci.cpp | 50 +++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 9c1594c..5a86962 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -668,9 +668,9 @@ struct NonSingletCI final : public GenCIWfn { NonSingletCI(const long, const long, const long, const Array); - std::vector> generate_combinations(long, long); + std::vector> generate_combinations(std::size_t, std::size_t); - std::vector> generate_cartesian_product(const AlignedVector>&, long); + std::vector> generate_cartesian_product(const AlignedVector>&, std::size_t); void fill_hartreefock_det(long, long, ulong *); diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 2cbe8c3..41ed370 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -59,13 +59,13 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar // In our case: this function is used to generate all possible combinations of // occupied orbitals to excite from for singles given pair of occupied orbitals in ref det std::vector> NonSingletCI::generate_cartesian_product( - const AlignedVector>& pairs, long k) { + const AlignedVector>& pairs, std::size_t k) { std::vector> result; std::cout << "Inside nonsingletci/generate_cartesian_product" << std::endl; std::cout << "pairs.size(): " << pairs.size() << std::endl; std::cout << "k: " << k << std::endl; - long nocc_pairs = pairs.size(); + std::size_t nocc_pairs = pairs.size(); if (k > nocc_pairs) return result; std::vector> temp_combinations = {{}}; @@ -103,7 +103,7 @@ std::vector> NonSingletCI::generate_cartesian_product( // Function to generate combinations, based on indices -std::vector> NonSingletCI::generate_combinations(long n, long k) { +std::vector> NonSingletCI::generate_combinations(std::size_t n, std::size_t k) { std::vector> combinations; if (k > n) return combinations; @@ -116,7 +116,7 @@ std::vector> NonSingletCI::generate_combinations(long n, long do { std::vector combination; - for (long i = 0; i < n; ++i) { + for (std::size_t i = 0; i < n; ++i) { if (mask[i]) combination.push_back(indices[i]); } combinations.push_back(combination); @@ -225,38 +225,40 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ for (long vir : virs) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); excite_det(occ, vir, &det[0]); - add_det(&det[0]); - // Print determinant after excite_det loop + add_det(&det[0]); - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - // Structure to store determinant and indices of params //corresponding to the pair-excitations & single-excitations if (is_hf_det) { - DetExcParamIndx det_exc_param; - std::memcpy(&det_exc_param.det[0], &det[0], sizeof(ulong) * nword); - det_exc_param.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); + DetExcParamIndx container; + container.det.resize(nword); + std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); + container.pair_inds.clear(); + container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); + det_exc_param_indx.push_back(container); } - std::cout << std::endl; + std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; + for (int k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << std::endl; } + std::cout << std::endl; } std::cout << std::endl; return ; } // Handle excitation orders >= 2 - long nocc_pairs = occ_pairs.size(); - long nvir_pairs = vir_pairs.size(); + std::size_t nocc_pairs = occ_pairs.size(); + std::size_t nvir_pairs = vir_pairs.size(); std::cout << "nocc_pairs: " << nocc_pairs << std::endl; if (e >= 2) { // Iterate over possible (d,s) pairs: d pair excitations and s single excitations std::cout << "--------Handling excitation order >= 2--------" << std::endl; - for (long d = 0; d <= std::min(e/2, nocc_pairs); ++d){ - long num_singles = e - 2 * d; + for (std::size_t d = 0; d <= std::min(static_cast(e/2), nocc_pairs); ++d){ + std::size_t num_singles = e - 2 * d; std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; @@ -296,10 +298,8 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det[0], rdet, sizeof(ulong) * nword); DetExcParamIndx det_exc; - - std::vector used_virs; - for (long idx = 0; idx < d; ++idx) { + for (std::size_t idx = 0; idx < d; ++idx) { const auto& occ_pair = occ_pairs[opair_comb[idx]]; const auto& vir_pair = vir_pairs[vpair_comb[idx]]; @@ -326,7 +326,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ if (num_singles > 0) { // Determine remaining occupied pairs AlignedVector> remaining_occ_pairs; - for (long i = 0; i < nocc_pairs; ++i) { + for (std::size_t i = 0; i < nocc_pairs; ++i) { if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { remaining_occ_pairs.push_back(occ_pairs[i]); } @@ -335,7 +335,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ AlignedVector remaining_virs; - for (long i = 0; i < virs.size(); ++i) { + for (std::size_t i = 0; i < virs.size(); ++i) { if (std::find(used_virs.begin(), used_virs.end(), virs[i]) == used_virs.end()) { remaining_virs.push_back(virs[i]); } @@ -372,7 +372,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); // Apply single excitations - for (long idx = 0; idx < num_singles; ++idx){ + for (std::size_t idx = 0; idx < num_singles; ++idx){ long occ = occ_comb[idx]; long vir = remaining_virs[vir_comb[idx]]; excite_det(occ, vir, &temp_det[0]); From 101d37cbe787a757331fd52949308adfea49517b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 20:11:58 -0500 Subject: [PATCH 083/197] Correction: excite singles from only doubly-occupied-orbital-pairs --- pyci/src/nonsingletci.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 41ed370..31ae612 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -219,9 +219,15 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // Handle excitation order 1 if (e == 1) { + // Flatten occ_pairs into a single-dimensional array + std::vector flattened_occs; + for (const auto& pair : occ_pairs) { + flattened_occs.push_back(pair.first); + flattened_occs.push_back(pair.second); + } std::cout << "-----Handling excitation order 1-----" << std::endl; std::cout << "Determinants of excitation order 1" << std::endl; - for (long occ : occs) { + for (long occ : flattened_occs) { for (long vir : virs) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); excite_det(occ, vir, &det[0]); @@ -268,7 +274,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ continue; } - // Generate occ pair combinations + // Generate occ pair and vir pair combinations std::vector>> opair_combinations; std::vector>> vpair_combinations; opair_combinations.push_back(generate_combinations(nocc_pairs, d)); From 952e5cefe822182619e1d38758d91981204a471c Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 20:19:28 -0500 Subject: [PATCH 084/197] Add check on combinations of occ and vir pairs --- pyci/src/nonsingletci.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 31ae612..631b889 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -301,6 +301,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Process pair combinations for current d for (const auto& opair_comb : opair_combinations[0]) { for (const auto& vpair_comb : vpair_combinations[0]) { + if (opair_comb.empty() || vpair_comb.empty()) { + std::cout << "Error: Empty combination detected" << std::endl; + // continue; + } std::memcpy(&det[0], rdet, sizeof(ulong) * nword); DetExcParamIndx det_exc; From 0aa9b175816d085dbb082b17808446678a0b25e8 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 19:25:44 -0500 Subject: [PATCH 085/197] Add det exc details entry at indx ndet everytime a new det is added in add_excited_dets --- pyci/src/nonsingletci.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 631b889..cfe3899 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -241,7 +241,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); container.pair_inds.clear(); container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); - det_exc_param_indx.push_back(container); + det_exc_param_indx[ndet] = container; } std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; for (int k = 0; k < nword; ++k) { @@ -400,7 +400,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << std::endl; if (is_hf_det) { std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); - det_exc_param_indx.push_back(det_exc); + det_exc_param_indx[ndet] = det_exc; } } @@ -417,7 +417,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << std::endl; if (is_hf_det) { std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); - det_exc_param_indx.push_back(det_exc); + det_exc_param_indx[ndet] = det_exc; } } } From dd9e9b1f300d39e41888a0f70e473b4d43a5174d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 22:02:24 -0500 Subject: [PATCH 086/197] add nonsingletci entry in sparseop --- pyci/src/sparseop.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 1eac1ee..2c50f18 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -70,6 +70,14 @@ SparseOp::SparseOp(const SQuantOp &ham, const GenCIWfn &wfn, const long rows, co update(ham, wfn, nrow, ncol, 0); } +SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, + const bool symm) + : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), + ecore(ham.ecore), symmetric(symm) { + append(indptr, 0); + update(ham, wfn, nrow, ncol, 0); +} + pybind11::object SparseOp::dtype(void) const { return pybind11::dtype::of(); } From a740485d996eb181b898b188b8df8ec97a192a02 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 22:36:00 -0500 Subject: [PATCH 087/197] comment line for pair inds in is_hf_block for e ==1 in add_excited_dets --- pyci/src/nonsingletci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index cfe3899..d60d0d2 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -239,7 +239,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ DetExcParamIndx container; container.det.resize(nword); std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); - container.pair_inds.clear(); + //container.pair_inds.clear(); container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); det_exc_param_indx[ndet] = container; } From d9fd120501d2fb0b2a5a3a741595117f7bd5e93b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 23:06:37 -0500 Subject: [PATCH 088/197] Commenting det_exc_param_indx line in e==1_ --- pyci/src/nonsingletci.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index d60d0d2..9c89411 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -232,16 +232,18 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det[0], rdet, sizeof(ulong) * nword); excite_det(occ, vir, &det[0]); add_det(&det[0]); - + DetExcParamIndx container; // Structure to store determinant and indices of params //corresponding to the pair-excitations & single-excitations if (is_hf_det) { - DetExcParamIndx container; + container.det.resize(nword); std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); //container.pair_inds.clear(); container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); - det_exc_param_indx[ndet] = container; + std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; + std::cout << "ndet" << ndet << std::endl; + //det_exc_param_indx[ndet] = container; } std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; for (int k = 0; k < nword; ++k) { From 986670665f1b0e62a1c24b4d2ba506e64c09c757 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 4 Dec 2024 12:03:45 -0500 Subject: [PATCH 089/197] Mark fill_hartreefock_det function as constant --- pyci/include/pyci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 5a86962..ec72f13 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -672,7 +672,7 @@ struct NonSingletCI final : public GenCIWfn { std::vector> generate_cartesian_product(const AlignedVector>&, std::size_t); - void fill_hartreefock_det(long, long, ulong *); + void fill_hartreefock_det(long, long, ulong *) const; void add_excited_dets(const ulong *, const long); From a6b4f4b641d607979043c29a4847b8a3793b0ae5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 4 Dec 2024 12:05:17 -0500 Subject: [PATCH 090/197] Update the det_exc_param_indx size verification and fix indices for new entries --- pyci/src/nonsingletci.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 9c89411..dc64457 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -232,18 +232,22 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det[0], rdet, sizeof(ulong) * nword); excite_det(occ, vir, &det[0]); add_det(&det[0]); - DetExcParamIndx container; + // Structure to store determinant and indices of params //corresponding to the pair-excitations & single-excitations if (is_hf_det) { - - container.det.resize(nword); + DetExcParamIndx container; + // container.DetExcParamIndx container; + // det.resize(nword); std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); - //container.pair_inds.clear(); + container.pair_inds.clear(); container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; std::cout << "ndet" << ndet << std::endl; - //det_exc_param_indx[ndet] = container; + if (det_exc_param_indx.size() < ndet) { + det_exc_param_indx.resize(ndet); + } + det_exc_param_indx[ndet-1] = container; } std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; for (int k = 0; k < nword; ++k) { @@ -402,7 +406,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << std::endl; if (is_hf_det) { std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); - det_exc_param_indx[ndet] = det_exc; + if (det_exc_param_indx.size() < ndet) { + det_exc_param_indx.resize(ndet); + } + det_exc_param_indx[ndet-1] = det_exc; } } @@ -419,7 +426,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << std::endl; if (is_hf_det) { std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); - det_exc_param_indx[ndet] = det_exc; + if (det_exc_param_indx.size() < ndet) { + det_exc_param_indx.resize(ndet); + } + det_exc_param_indx[ndet-1] = det_exc; } } } @@ -432,7 +442,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ -void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) { +void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) const { /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ long nb = nb2/2; // FIXME: The code is assuming nocc is even From e29f1360d8dc808501f27b8d3bb090e03bce4e15 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 4 Dec 2024 12:21:11 -0500 Subject: [PATCH 091/197] Ensure the container det size for every entry of the det_exc_param_indx --- pyci/src/nonsingletci.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index dc64457..7a87f36 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -237,8 +237,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ //corresponding to the pair-excitations & single-excitations if (is_hf_det) { DetExcParamIndx container; - // container.DetExcParamIndx container; - // det.resize(nword); + container.det.resize(nword); std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); container.pair_inds.clear(); container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); @@ -311,10 +310,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Error: Empty combination detected" << std::endl; // continue; } + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + std::vector used_virs; DetExcParamIndx det_exc; - std::vector used_virs; for (std::size_t idx = 0; idx < d; ++idx) { const auto& occ_pair = occ_pairs[opair_comb[idx]]; const auto& vir_pair = vir_pairs[vpair_comb[idx]]; @@ -405,6 +405,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; if (is_hf_det) { + det_exc.det.resize(nword); std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); if (det_exc_param_indx.size() < ndet) { det_exc_param_indx.resize(ndet); @@ -425,6 +426,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; if (is_hf_det) { + det_exc.det.resize(nword); std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); if (det_exc_param_indx.size() < ndet) { det_exc_param_indx.resize(ndet); From cb0d2bdf21cc8ebba955038a06754385d887ed5f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 4 Dec 2024 12:30:20 -0500 Subject: [PATCH 092/197] Add inline function to insure the struct size --- pyci/include/pyci.h | 7 +++++++ pyci/src/nonsingletci.cpp | 12 +++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index ec72f13..62cc37d 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -620,6 +620,13 @@ struct DetExcParamIndx { std::vector single_inds; }; +// Inline utility function for resizing DetExcParamIndx Object +inline void ensure_struct_size(std::vector& vec, const long size) { + if (vec.size() < static_cast::size_type>(size)) { + vec.resize(size); + } +} + struct NonSingletCI final : public GenCIWfn { public: using Wfn::maxrank_dn; diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 7a87f36..a752602 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -243,9 +243,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; std::cout << "ndet" << ndet << std::endl; - if (det_exc_param_indx.size() < ndet) { - det_exc_param_indx.resize(ndet); - } + ensure_struct_size(det_exc_param_indx, ndet); det_exc_param_indx[ndet-1] = container; } std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; @@ -407,9 +405,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ if (is_hf_det) { det_exc.det.resize(nword); std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); - if (det_exc_param_indx.size() < ndet) { - det_exc_param_indx.resize(ndet); - } + ensure_struct_size(det_exc_param_indx, ndet); det_exc_param_indx[ndet-1] = det_exc; } } @@ -428,9 +424,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ if (is_hf_det) { det_exc.det.resize(nword); std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); - if (det_exc_param_indx.size() < ndet) { - det_exc_param_indx.resize(ndet); - } + ensure_struct_size(det_exc_param_indx, ndet); det_exc_param_indx[ndet-1] = det_exc; } } From d20e695ef26f1dc3601c68265fa0010debbd07ba Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 5 Dec 2024 20:28:53 -0500 Subject: [PATCH 093/197] Update add_row function for NonSingletCI --- pyci/src/sparseop.cpp | 418 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 409 insertions(+), 9 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 2c50f18..2ed8013 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -14,7 +14,7 @@ * along with PyCI. If not, see . */ #include - +#include namespace pyci { namespace { @@ -67,16 +67,17 @@ SparseOp::SparseOp(const SQuantOp &ham, const GenCIWfn &wfn, const long rows, co : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), ecore(ham.ecore), symmetric(symm) { append(indptr, 0); + std::cout << "Inside SparseOp constructor" << std::endl; update(ham, wfn, nrow, ncol, 0); } -SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, - const bool symm) - : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), - ecore(ham.ecore), symmetric(symm) { - append(indptr, 0); - update(ham, wfn, nrow, ncol, 0); -} +// SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, +// const bool symm) +// : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), +// ecore(ham.ecore), symmetric(symm) { +// append(indptr, 0); +// update(ham, wfn, nrow, ncol, 0); +// } pybind11::object SparseOp::dtype(void) const { return pybind11::dtype::of(); @@ -200,12 +201,14 @@ void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, shape = pybind11::make_tuple(pybind11::cast(rows), pybind11::cast(cols)); nrow = rows; ncol = cols; + std::cout << "nrow: " << nrow << std::endl; indptr.reserve(nrow + 1); for (long idet = startrow; idet < rows; ++idet) { add_row(ham, wfn, idet, &det[0], &occs[0], &virs[0]); sort_row(idet); } size = indices.size(); + std::cout << "size: " << size << std::endl; } void SparseOp::reserve(const long n) { @@ -407,7 +410,7 @@ void SparseOp::add_row(const SQuantOp &ham, const FullCIWfn &wfn, const long ide koffset = ioffset + n2 * kk; // loop over spin-down virtual indices for (l = j + 1; l < wfn.nvir_dn; ++l) { - ll = virs_dn[l]; + ; ll = virs_dn[l]; // 0-2 excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); @@ -509,4 +512,401 @@ void SparseOp::add_row(const SQuantOp &ham, const GenCIWfn &wfn, const long idet append(indptr, indices.size()); } + +void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long idet, ulong *det_up, + long *occs_up, long *virs) { + long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); + long ioffset, koffset, sign_up; + long nbasis = wfn.nbasis / 2; + long n1 = nbasis; // Check if nbasis or nbasis * 2! + long n2 = n1 * n1; + long n3 = n1 * n2; + double val1, val2 = 0.0; + const ulong *rdet_up = wfn.det_ptr(idet); + const ulong *rdet_dn = rdet_up + nbasis; + ulong *det_dn = det_up + nbasis; + long *occs_dn = occs_up + wfn.nocc / 2; // Assuming nocc is even; closed shell system + std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); // !Check nword or nword2 + + fill_occs(wfn.nword, rdet_up, occs_up); + fill_occs(wfn.nword, rdet_dn, occs_dn); + fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); + + long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis / 2) - 1)); + long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); + long nvir_up = nbasis - nocc_up; + long nvir_dn = nbasis - nocc_dn; + long *virs_up = virs; + long *virs_dn = nullptr; + for (long i = 0; i < wfn.nvir; ++i) { + if (virs[i] >= nbasis) { + virs_dn = &virs[i]; + break; + } + } + + // loop over spin-up occupied indices + for (i = 0; i < nocc_up; ++i) { + ii = occs_up[i]; + ioffset = n3 * ii; + // compute part of diagonal matrix element + val2 += ham.one_mo[(n1 + 1) * ii]; + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; + } + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + val2 += ham.two_mo[ioffset + n2 * kk + n1 * ii + kk]; + } + // loop over spin-up virtual indices + for (j = 0; j < nvir_up; ++j) { + jj = virs_up[j]; + // alpha -> alpha excitation elements + excite_det(ii, jj, det_up); + sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); + jdet = wfn.index_det(det_up); + // check if 1-0 excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // compute 1-0 matrix element + val1 = ham.one_mo[n1 * ii + jj]; + for (k = 0; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + } + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + } + // add 1-0 matrix element + append(data, sign_up * val1); + append(indices, jdet); + } + // loop over spin-down occupied indices + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + // loop over spin-up virtual indices + for (l = 0; l < nvir_up; ++l) { + ll = virs_up[l]; + // beta -> alpha excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if 1-1 excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 1-1 matrix element + append(data, sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_up) * + ham.two_mo[koffset + n1 * jj + ll]); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + // loop over spin-down virtual indices + for (l = 0; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // 1-1 excitation elements + excite_det(kk, ll, det_dn); + jdet = wfn.index_det(det_up); + // check if 1-1 excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 1-1 matrix element + append(data, sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_dn) * + ham.two_mo[koffset + n1 * jj + ll]); + append(indices, jdet); + } + excite_det(ll, kk, det_dn); + } + } + // loop over spin-up occupied indices + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + // loop over spin-up virtual indices + for (l = j + 1; l < nvir_up; ++l) { + ll = virs_up[l]; + // alpha -> alpha excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 2-0 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + // loop over spin-dn virtual indices + for (l = j + 1; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // alpha -> beta excitation elements + excite_det(kk, ll, det_dn); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 2-0 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_dn); + } + } + excite_det(jj, ii, det_up); + } + + // loop over spin-dn virtual indices + for (j = 0; j < nvir_dn; ++j) { + jj = virs_dn[j]; + // alpha -> beta excitation elements + excite_det(ii, jj, det_up); + sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // compute the matrix element + val1 = ham.one_mo[n1 * ii + jj]; + for (k = 0; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + } + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + } + // add the matrix element + append(data, sign_up * val1); + append(indices, jdet); + } + // loop over spin-down occupied indices + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + // loop over spin-up virtual indices + for (l = 0; l < nvir_up; ++l) { + ll = virs_up[l]; + // beta -> alpha excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if 1-1 excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 1-1 matrix element + append(data, sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_up) * + ham.two_mo[koffset + n1 * jj + ll]); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + // loop over spin-down virtual indices + for (l = 0; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // 1-1 excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if 1-1 excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 1-1 matrix element + append(data, sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_up) * + ham.two_mo[koffset + n1 * jj + ll]); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + } + // loop over spin-up occupied indices + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + // loop over spin-up virtual indices + for (l = j + 1; l < nvir_up; ++l) { + ll = virs_up[l]; + // alpha -> alpha excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 2-0 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + // loop over spin-dn virtual indices + for (l = j + 1; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // alpha -> beta excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 2-0 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + } + excite_det(jj, ii, det_up); + } + } + // loop over spin-down occupied indices + for (i = 0; i < nocc_dn; ++i) { + ii = occs_dn[i]; + ioffset = n3 * ii; + // compute part of diagonal matrix element + val2 += ham.one_mo[(n1 + 1) * ii]; + for (k = i + 1; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; + } + // loop over spin-up virtual indices + for (j = 0; j < nvir_up; ++j) { + jj = virs_up[j]; + // beta -> alpha excitation elements + excite_det(ii, jj, det_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // compute the matrix element + val1 = ham.one_mo[n1 * ii + jj]; + for (k = 0; k < nocc_up; ++k) { + kk = occs_up[k]; + val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + } + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + } + // add the matrix element + append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); + append(indices, jdet); + } + // loop over spin-down occupied indices + for (k = i + 1; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + // loop over spin-up virtual indices + for (l = j + 1; l < nvir_up; ++l) { + ll = virs_up[l]; + // beta -> alpha excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 0-2 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + // loop over spin-down virtual indices + for (l = j + 1; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // beta -> beta excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 0-2 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + } + excite_det(jj, ii, det_up); + } + // loop over spin-down virtual indices + for (j = 0; j < nvir_dn; ++j) { + jj = virs_dn[j]; + // beta -> beta excitation elements + excite_det(ii, jj, det_up); + jdet = wfn.index_det(det_up); + // check if 0-1 excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // compute 0-1 matrix element + val1 = ham.one_mo[n1 * ii + jj]; + for (k = 0; k < nocc_up; ++k) { + kk = occs_up[k]; + val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + } + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + } + // add 0-1 matrix element + append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); + append(indices, jdet); + } + // loop over spin-down occupied indices + for (k = i + 1; k < nocc_dn; ++k) { + kk = occs_dn[k]; + koffset = ioffset + n2 * kk; + // loop over spin-up virtual indices + for (l = j + 1; l < nvir_up; ++l) { + ll = virs_up[l]; + // beta -> alpha excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 0-2 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + // loop over spin-down virtual indices + for (l = j + 1; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // beta -> beta excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // add 0-2 matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + } + excite_det(jj, ii, det_up); + } + } + // add diagonal element to matrix + if (idet < ncol) { + append(data, val2); + append(indices, idet); + } + // add pointer to next row's indices + append(indptr, indices.size()); +} + + + } // namespace pyci From 3e7f0b3408e285c7f47927e69304d04eb21e5768 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 5 Dec 2024 21:48:48 -0500 Subject: [PATCH 094/197] Add entries for SparseOP NonSingletCI spefic functions --- pyci/src/binding.cpp | 5 +++++ pyci/src/sparseop.cpp | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 7f6996b..7b51042 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1103,6 +1103,9 @@ sparse_op.def(py::init(), py::arg("ham"), py::arg("wfn"), py::arg("nrow") = -1, py::arg("ncol") = -1, py::arg("symmetric") = true); +sparse_op.def(py::init(), + py::arg("ham"), py::arg("wfn"), py::arg("nrow") = -1, py::arg("ncol") = -1, + py::arg("symmetric") = true); sparse_op.def("update", &SparseOp::py_update, R"""( Update a sparse matrix operator for the HCI algorithm. @@ -1127,6 +1130,8 @@ sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg("wfn")); +sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg("wfn")); + sparse_op.def("__call__", &SparseOp::py_matvec, R"""( Compute the matrix vector product of the sparse matrix operator with vector ``x``. diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 2ed8013..c6fde9c 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -71,13 +71,13 @@ SparseOp::SparseOp(const SQuantOp &ham, const GenCIWfn &wfn, const long rows, co update(ham, wfn, nrow, ncol, 0); } -// SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, -// const bool symm) -// : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), -// ecore(ham.ecore), symmetric(symm) { -// append(indptr, 0); -// update(ham, wfn, nrow, ncol, 0); -// } +SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, + const bool symm) + : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), + ecore(ham.ecore), symmetric(symm) { + append(indptr, 0); + update(ham, wfn, nrow, ncol, 0); +} pybind11::object SparseOp::dtype(void) const { return pybind11::dtype::of(); @@ -192,6 +192,8 @@ template void SparseOp::py_update(const SQuantOp &, const FullCIWfn &); template void SparseOp::py_update(const SQuantOp &, const GenCIWfn &); +template void SparseOp::py_update(const SQuantOp &, const NonSingletCI &); + template void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, const long cols, const long startrow) { From 91652b516a40f54824c8a9268bc4c289b9c1911c Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Fri, 6 Dec 2024 21:40:50 -0500 Subject: [PATCH 095/197] Add update function in sparseop.cpp exclusively for NonSingletCI and add extra keyword for sparseop constructor to invoke appropriate function call when wfn is NonSingletCI --- pyci/include/pyci.h | 4 +- pyci/src/binding.cpp | 4 +- pyci/src/sparseop.cpp | 137 ++++++++++++++++++++++++++++++------------ 3 files changed, 105 insertions(+), 40 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 62cc37d..514f77a 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -712,7 +712,7 @@ struct SparseOp final { SparseOp(const SQuantOp &, const GenCIWfn &, const long, const long, const bool); - SparseOp(const SQuantOp &, const NonSingletCI &, const long, const long, const bool); + SparseOp(const SQuantOp &, const NonSingletCI &, const long, const long, const bool, const std::string); pybind11::object dtype(void) const; @@ -734,6 +734,8 @@ struct SparseOp final { template void update(const SQuantOp &, const WfnType &, const long, const long, const long); + void update(const SQuantOp &, const NonSingletCI &, const long , const long, const long); + void reserve(const long); void squeeze(void); diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 7b51042..46f0a57 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1103,9 +1103,9 @@ sparse_op.def(py::init(), py::arg("ham"), py::arg("wfn"), py::arg("nrow") = -1, py::arg("ncol") = -1, py::arg("symmetric") = true); -sparse_op.def(py::init(), +sparse_op.def(py::init(), py::arg("ham"), py::arg("wfn"), py::arg("nrow") = -1, py::arg("ncol") = -1, - py::arg("symmetric") = true); + py::arg("symmetric") = true, py::arg("wfntype") = "nonsingletci"); sparse_op.def("update", &SparseOp::py_update, R"""( Update a sparse matrix operator for the HCI algorithm. diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index c6fde9c..6aeb857 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -15,6 +15,7 @@ #include #include + namespace pyci { namespace { @@ -72,10 +73,11 @@ SparseOp::SparseOp(const SQuantOp &ham, const GenCIWfn &wfn, const long rows, co } SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, - const bool symm) + const bool symm, const std::string wfntype) : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), ecore(ham.ecore), symmetric(symm) { append(indptr, 0); + std::cout << "Inside SparseOp NonSingletCI constructor" << std::endl; update(ham, wfn, nrow, ncol, 0); } @@ -197,9 +199,13 @@ template void SparseOp::py_update(const SQuantOp &, const NonSingletCI &); template void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, const long cols, const long startrow) { + std::cout << "Inside SparseOp update" << std::endl; + std::cout << "Type of WfnType: " << typeid(WfnType).name() << std::endl; + AlignedVector det(wfn.nword2); AlignedVector occs(wfn.nocc); AlignedVector virs(wfn.nvir); + std::cout << "wfn.nvir: " << wfn.nvir << std::endl; shape = pybind11::make_tuple(pybind11::cast(rows), pybind11::cast(cols)); nrow = rows; ncol = cols; @@ -213,6 +219,36 @@ void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, std::cout << "size: " << size << std::endl; } + +void SparseOp::update(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, + const long startrow) { + std::cout << "Inside NonsingletCI SparseOp update" << std::endl; + // std::cout << "Type of WfnType: " << typeid(WfnType).name() << std::endl; + // if (is_same::value) { + // long nword = wfn.nword; + // long nvir = wfn.nbasis - wfn.nocc; + // } else { + // long nword = wfn.nword2; + // long nvir = wfn.nvir; + // } + AlignedVector det(wfn.nword); + AlignedVector occs(wfn.nocc); + AlignedVector virs(wfn.nbasis - wfn.nocc); + std::cout << "wfn.nvir: " << wfn.nvir << std::endl; + shape = pybind11::make_tuple(pybind11::cast(rows), pybind11::cast(cols)); + nrow = rows; + ncol = cols; + std::cout << "nrow: " << nrow << std::endl; + indptr.reserve(nrow + 1); + for (long idet = startrow; idet < rows; ++idet) { + add_row(ham, wfn, idet, &det[0], &occs[0], &virs[0]); + sort_row(idet); + } + size = indices.size(); + std::cout << "size: " << size << std::endl; +} + + void SparseOp::reserve(const long n) { indices.reserve(n); data.reserve(n); @@ -516,7 +552,11 @@ void SparseOp::add_row(const SQuantOp &ham, const GenCIWfn &wfn, const long idet void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long idet, ulong *det_up, - long *occs_up, long *virs) { + long *occs, long *virs) { + std::cout << "---Inside add_row NonSingletCI--" << std::endl; + std::cout << "idet: " << idet << std::endl; + std::cout << "wfn.nbasis: " << wfn.nbasis << std::endl; + std::cout << "wfn.nword: " << wfn.nword << std::endl; long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); long ioffset, koffset, sign_up; long nbasis = wfn.nbasis / 2; @@ -526,18 +566,29 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long double val1, val2 = 0.0; const ulong *rdet_up = wfn.det_ptr(idet); const ulong *rdet_dn = rdet_up + nbasis; + std::cout << "rdet_up: " << *rdet_up << std::endl; ulong *det_dn = det_up + nbasis; - long *occs_dn = occs_up + wfn.nocc / 2; // Assuming nocc is even; closed shell system std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); // !Check nword or nword2 - fill_occs(wfn.nword, rdet_up, occs_up); - fill_occs(wfn.nword, rdet_dn, occs_dn); - fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); + fill_occs(wfn.nword, rdet_up, occs); + fill_virs(wfn.nword, nbasis, rdet_up, virs); long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis / 2) - 1)); long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; + std::cout << "nocc_up: " << nocc_up << ", nocc_dn: " << nocc_dn << std::endl; + std::cout << "nvir_up: " << nvir_up << ", nvir_dn: " << nvir_dn << std::endl; + std::cout << "Occs: " ; + for (i = 0; i < wfn.nocc; ++i) { + std::cout << occs[i] << " "; + } + std::cout << std::endl; + std::cout << "Virs: " ; + for (i = 0; i < (nvir_up + nvir_dn); ++i) { + std::cout << virs[i] << " "; + } + std::cout << std::endl; long *virs_up = virs; long *virs_dn = nullptr; for (long i = 0; i < wfn.nvir; ++i) { @@ -546,11 +597,20 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long break; } } - + long *occs_up = occs; + long *occs_dn = nullptr; + for (long i = 0; i < wfn.nocc; ++i) { + if (occs[i] >= nbasis) { + occs_dn = &occs[i]; + break; + } + } + // std::cout << "ham.one_mo.size(): " << ham.one_mo.size() << std::endl; // loop over spin-up occupied indices for (i = 0; i < nocc_up; ++i) { ii = occs_up[i]; ioffset = n3 * ii; + // compute part of diagonal matrix element val2 += ham.one_mo[(n1 + 1) * ii]; for (k = i + 1; k < nocc_up; ++k) { @@ -569,6 +629,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(ii, jj, det_up); sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); jdet = wfn.index_det(det_up); + // check if 1-0 excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { // compute 1-0 matrix element @@ -585,6 +646,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // add 1-0 matrix element append(data, sign_up * val1); append(indices, jdet); + std::cout << "jdet: " << jdet << std::endl; } // loop over spin-down occupied indices for (k = 0; k < nocc_dn; ++k) { @@ -729,21 +791,21 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_up[k]; koffset = ioffset + n2 * kk; // loop over spin-up virtual indices - for (l = j + 1; l < nvir_up; ++l) { - ll = virs_up[l]; - // alpha -> alpha excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } + // for (l = j + 1; l < nvir_up; ++l) { + // ll = virs_up[l]; + // // alpha -> alpha excitation elements + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // add 2-0 matrix element + // append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + // (ham.two_mo[koffset + n1 * jj + ll] - + // ham.two_mo[koffset + n1 * ll + jj])); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } // loop over spin-dn virtual indices for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; @@ -865,21 +927,21 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; koffset = ioffset + n2 * kk; // loop over spin-up virtual indices - for (l = j + 1; l < nvir_up; ++l) { - ll = virs_up[l]; - // beta -> alpha excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } + // for (l = j + 1; l < nvir_up; ++l) { + // ll = virs_up[l]; + // // beta -> alpha excitation elements + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // add 0-2 matrix element + // append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + // (ham.two_mo[koffset + n1 * jj + ll] - + // ham.two_mo[koffset + n1 * ll + jj])); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } // loop over spin-down virtual indices for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; @@ -905,6 +967,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(data, val2); append(indices, idet); } + std::cout << "Insinde nonsinglet add_row indices.size(): " << indices.size() << std::endl; // add pointer to next row's indices append(indptr, indices.size()); } From c107970714c265aa53ed80a599eca08ef6272abd Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 8 Dec 2024 12:11:16 -0500 Subject: [PATCH 096/197] Update definition and declaration for py_update function --- pyci/include/pyci.h | 7 +++++-- pyci/src/binding.cpp | 2 +- pyci/src/sparseop.cpp | 12 +++--------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 514f77a..fe586c0 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -731,11 +731,11 @@ struct SparseOp final { void solve_ci(const long, const double *, const long, const long, const double, double *, double *) const; + void update(const SQuantOp &, const NonSingletCI &, const long , const long, const long); + template void update(const SQuantOp &, const WfnType &, const long, const long, const long); - void update(const SQuantOp &, const NonSingletCI &, const long , const long, const long); - void reserve(const long); void squeeze(void); @@ -750,6 +750,9 @@ struct SparseOp final { template void py_update(const SQuantOp &, const WfnType &); + void py_update(const SQuantOp &, const NonSingletCI &); //, const long, const long, const long); + + private: void sort_row(const long); diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index 46f0a57..d0568a5 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -1130,7 +1130,7 @@ sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg("wfn")); -sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg("wfn")); +sparse_op.def("update", &SparseOp::py_update, py::arg("ham"), py::arg("wfn")); //, py::arg("rows")); sparse_op.def("__call__", &SparseOp::py_matvec, R"""( Compute the matrix vector product of the sparse matrix operator with vector ``x``. diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 6aeb857..92c5207 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -78,6 +78,7 @@ SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows ecore(ham.ecore), symmetric(symm) { append(indptr, 0); std::cout << "Inside SparseOp NonSingletCI constructor" << std::endl; + std::cout << "nrow: " << nrow << ", ncol: " << ncol << std::endl; update(ham, wfn, nrow, ncol, 0); } @@ -194,7 +195,8 @@ template void SparseOp::py_update(const SQuantOp &, const FullCIWfn &); template void SparseOp::py_update(const SQuantOp &, const GenCIWfn &); -template void SparseOp::py_update(const SQuantOp &, const NonSingletCI &); +template void SparseOp::py_update(const SQuantOp &ham, const NonSingletCI &wfn); +// { update(ham, wfn, wfn.ndet, wfn.ndet, nrow);} template void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, const long cols, @@ -223,14 +225,6 @@ void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, void SparseOp::update(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, const long startrow) { std::cout << "Inside NonsingletCI SparseOp update" << std::endl; - // std::cout << "Type of WfnType: " << typeid(WfnType).name() << std::endl; - // if (is_same::value) { - // long nword = wfn.nword; - // long nvir = wfn.nbasis - wfn.nocc; - // } else { - // long nword = wfn.nword2; - // long nvir = wfn.nvir; - // } AlignedVector det(wfn.nword); AlignedVector occs(wfn.nocc); AlignedVector virs(wfn.nbasis - wfn.nocc); From 2259d3254a5acf172a1f3dc1dc51972411eb85d4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 8 Dec 2024 18:46:28 -0500 Subject: [PATCH 097/197] Add function to calculate indices of params corresponding to the excitations --- pyci/include/pyci.h | 10 +++++ pyci/src/nonsingletci.cpp | 87 +++++++++++++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index fe586c0..b10c228 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -684,6 +684,16 @@ struct NonSingletCI final : public GenCIWfn { void add_excited_dets(const ulong *, const long); long py_add_excited_dets(const long, const pybind11::object); + + long calc_sindex(const long occ, const long vir); + + long calc_pindex(const long occ, const long vir); + + template + void print_vector(const std::string&, const AlignedVector& ); + + void print_pairs(const std::string&, const AlignedVector>&); + }; /* Sparse matrix operator class. */ diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index a752602..fe92973 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -141,9 +141,43 @@ void NonSingletCI::print_pairs(const std::string& label, const AlignedVector nbasis / 2) { + o = occ - nbasis / 2; + } + long idx = nocc / 2 * (nbasis - nocc) / 2 + o * v + v; + return idx; +} + +long NonSingletCI::calc_pindex(const long occ, const long vir){ + long o = 0; + long v = 0; + if (vir < nbasis / 2) { + v = vir - nocc / 2; + } else { + v = vir - nocc; + } + if (occ > nbasis / 2) { + o = occ - nbasis / 2; + } + long idx = (nbasis / 2 - nocc / 2) * o + v; + return idx; +} + void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Inside nonsingletci/add_excited_dets" << std::endl; //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); + std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; + std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; + std::cout << "nocc_dn: " << nocc_dn << ", nvir_dn: " << nvir_dn << std::endl; + std::cout << "nbasis: " << nbasis << std::endl; AlignedVector det(nword); AlignedVector occs(nocc); @@ -215,6 +249,17 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Handling excitation order 0" << std::endl; std::memcpy(&det[0], rdet, sizeof(ulong) * nword); add_det(&det[0]); + if (is_hf_det) { + DetExcParamIndx container; + container.det.resize(nword); + std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); + container.pair_inds.clear(); + container.single_inds.clear(); + ensure_struct_size(det_exc_param_indx, ndet); + det_exc_param_indx[ndet-1] = container; + std::cout << "Added HF det for e=0" << std::endl; + std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + } return ; } // Handle excitation order 1 @@ -240,11 +285,14 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ container.det.resize(nword); std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); container.pair_inds.clear(); - container.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); + long sidx = calc_sindex(occ, vir); + std::cout << "ndet: " << ndet << " S_index: " << (sidx) << std::endl; + container.single_inds.push_back(sidx); std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; std::cout << "ndet" << ndet << std::endl; ensure_struct_size(det_exc_param_indx, ndet); det_exc_param_indx[ndet-1] = container; + std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; } std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; for (int k = 0; k < nword; ++k) { @@ -331,7 +379,9 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } std::cout << std::endl; if (is_hf_det){ - det_exc.pair_inds.push_back(nvir_up * occ_pair.first + vir_pair.first); + long pidx = calc_pindex(occ_pair.first, vir_pair.first); + std::cout << "Pair index: " << pidx << std::endl; + det_exc.pair_inds.push_back(pidx); } } @@ -392,7 +442,8 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ excite_det(occ, vir, &temp_det[0]); std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; if (is_hf_det) { - det_exc.single_inds.push_back(nocc / 2 * nvir_up + nvir * occ + vir); + long sidx = calc_sindex(occ, vir); + det_exc.single_inds.push_back(sidx); } } add_det(&temp_det[0]); @@ -407,6 +458,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); ensure_struct_size(det_exc_param_indx, ndet); det_exc_param_indx[ndet-1] = det_exc; + std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; } } @@ -426,6 +478,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); ensure_struct_size(det_exc_param_indx, ndet); det_exc_param_indx[ndet-1] = det_exc; + std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; } } } @@ -447,30 +500,30 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) const { long num_ulongs = (nb2 + Size() - 1) / Size(); - std::cout << "Inside nonsingletci/fill_hartreefock_det" << std::endl; - std::cout << "nb: " << nb << std::endl; - std::cout << "nocc: " << nocc << std::endl; - std::cout << "nocc_beta: " << nocc_beta << std::endl; - std::cout << "nocc_alpha: " << nocc_alpha << std::endl; + // std::cout << "Inside nonsingletci/fill_hartreefock_det" << std::endl; + // std::cout << "nb: " << nb << std::endl; + // std::cout << "nocc: " << nocc << std::endl; + // std::cout << "nocc_beta: " << nocc_beta << std::endl; + // std::cout << "nocc_alpha: " << nocc_alpha << std::endl; - std::cout << "Filling beta spin orbitals" << std::endl; + // std::cout << "Filling beta spin orbitals" << std::endl; for (long i = 0; i < nocc_beta; ++i) { long bit_index = nb + i; - std::cout << "bit_index: " << bit_index << std::endl; + // std::cout << "bit_index: " << bit_index << std::endl; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } - std::cout << "Filling alpha spin orbitals" << std::endl; + // std::cout << "Filling alpha spin orbitals" << std::endl; for (long i = 0; i < nocc_alpha; ++i) { - std::cout << "bit_index: " << i << std::endl; + // std::cout << "bit_index: " << i << std::endl; long bit_index = i; det[bit_index / Size()] |= 1UL << (bit_index % Size()); } - std::cout << "det: "; - for (int i = 0; i < num_ulongs; ++i) { - std::cout << det[i] << " "; - } - std::cout << std::endl; + // std::cout << "det: "; + // for (int i = 0; i < num_ulongs; ++i) { + // std::cout << det[i] << " "; + // } + // std::cout << std::endl; } From 5eb4a020d05a697244822b346ceb8a7fb22b04cd Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 8 Dec 2024 19:03:38 -0500 Subject: [PATCH 098/197] Update NonSingletCI declarations as per branch of ap1rogen --- pyci/include/pyci.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index b10c228..c56af66 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -641,15 +641,11 @@ struct NonSingletCI final : public GenCIWfn { using Wfn::nvir_up; using Wfn::nword; using Wfn::nword2; + std::vector det_exc_param_indx; protected: using Wfn::dets; using Wfn::dict; - std::vector det_exc_param_indx; - - template - void print_vector(const std::string&, const AlignedVector& ); - void print_pairs(const std::string&, const AlignedVector>&); private: bool is_hf_det; From a149e0e1fddc0e0b10258d9f97e5ec0c58084d18 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 11:46:24 -0500 Subject: [PATCH 099/197] Mark calc_sindex and calc_pindex as const functions to suit it to init_overlap const wfn_ arg --- pyci/include/pyci.h | 36 ++++++++++++++++++++++++++---------- pyci/src/nonsingletci.cpp | 4 ++-- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index c56af66..d799637 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -681,9 +681,9 @@ struct NonSingletCI final : public GenCIWfn { long py_add_excited_dets(const long, const pybind11::object); - long calc_sindex(const long occ, const long vir); + long calc_sindex(const long occ, const long vir) const; - long calc_pindex(const long occ, const long vir); + long calc_pindex(const long occ, const long vir) const; template void print_vector(const std::string&, const AlignedVector& ); @@ -896,17 +896,13 @@ class AP1roGeneralizedSenoObjective : public Objective { using Objective::nparam; // # of FanCI parameters using Objective::ovlp; // Overlap vector using Objective::d_ovlp; // Overlap gradient matrix + // Declare variables you want to store to faciliate the computation // of {d_,}overlap here: - std::size_t nrow; - std::size_t ncol; std::vector nexc_list; - std::vector hole_list; - std::vector part_list; - // ... - // ... - + std::vector det_exc_param_indx; // Det and excitation details + public: // Keep in mind the {DOCI,FullCI,GenCI}Wfn class names in // the arguments below depend on the template specialization @@ -927,13 +923,33 @@ class AP1roGeneralizedSenoObjective : public Objective { // C++ move constructor AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&) noexcept; + // Generate combinations of pairs and singles + template + void generate_combinations(const std::vector&, int , std::vector>&, long ); + + // Generate partitions + std::vector> generate_partitions(int , int); + + // Generate excitations + void generate_excitations(const std::vector& , + const std::vector& , int , std::vector& , + std::vector&, long, const NonSingletCI &); + // Initializer for {d_,}overlap variables void init_overlap(const NonSingletCI &); + // Permanent calculation: Ryser's Algorithm + double permanent_calculation(const std::vector&, const double* ); + // Overlap function - virtual void overlap(const size_t, const double *x, double *y); + // virtual void overlap(const NonSingletCI &, const double *x, double *y); + virtual void overlap(const std::size_t, const double *x, double *y); + + // Helper function for d_overlap + double compute_derivative(const std::vector& excitation_indices, const double*, std::size_t ); // Overlap gradient function + // virtual void d_overlap(const NonSingletCI &, const size_t, const double *x, double *y); virtual void d_overlap(const size_t, const double *x, double *y); }; diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index fe92973..ec4355a 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -141,7 +141,7 @@ void NonSingletCI::print_pairs(const std::string& label, const AlignedVector Date: Mon, 9 Dec 2024 15:02:12 -0500 Subject: [PATCH 100/197] Correct the sindex calculations --- pyci/src/nonsingletci.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index ec4355a..c92ca42 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -142,17 +142,24 @@ void NonSingletCI::print_pairs(const std::string& label, const AlignedVector nbasis / 2) { - o = occ - nbasis / 2; + if (occ >= nb) { + o = occ - (nb - nocc / 2); + } else{ + o = occ; } - long idx = nocc / 2 * (nbasis - nocc) / 2 + o * v + v; + // std::cout << "\nocc: " << occ << ", vir: " << vir << std::endl; + // std::cout << "o: " << o << ", v: " << v << std::endl; + // std::cout << "nocc: " << nocc << ", nb: " << nb << std::endl; + + long idx = nocc / 2 * (nbasis - nocc) / 2 + o * (nbasis - nocc) + v; + // std::cout << "idx: " << idx << std::endl; return idx; } @@ -164,7 +171,7 @@ long NonSingletCI::calc_pindex(const long occ, const long vir) const { } else { v = vir - nocc; } - if (occ > nbasis / 2) { + if (occ >= nbasis / 2) { o = occ - nbasis / 2; } long idx = (nbasis / 2 - nocc / 2) * o + v; From 1b9b29ce7d104dd9924491e23d936d5cb80d1874 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 10 Dec 2024 16:51:27 -0500 Subject: [PATCH 101/197] Remove the det_exc_param_indx structure as a nonsingletci member --- pyci/include/pyci.h | 3 +- pyci/src/nonsingletci.cpp | 100 +++++++++++++++++++------------------- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index d799637..3b02fee 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -641,14 +641,13 @@ struct NonSingletCI final : public GenCIWfn { using Wfn::nvir_up; using Wfn::nword; using Wfn::nword2; - std::vector det_exc_param_indx; protected: using Wfn::dets; using Wfn::dict; private: - bool is_hf_det; + // bool is_hf_det; public: NonSingletCI(const NonSingletCI &); diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index c92ca42..2943f09 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -256,17 +256,17 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << "Handling excitation order 0" << std::endl; std::memcpy(&det[0], rdet, sizeof(ulong) * nword); add_det(&det[0]); - if (is_hf_det) { - DetExcParamIndx container; - container.det.resize(nword); - std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); - container.pair_inds.clear(); - container.single_inds.clear(); - ensure_struct_size(det_exc_param_indx, ndet); - det_exc_param_indx[ndet-1] = container; - std::cout << "Added HF det for e=0" << std::endl; - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - } + // if (is_hf_det) { + // DetExcParamIndx container; + // container.det.resize(nword); + // std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); + // container.pair_inds.clear(); + // container.single_inds.clear(); + // ensure_struct_size(det_exc_param_indx, ndet); + // det_exc_param_indx[ndet-1] = container; + // std::cout << "Added HF det for e=0" << std::endl; + // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // } return ; } // Handle excitation order 1 @@ -287,20 +287,20 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // Structure to store determinant and indices of params //corresponding to the pair-excitations & single-excitations - if (is_hf_det) { - DetExcParamIndx container; - container.det.resize(nword); - std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); - container.pair_inds.clear(); - long sidx = calc_sindex(occ, vir); - std::cout << "ndet: " << ndet << " S_index: " << (sidx) << std::endl; - container.single_inds.push_back(sidx); - std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; - std::cout << "ndet" << ndet << std::endl; - ensure_struct_size(det_exc_param_indx, ndet); - det_exc_param_indx[ndet-1] = container; - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - } + // if (is_hf_det) { + // DetExcParamIndx container; + // container.det.resize(nword); + // std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); + // container.pair_inds.clear(); + // long sidx = calc_sindex(occ, vir); + // std::cout << "ndet: " << ndet << " S_index: " << (sidx) << std::endl; + // container.single_inds.push_back(sidx); + // std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; + // std::cout << "ndet" << ndet << std::endl; + // ensure_struct_size(det_exc_param_indx, ndet); + // det_exc_param_indx[ndet-1] = container; + // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // } std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; for (int k = 0; k < nword; ++k) { std::cout << det[k] << " "; @@ -385,11 +385,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << det[k] << " "; } std::cout << std::endl; - if (is_hf_det){ - long pidx = calc_pindex(occ_pair.first, vir_pair.first); - std::cout << "Pair index: " << pidx << std::endl; - det_exc.pair_inds.push_back(pidx); - } + // if (is_hf_det){ + // long pidx = calc_pindex(occ_pair.first, vir_pair.first); + // std::cout << "Pair index: " << pidx << std::endl; + // det_exc.pair_inds.push_back(pidx); + // } } @@ -448,10 +448,10 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ long vir = remaining_virs[vir_comb[idx]]; excite_det(occ, vir, &temp_det[0]); std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; - if (is_hf_det) { - long sidx = calc_sindex(occ, vir); - det_exc.single_inds.push_back(sidx); - } + // if (is_hf_det) { + // long sidx = calc_sindex(occ, vir); + // det_exc.single_inds.push_back(sidx); + // } } add_det(&temp_det[0]); // Print determinant after single excitations @@ -460,13 +460,13 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << temp_det[k] << " "; } std::cout << std::endl; - if (is_hf_det) { - det_exc.det.resize(nword); - std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); - ensure_struct_size(det_exc_param_indx, ndet); - det_exc_param_indx[ndet-1] = det_exc; - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - } + // if (is_hf_det) { + // det_exc.det.resize(nword); + // std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); + // ensure_struct_size(det_exc_param_indx, ndet); + // det_exc_param_indx[ndet-1] = det_exc; + // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // } } } @@ -480,13 +480,13 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::cout << det[k] << " "; } std::cout << std::endl; - if (is_hf_det) { - det_exc.det.resize(nword); - std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); - ensure_struct_size(det_exc_param_indx, ndet); - det_exc_param_indx[ndet-1] = det_exc; - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - } + // if (is_hf_det) { + // det_exc.det.resize(nword); + // std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); + // ensure_struct_size(det_exc_param_indx, ndet); + // det_exc_param_indx[ndet-1] = det_exc; + // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // } } } } @@ -542,10 +542,10 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re ptr = &v_ref[0]; fill_hartreefock_det(nbasis,nocc, ptr); - is_hf_det = true; + // is_hf_det = true; } else { ptr = reinterpret_cast(ref.cast>().request().ptr); - is_hf_det = false; + // is_hf_det = false; } long ndet_old = ndet; add_excited_dets(ptr, exc); From 2e022cc0977db8ac68a0c54cbd6d3f3ff2d332cb Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 10:56:19 -0500 Subject: [PATCH 102/197] Add print statments --- pyci/src/squantop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/squantop.cpp b/pyci/src/squantop.cpp index 59b6e7b..f656593 100644 --- a/pyci/src/squantop.cpp +++ b/pyci/src/squantop.cpp @@ -112,7 +112,7 @@ SQuantOp::SQuantOp(const std::string &filename) { h = reinterpret_cast(h_array.request().ptr); v = reinterpret_cast(v_array.request().ptr); w = reinterpret_cast(w_array.request().ptr); - + std::cout << "size of h: " << h_array.request().size << std::endl; long n1, n2, n3; n1 = nbasis; n2 = n1 * n1; From 2043f735be00f729b46449afe23cf615639a6583 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 10:56:36 -0500 Subject: [PATCH 103/197] change wfn.nvir to nvir in add_row --- pyci/src/sparseop.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 92c5207..6893499 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -571,6 +571,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; + long nvir = nvir_up + nvir_dn; std::cout << "nocc_up: " << nocc_up << ", nocc_dn: " << nocc_dn << std::endl; std::cout << "nvir_up: " << nvir_up << ", nvir_dn: " << nvir_dn << std::endl; std::cout << "Occs: " ; @@ -579,13 +580,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } std::cout << std::endl; std::cout << "Virs: " ; - for (i = 0; i < (nvir_up + nvir_dn); ++i) { + for (i = 0; i < (nvir); ++i) { std::cout << virs[i] << " "; } std::cout << std::endl; long *virs_up = virs; long *virs_dn = nullptr; - for (long i = 0; i < wfn.nvir; ++i) { + for (long i = 0; i < nvir; ++i) { if (virs[i] >= nbasis) { virs_dn = &virs[i]; break; @@ -611,6 +612,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_up[k]; koffset = ioffset + n2 * kk; val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; + std::cout << "ii, kk: " << ii << ", " << kk << std::endl; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; From ecaf9192b77110b9f05ddbc42c43ede29b3aaf18 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 2 Dec 2024 20:28:36 -0500 Subject: [PATCH 104/197] Modify init_overlap --- pyci/src/ap1rogen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 0ec39fa..b7478c6 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -68,9 +68,9 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) std::cout << "Inside init_overlap" << std::endl; // Initialize your class-specific variables here // init_Overlap objective for the AP1roGSDspin_sen-o - nparam = 2 * wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); //paired-doubles + alpha singles - std::cout << "nparam (doubles + S_alpha): " << nparam << std::endl; - nparam += wfn_.nocc_dn * (wfn_.nbasis - wfn_.nocc_dn); // beta singles + nparam = wfn_.nocc_up * (wfn_.nbasis - wfn_.nocc_up); //paired-doubles + std::cout << "nparam (doubles): " << nparam << std::endl; + nparam += wfn_.nocc * (2* wfn_.nbasis - wfn_.nocc); // beta singles std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; nrow = wfn_.nocc_up; ncol = wfn_.nbasis - wfn_.nocc_up; From 60fb83dea362f4851f7f61b0a1ed8d701c2a74d9 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 10:51:39 -0500 Subject: [PATCH 105/197] Form pairs of occ and virs to get param indices for dets not stored in the add_excited_dets --- pyci/src/ap1rogen.cpp | 125 ++++++++++++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 36 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index b7478c6..dcf0261 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,6 +14,7 @@ * along with PyCI. If not, see . */ #include +#include #include namespace pyci { @@ -72,57 +73,109 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) std::cout << "nparam (doubles): " << nparam << std::endl; nparam += wfn_.nocc * (2* wfn_.nbasis - wfn_.nocc); // beta singles std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; - nrow = wfn_.nocc_up; - ncol = wfn_.nbasis - wfn_.nocc_up; - std::cout << "nrow: " << nrow << ", ncol: " << ncol << std::endl; - std::cout << "nconn: " << nconn << std::endl; + // nrow = wfn_.nocc_up; + // ncol = wfn_.nbasis - wfn_.nocc_up; + // std::cout << "nrow: " << nrow << ", ncol: " << ncol << std::endl; + // std::cout << "nconn: " << nconn << std::endl; ovlp.resize(wfn_.ndet); d_ovlp.resize(wfn_.ndet * nparam); - nexc_list.resize(nconn); - hole_list.resize(wfn_.nocc * nconn); //list of all holes - part_list.resize(wfn_.nocc * nconn); //list of all particles + // nexc_list.resize(nconn); + // hole_list.resize(wfn_.nocc * nconn); //list of all holes + // part_list.resize(wfn_.nocc * nconn); //list of all particles std::size_t nword = (ulong)wfn_.nword; + std::unordered_map, DetExcParamIndx> det_map; + + // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) + for (const auto& exc_info : wfn_.det_exc_param_indx) { + det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + } + for (std::size_t idet = 0; idet != nconn; ++idet) { std::vector rdet(wfn_.nword); - fill_hartreefock_det(wfn_.nocc, &rdet[0]); + wfn_.fill_hartreefock_det(wfn_.nocc, &rdet[0]); + std::cout << "After fill_hartreefock_det rdet:" << std::endl; - - // Print the contents of rdet - for (const auto& val : rdet) { - std::cout << val << " "; - } - std::cout << std::endl; + print_vector("rdet", rdet); const ulong *det = wfn_.det_ptr(idet); - ulong word, hword, pword; - // Initialize your class-specific variables here - std::size_t h, p, nexc = 0; - for (std::size_t iword = 0; iword != nword; ++iword) - { - word = rdet[iword] ^ det[iword]; //str for excitation - hword = word & rdet[iword]; //str for hole - pword = word & det[iword]; //str for particle - while(hword){ - h = Ctz(hword); - p = Ctz(pword); - hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); - part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; - hword &= ~(1UL << h); - pword &= ~(1UL << p); - std::cout << "hword" << hword << std::endl; - std::cout << "pword" << pword << std::endl; - std::cout << "nexc: " << nexc << std::endl; - std::cout << "hole_list: " << hole_list[idet * wfn_.nocc_up + nexc] << std::endl; - std::cout << "part_list: " << part_list[idet * wfn_.nocc_up + nexc] << std::endl; - ++nexc; + + std::vector det_vector(det, det + nword); + auto it = det_map.find(det_vector); + if (it != det_map.end()) { + std::cout << "Found det in det_map" << std::endl; + std::cout << "Det: " << det_vector << std::endl; + std::cout << "DetExcParamIndx: " << it->second << std::endl; + } else { + std::cout << "Det not found in det_map" << std::endl; + DetExcParamIndx exc_info; + ulong word, hword, pword; + std::size_t h, p, nexc = 0; + + std::vector holes; + std::vector particles; + + // Collect holes and particles + for (std::size_t iword = 0; iword != nword; ++iword) + { + word = rdet[iword] ^ det[iword]; //str for excitation + hword = word & rdet[iword]; //str for hole + pword = word & det[iword]; //str for particle + while(hword){ + h = Ctz(hword); + p = Ctz(pword); + // hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); + // part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; + + std::size_t hole_idx = h + iword * Size(); + std::size_t part_idx = p + iword * Size() - wfn_.nocc_up; + + holes.push_back(hole_idx); + particles.push_back(part_idx); + + hword &= ~(1UL << h); + pword &= ~(1UL << p); + std::cout << "hword" << hword << std::endl; + std::cout << "pword" << pword << std::endl; + std::cout << "nexc: " << nexc << std::endl; + std::cout << "hole_list: " << hole_idx << std::endl; + std::cout << "part_list: " << part_idx << std::endl; + ++nexc; + } + } + nexc_list[idet] = nexc; + + std::vector> occ_pairs; + for (std::size_t hole in holes) { + std::size_t conjugate = hole + wfn_.nbasis / 2; + if(std::find(holes.begin(), holes.end(), conjugate) != holes.end()) { + occ_pairs.push_back(std::make_pair(hole, conjugate)); + // exc_info.pair_inds.push_back(wfn_.nvir_up * hole); + } } + + std::vector vir_pairs; + for (std::size_t part in particles) { + std::size_t conjugate = part + wfn_.nbasis / 2; + if(std::find(particles.begin(), particles.end(), conjugate) != particles.end()) { + vir_pairs.push_back(std::make_pair(part, conjugate)); + // exc_info.pair_inds.push_back(wfn_.nvir_up * part); + } + } + + for (const auto& pair : occ_pairs) { + for (const auto& vir_pair : vir_pairs) { + exc_info.pair_inds.push_back(wfn_.nvir_up * pair.first + vir_pair.first); + exc_info.pair_inds.push_back(wfn_.nvir_up * pair.second + vir_pair.second); + } + } + + } - nexc_list[idet] = nexc; } } From 687135366ed88ac12c1b9b75559ac665d855cc9e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 11:46:01 -0500 Subject: [PATCH 106/197] Add function to generate combintaitons of holes and particles --- pyci/src/ap1rogen.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index dcf0261..27227b0 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -64,6 +64,19 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSen return; } +void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result) { + std::vector mask(elems.size()); + std::fill(mask.end() - k, mask.end() + k, true); + do { + std::vector combination; + for (std::size_t i = 0; i < elems.size(); ++i) { + if (mask[i]) combination.push_back(elems[i]); + } + result.push_back(combination); + } while (std::next_permutation(mask.begin(), mask.end())); +} + + void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { std::cout << "Inside init_overlap" << std::endl; From 527ee379220f0804edbc60dc0b751bef3cc30be0 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 11:53:20 -0500 Subject: [PATCH 107/197] Add function to generate partition of number of pairs and number of singles --- pyci/include/pyci.h | 3 +++ pyci/src/ap1rogen.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 3b02fee..06d6b55 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -934,6 +934,9 @@ class AP1roGeneralizedSenoObjective : public Objective { const std::vector& , int , std::vector& , std::vector&, long, const NonSingletCI &); + // Generate partitions + std::vector> AP1roGeneralizedSenoObjective::generate_paritions(int , int); + // Initializer for {d_,}overlap variables void init_overlap(const NonSingletCI &); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 27227b0..e60e121 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -76,6 +76,14 @@ void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& } while (std::next_permutation(mask.begin(), mask.end())); } +std::vector> AP1roGeneralizedSenoObjective::generate_paritions(int e, int max_pairs) { + std::vector> partitions; + for (int p = 0; p <= std::min(e / 2 , max_pairs); ++p) { + int s = e - 2 * p; + partitions.emblace_back(p, s); + } + return partitions; +} void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { From 79aaf20c7661a8f04b222adcfbd4754d2395e699 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 12:48:19 -0500 Subject: [PATCH 108/197] Add generate excitations function for generate list of holes and particles --- pyci/include/pyci.h | 5 +++ pyci/src/ap1rogen.cpp | 93 ++++++++++++++++++++++++++++++++----------- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 06d6b55..2dd6683 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -937,6 +937,11 @@ class AP1roGeneralizedSenoObjective : public Objective { // Generate partitions std::vector> AP1roGeneralizedSenoObjective::generate_paritions(int , int); + // Generate excitations + void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& , + const std::vector& , int , std::vector& , + std::vector& ); + // Initializer for {d_,}overlap variables void init_overlap(const NonSingletCI &); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index e60e121..871af9f 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -85,6 +85,46 @@ std::vector> AP1roGeneralizedSenoObjective::generate_paritio return partitions; } +void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, + const std::vector& particles, int excitation_order, std::vector& pair_inds, + std::vector& single_inds) { + int max_pairs = holes.size() / 2; + auto paritions = generate_partitions(excitation_order, max_pairs); + + for (const auto& [num_pairs, num_singles] : partitions) { + // Step 2: Generate combinations of pairs and singles + std::vector> hole_pairs, hole_singles; + std::vector> part_pairs, part_singles; + + generate_combinations(holes, 2, hole_pairs); + generate_combinations(holes, 1, hole_singles); + generate_combinations(particles, 2, part_pairs); + generate_combinations(particles, 1, part_singles); + + // Limit the number of pairs and singles to the requested partition + hole_pairs.resize(std::min(hole_pairs.size(), static_cast(num_pairs))); + hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); + part_pairs.resize(std::min(part_pairs.size(), static_cast(num_pairs))); + part_singles.resize(std::min(part_singles.size(), static_cast(num_singles))); + + // Match pairs and singles + for (const auto& hole_pair : hole_pairs) { + for (const auto& part_pair : part_pairs) { + // Check constraints + pair_inds.push_back(wfn_.nvir_up * hole_pair[0] + part_pair[0]); + //pair_inds.push_back(wfn_.nvir_up * hole_pair[1] + part_pair[1]); + } + } + + for (const auto& hole_single : hole_singles) { + for (const auto& part_single : part_singles) { + // Check constraints + single_inds.push_back(wfn_.nvir_up * wfn_.nocc / 2 + hole_single[0] * wfn_.nvir + part_single[0]); + } + } + + } + void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { std::cout << "Inside init_overlap" << std::endl; @@ -170,30 +210,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } nexc_list[idet] = nexc; - std::vector> occ_pairs; - for (std::size_t hole in holes) { - std::size_t conjugate = hole + wfn_.nbasis / 2; - if(std::find(holes.begin(), holes.end(), conjugate) != holes.end()) { - occ_pairs.push_back(std::make_pair(hole, conjugate)); - // exc_info.pair_inds.push_back(wfn_.nvir_up * hole); - } - } - - std::vector vir_pairs; - for (std::size_t part in particles) { - std::size_t conjugate = part + wfn_.nbasis / 2; - if(std::find(particles.begin(), particles.end(), conjugate) != particles.end()) { - vir_pairs.push_back(std::make_pair(part, conjugate)); - // exc_info.pair_inds.push_back(wfn_.nvir_up * part); - } - } - - for (const auto& pair : occ_pairs) { - for (const auto& vir_pair : vir_pairs) { - exc_info.pair_inds.push_back(wfn_.nvir_up * pair.first + vir_pair.first); - exc_info.pair_inds.push_back(wfn_.nvir_up * pair.second + vir_pair.second); - } - } + generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds); + wfn_.det_exc_param_indx.push_back(exc_info); } @@ -304,3 +322,30 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x } } // namespace pyci + + + +// std::vector> occ_pairs; +// for (std::size_t hole in holes) { +// std::size_t conjugate = hole + wfn_.nbasis / 2; +// if(std::find(holes.begin(), holes.end(), conjugate) != holes.end()) { +// occ_pairs.push_back(std::make_pair(hole, conjugate)); +// // exc_info.pair_inds.push_back(wfn_.nvir_up * hole); +// } +// } + +// std::vector vir_pairs; +// for (std::size_t part in particles) { +// std::size_t conjugate = part + wfn_.nbasis / 2; +// if(std::find(particles.begin(), particles.end(), conjugate) != particles.end()) { +// vir_pairs.push_back(std::make_pair(part, conjugate)); +// // exc_info.pair_inds.push_back(wfn_.nvir_up * part); +// } +// } + +// for (const auto& pair : occ_pairs) { +// for (const auto& vir_pair : vir_pairs) { +// exc_info.pair_inds.push_back(wfn_.nvir_up * pair.first + vir_pair.first); +// exc_info.pair_inds.push_back(wfn_.nvir_up * pair.second + vir_pair.second); +// } +// } From aa484abe43aea52f99541eb9f4ae0b3169f04699 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 13:19:27 -0500 Subject: [PATCH 109/197] Add function to calculate permanet using Rysers algorithm given parameter indices --- pyci/src/ap1rogen.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 871af9f..04b2f53 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -218,6 +218,33 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } } + +double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector>& + excitation_inds, const double* x) { + std::size_t num_excitations = excitation_inds.size(); + if (num_excitations == 0) return 1.0; + + double permanent = 0.0; + std::size_t subset_count = 1UL << num_excitations; + + for (std::size_t subset = 0; subset < subset_count; ++subset) { + double rowsumprod = 1.0; + + for (std::size_t i = 0; j < num_excitations; ++j) { + double rowsum = 0.0; + for (std::size_t j = 0; j < num_excitations; ++j) { + if (subset & (1UL << j)) { + rowsum += x[excitation_inds[j]]; + } + } + rowsumprod *= rowsum; + } + permanent += rowsumprod * (1 - ((__builtin_popcount(subset) & 1) << 1)); + } + permanent *= ((num_excitations % 2 == 1) ? -1 : 1); + return permanent; +} + void AP1roGeneralizedSenoObjective::overlap(const size_t ndet, const double *x, double *y) { // x == parameters p_j From 5d9bc67afc883cd5a3f04558df747e3153e5d971 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 13:37:35 -0500 Subject: [PATCH 110/197] Update the overalp function --- pyci/src/ap1rogen.cpp | 70 +++++++++++++------------------------------ 1 file changed, 20 insertions(+), 50 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 04b2f53..a4c8fdd 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -134,20 +134,11 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) std::cout << "nparam (doubles): " << nparam << std::endl; nparam += wfn_.nocc * (2* wfn_.nbasis - wfn_.nocc); // beta singles std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; - // nrow = wfn_.nocc_up; - // ncol = wfn_.nbasis - wfn_.nocc_up; - // std::cout << "nrow: " << nrow << ", ncol: " << ncol << std::endl; - // std::cout << "nconn: " << nconn << std::endl; ovlp.resize(wfn_.ndet); d_ovlp.resize(wfn_.ndet * nparam); - // nexc_list.resize(nconn); - // hole_list.resize(wfn_.nocc * nconn); //list of all holes - // part_list.resize(wfn_.nocc * nconn); //list of all particles - std::size_t nword = (ulong)wfn_.nword; - std::unordered_map, DetExcParamIndx> det_map; // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) @@ -189,8 +180,6 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) while(hword){ h = Ctz(hword); p = Ctz(pword); - // hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); - // part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; std::size_t hole_idx = h + iword * Size(); std::size_t part_idx = p + iword * Size() - wfn_.nocc_up; @@ -212,8 +201,6 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds); wfn_.det_exc_param_indx.push_back(exc_info); - - } } } @@ -245,45 +232,28 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector det_vector(det, det + wfn_.nword); - for (k=0; k < c; ++k) - { - rowsumprod = 1.0; - for (i = 0; i < m; ++i) - { - rowsum = 1.0; - for (j = 0; j < m; ++j) - { - if (k & (1UL << j)) - { - rowsum *= x[ncol * hlist[j] + plist[i]]; - } } - rowsumprod += rowsum; - } - out += rowsumprod * (1 - ((__builtin_popcount(k) & 1) << 1)); - } - y[idet] = out * ((m % 2 == 1) ? -1 : 1); + // Find corresponding DetExcParamIndx for the current determinant + auto it = det_map.find(det_vector); + + // Access the excitation parameter indices + const decltype(it->second)& exc_info = it->second; + + double pair_permanent = permanent_calculation(exc_info.pair_inds, x, exc_info.pair_inds.size()); + double single_permanent = permanent_calculation(exc_info.single_inds, x, exc_info.single_inds.size()); + + y[idet] = pair_permanent * single_permanent; + } else { + std::cout << "Det" << det_vector << " not found in det_map" << std::endl; + y[idet] = 0.0; + + } } } From c39d15c9ee76acb0269c201078754549fb7e372e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 13:47:25 -0500 Subject: [PATCH 111/197] Add helper function compute_derivative --- pyci/include/pyci.h | 4 ++++ pyci/src/ap1rogen.cpp | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 2dd6683..6a3d953 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -955,6 +955,10 @@ class AP1roGeneralizedSenoObjective : public Objective { // Helper function for d_overlap double compute_derivative(const std::vector& excitation_indices, const double*, std::size_t ); + double AP1roGeneralizedSenoObjective::compute_derivative( + const std::vector& excitation_indices, + const double*, std::size_t, std::size_t ); + // Overlap gradient function // virtual void d_overlap(const NonSingletCI &, const size_t, const double *x, double *y); virtual void d_overlap(const size_t, const double *x, double *y); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index a4c8fdd..a02e7a3 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -257,6 +257,23 @@ void AP1roGeneralizedSenoObjective::overlap(const size_t ndet, const double *x, } } + +double AP1roGeneralizedSenoObjective::compute_derivative( + const std::vector& excitation_inds, + const double* x, + std::size_t num_excitations, + std::size_t excitation_idx) { + + double derivative = 0.0; + + std::vector modified_x(x, x + wfn_.nparam); + modified_x[excitation_inds[excitation_idx]] = 1.0; + derivative = permanent_calculation(excitation_inds, modified_x.data()); + + return derivative; +} + + void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y) { // x == parameters p_j From 3409e744a4663bf8f08b4d1d38d64af1f52ffc02 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 14:12:08 -0500 Subject: [PATCH 112/197] Fix template definition for generation combinations function --- pyci/src/ap1rogen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index a02e7a3..f7e66ec 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -64,7 +64,8 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSen return; } -void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result) { +template +void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result) { std::vector mask(elems.size()); std::fill(mask.end() - k, mask.end() + k, true); do { From f79eeb22f962aac3259fd645026bab2d6949b32f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 14:13:16 -0500 Subject: [PATCH 113/197] Fix typo --- pyci/src/ap1rogen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index f7e66ec..371a219 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,7 +14,7 @@ * along with PyCI. If not, see . */ #include -#include +#include #include namespace pyci { From 4d4a8280ce9b0a7680e68a701f11d98b688f4418 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 14:17:07 -0500 Subject: [PATCH 114/197] Add d_overlap function --- pyci/src/ap1rogen.cpp | 98 +++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 371a219..26da9e2 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -275,67 +275,63 @@ double AP1roGeneralizedSenoObjective::compute_derivative( } -void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y) -{ - // x == parameters p_j - // y == unwrapped overlap objective ∂σ_i/∂p_j +void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ + // Loop over each determinant + for (std::size_t idet = 0; idet != ndet; ++idet) + { + // Retrieve the corresponding determinant + const ulong* det = wfn_.det_ptr(idet); + std::vector det_vector(det, det + wfn_.nword); + + // Find corresponding DetExcParamIndx for the current determinant + auto it = det_map.find(det_vector); + + // Ensure we have the excitation parameters for this determinant + if (it != det_map.end()) { + const DetExcParamIndx& exc_info = it->second; + + // Loop over each parameter (paired and single excitations) + std::size_t param_index = 0; - std::size_t m, n, i, j, k, c; - std::size_t *hlist, *plist; - double rowsum, rowsumprod, out; + // Derivative for paired excitations + for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { + // Get the excitation index for the pair + const std::size_t excitation_idx = exc_info.pair_inds[i]; - for (std::size_t idet = 0; idet != ndet; ++idet){ - for (std::size_t iparam = 0; iparam != nparam; ++iparam){ - hlist = &hole_list[idet * nrow]; - plist = &part_list[idet * nrow]; - - m = nexc_list[idet]; - if (m == 0){ - y[ndet * iparam + idet] = 0; - continue; - } + // Compute the derivative of the permanent with respect to this excitation + double derivative = compute_derivative(exc_info.pair_inds, x, exc_info.pair_inds.size(), excitation_idx); + + // Store the result in the output vector d_ovlp (size ndet * nparam) + y[idet * nparam + param_index] = derivative; - std::vector rows; - std::vector cols; - for (i = 0; i < m; ++i){ - if (hlist[i] != iparam / ncol){ - rows.push_back(hlist[i]); - } - if (plist[i] != iparam % ncol){ - cols.push_back(plist[i]); - } + ++param_index; } - m = rows.size(); - n = cols.size(); - if (m == 0 && n == 0) { - y[ndet * iparam + idet] = 1; - continue; - } else if (m == nexc_list[idet] || n == nexc_list[idet] || m != n) { - y[ndet * iparam + idet] = 0; - continue; + + // Derivative for single excitations + for (std::size_t i = 0; i < exc_info.single_inds.size(); ++i) { + // Get the excitation index for the single + const std::size_t excitation_idx = exc_info.single_inds[i]; + + // Compute the derivative of the permanent with respect to this excitation + double derivative = compute_derivative(exc_info.single_inds, x, exc_info.single_inds.size(), excitation_idx); + + // Store the result in the output vector d_ovlp (size ndet * nparam) + y[idet * nparam + param_index] = derivative; + + ++param_index; } - out = 0; - - c = 1UL << m; - for (k = 0; k < c; ++k){ - rowsumprod = 1.0; - for (i = 0; i < m; ++i){ - rowsum = 1.0; - for (j = 0; j < m; ++j){ - if (k & (1UL << j)){ - rowsum *= x[ncol * hlist[j] + plist[i]]; - } - } - rowsumprod *= rowsum; - } - out += rowsumprod * (1 - ((__builtin_popcountll(k) & 1) << 1)); + } + else { + std::cout << "Determinant " << idet << " not found in det_map" << std::endl; + // Set all derivatives to zero if determinant is not found + for (std::size_t i = 0; i < nparam; ++i) { + y[idet * nparam + i] = 0.0; } - y[ndet * iparam + idet] = out * ((m % 2 == 1) ? -1 : 1); - } } } + } // namespace pyci From 5ab9833febee4a84e3261abc6fcb58e44b1a095f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 14:33:33 -0500 Subject: [PATCH 115/197] Fix typos --- pyci/include/pyci.h | 2 +- pyci/src/ap1rogen.cpp | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 6a3d953..ffc571d 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -940,7 +940,7 @@ class AP1roGeneralizedSenoObjective : public Objective { // Generate excitations void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& , const std::vector& , int , std::vector& , - std::vector& ); + std::vector&, std::size_t, std::size_t, std::size_t ); // Initializer for {d_,}overlap variables void init_overlap(const NonSingletCI &); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 26da9e2..cc1d366 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -49,8 +49,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_ // Copy Constructor // obj is the constant reference to another object to be copied AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGeneralizedSenoObjective &obj) -: Objective::Objective(obj), nrow(obj.nrow), ncol(obj.ncol), - nexc_list(obj.nexc_list), hole_list(obj.hole_list), part_list(obj.part_list) +: Objective::Objective(obj), nexc_list(obj.nexc_list) { return; } @@ -58,14 +57,13 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGenerali // Move constructor // obj is the rvalue reference to another object to be moved AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&obj) noexcept -: Objective::Objective(obj), nrow(std::exchange(obj.nrow, 0)), ncol(std::exchange(obj.ncol, 0)), - nexc_list(std::move(obj.nexc_list)), hole_list(std::move(obj.hole_list)), part_list(std::move(obj.part_list)) +: Objective::Objective(obj), nexc_list(std::move(obj.nexc_list)) { return; } template -void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result) { +void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result) { std::vector mask(elems.size()); std::fill(mask.end() - k, mask.end() + k, true); do { @@ -77,20 +75,20 @@ void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector> AP1roGeneralizedSenoObjective::generate_paritions(int e, int max_pairs) { +std::vector> AP1roGeneralizedSenoObjective::generate_partitions(int e, int max_pairs) { std::vector> partitions; for (int p = 0; p <= std::min(e / 2 , max_pairs); ++p) { int s = e - 2 * p; - partitions.emblace_back(p, s); + partitions.emplace_back(p, s); } return partitions; } void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, const std::vector& particles, int excitation_order, std::vector& pair_inds, - std::vector& single_inds) { + std::vector& single_inds, size_t nocc, size_t nvir_up, size_t nvir) { int max_pairs = holes.size() / 2; - auto paritions = generate_partitions(excitation_order, max_pairs); + auto partitions = generate_partitions(excitation_order, max_pairs); for (const auto& [num_pairs, num_singles] : partitions) { // Step 2: Generate combinations of pairs and singles @@ -112,7 +110,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector Date: Tue, 3 Dec 2024 15:52:33 -0500 Subject: [PATCH 116/197] Fix typos --- pyci/include/pyci.h | 2 +- pyci/src/ap1rogen.cpp | 69 +++++++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index ffc571d..9ed3226 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -943,7 +943,7 @@ class AP1roGeneralizedSenoObjective : public Objective { std::vector&, std::size_t, std::size_t, std::size_t ); // Initializer for {d_,}overlap variables - void init_overlap(const NonSingletCI &); + void init_overlap(NonSingletCI &); // Permanent calculation: Ryser's Algorithm double permanent_calculation(const std::vector&, const double* ); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index cc1d366..8cc037f 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -85,8 +85,8 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti } void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, - const std::vector& particles, int excitation_order, std::vector& pair_inds, - std::vector& single_inds, size_t nocc, size_t nvir_up, size_t nvir) { + const std::vector& particles, int excitation_order, std::vector& pair_inds, + std::vector& single_inds, long nocc, long nvir_up, long nvir) { int max_pairs = holes.size() / 2; auto partitions = generate_partitions(excitation_order, max_pairs); @@ -125,7 +125,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector rdet(wfn_.nword); - wfn_.fill_hartreefock_det(wfn_.nocc, &rdet[0]); + wfn_.fill_hartreefock_det(wfn_.nbasis, wfn_.nocc, &rdet[0]); std::cout << "After fill_hartreefock_det rdet:" << std::endl; - print_vector("rdet", rdet); + //print_vector("rdet", rdet); const ulong *det = wfn_.det_ptr(idet); @@ -160,8 +160,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) auto it = det_map.find(det_vector); if (it != det_map.end()) { std::cout << "Found det in det_map" << std::endl; - std::cout << "Det: " << det_vector << std::endl; - std::cout << "DetExcParamIndx: " << it->second << std::endl; + // std::cout << "Det: " << det_vector << std::endl; + // std::cout << "DetExcParamIndx: " << it->second << std::endl; } else { std::cout << "Det not found in det_map" << std::endl; DetExcParamIndx exc_info; @@ -199,15 +199,14 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } nexc_list[idet] = nexc; - generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, wfn_.nvir_up); + generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, wfn_.nvir_up, wfn_.nvir); wfn_.det_exc_param_indx.push_back(exc_info); } } } -double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector>& - excitation_inds, const double* x) { +double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, const double* x) { std::size_t num_excitations = excitation_inds.size(); if (num_excitations == 0) return 1.0; @@ -217,7 +216,7 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector det_vector(det, det + wfn_.nword); // Find corresponding DetExcParamIndx for the current determinant + std::unordered_map, DetExcParamIndx> det_map; + // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) + for (const auto& exc_info : wfn_.det_exc_param_indx) { + det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + } + auto it = det_map.find(det_vector); - // Access the excitation parameter indices - const decltype(it->second)& exc_info = it->second; + if (it != det_map.end()) { + // Access the excitation parameter indices + const DetExcParamIndx& exc_info = it->second; - double pair_permanent = permanent_calculation(exc_info.pair_inds, x, exc_info.pair_inds.size()); - double single_permanent = permanent_calculation(exc_info.single_inds, x, exc_info.single_inds.size()); + double pair_permanent = permanent_calculation(exc_info.pair_inds, x); + double single_permanent = permanent_calculation(exc_info.single_inds, x); - y[idet] = pair_permanent * single_permanent; - } else { - std::cout << "Det" << det_vector << " not found in det_map" << std::endl; - y[idet] = 0.0; + y[idet] = pair_permanent * single_permanent; + } else { + // std::cout << "Det" << det_vector << " not found in det_map" << std::endl; + y[idet] = 0.0; - } + } } } double AP1roGeneralizedSenoObjective::compute_derivative( - const std::vector& excitation_inds, + const std::vector& excitation_inds, const double* x, - std::size_t num_excitations, std::size_t excitation_idx) { double derivative = 0.0; - std::vector modified_x(x, x + wfn_.nparam); + std::vector modified_x(x, x + nparam); modified_x[excitation_inds[excitation_idx]] = 1.0; derivative = permanent_calculation(excitation_inds, modified_x.data()); @@ -274,13 +279,21 @@ double AP1roGeneralizedSenoObjective::compute_derivative( } -void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ +void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ // Loop over each determinant for (std::size_t idet = 0; idet != ndet; ++idet) { // Retrieve the corresponding determinant const ulong* det = wfn_.det_ptr(idet); std::vector det_vector(det, det + wfn_.nword); + + + // Find corresponding DetExcParamIndx for the current determinant + std::unordered_map, DetExcParamIndx> det_map; + // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) + for (const auto& exc_info : wfn_.det_exc_param_indx) { + det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + } // Find corresponding DetExcParamIndx for the current determinant auto it = det_map.find(det_vector); @@ -298,7 +311,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x const std::size_t excitation_idx = exc_info.pair_inds[i]; // Compute the derivative of the permanent with respect to this excitation - double derivative = compute_derivative(exc_info.pair_inds, x, exc_info.pair_inds.size(), excitation_idx); + double derivative = compute_derivative(exc_info.pair_inds, x, excitation_idx); // Store the result in the output vector d_ovlp (size ndet * nparam) y[idet * nparam + param_index] = derivative; @@ -312,7 +325,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x const std::size_t excitation_idx = exc_info.single_inds[i]; // Compute the derivative of the permanent with respect to this excitation - double derivative = compute_derivative(exc_info.single_inds, x, exc_info.single_inds.size(), excitation_idx); + double derivative = compute_derivative(exc_info.single_inds, x, excitation_idx); // Store the result in the output vector d_ovlp (size ndet * nparam) y[idet * nparam + param_index] = derivative; From 984726dd017c9c48d8da9f23bf6a5f92cad860ae Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 19:47:51 -0500 Subject: [PATCH 117/197] Add det exc details entry at indx ndet everytime a new det is added in add_excited_dets, to avoid hashing through unordered_map --- pyci/src/ap1rogen.cpp | 53 ++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 8cc037f..a5e7446 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -135,8 +135,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) nparam += wfn_.nocc * (2* wfn_.nbasis - wfn_.nocc); // beta singles std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; - ovlp.resize(wfn_.ndet); - d_ovlp.resize(wfn_.ndet * nparam); + // ovlp.resize(wfn_.ndet); + // d_ovlp.resize(wfn_.ndet * nparam); std::size_t nword = (ulong)wfn_.nword; std::unordered_map, DetExcParamIndx> det_map; @@ -156,12 +156,14 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) const ulong *det = wfn_.det_ptr(idet); - std::vector det_vector(det, det + nword); - auto it = det_map.find(det_vector); - if (it != det_map.end()) { - std::cout << "Found det in det_map" << std::endl; - // std::cout << "Det: " << det_vector << std::endl; - // std::cout << "DetExcParamIndx: " << it->second << std::endl; + // std::vector det_vector(det, det + nword); + // auto it = det_map.find(det_vector); + // if (it != det_map.end()) { + // std::cout << "Found det in det_map" << std::endl; + // // std::cout << "Det: " << det_vector << std::endl; + // // std::cout << "DetExcParamIndx: " << it->second << std::endl; + if (idet < wfn_.det_exc_param_indx.size()) { + std::cout << "Det found in det_map" << std::endl; } else { std::cout << "Det not found in det_map" << std::endl; DetExcParamIndx exc_info; @@ -236,18 +238,18 @@ void AP1roGeneralizedSenoObjective::overlap(const NonSingletCI &wfn_, const doub //Retrieve the DetExcParamIndx object from the hash map const ulong* det = wfn_.det_ptr(idet); - std::vector det_vector(det, det + wfn_.nword); - // Find corresponding DetExcParamIndx for the current determinant - std::unordered_map, DetExcParamIndx> det_map; - // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) - for (const auto& exc_info : wfn_.det_exc_param_indx) { - det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - } + // // std::vector det_vector(det, det + wfn_.nword); + // // Find corresponding DetExcParamIndx for the current determinant + // std::unordered_map, DetExcParamIndx> det_map; + // // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) + // for (const auto& exc_info : wfn_.det_exc_param_indx) { + // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + // } - auto it = det_map.find(det_vector); + // auto it = det_map.find(det_vector); - if (it != det_map.end()) { + if (idet < wfn_.det_exc_param_indx.size()) { // Access the excitation parameter indices const DetExcParamIndx& exc_info = it->second; @@ -285,21 +287,20 @@ void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const si { // Retrieve the corresponding determinant const ulong* det = wfn_.det_ptr(idet); - std::vector det_vector(det, det + wfn_.nword); - + // std::vector det_vector(det, det + wfn_.nword); // Find corresponding DetExcParamIndx for the current determinant - std::unordered_map, DetExcParamIndx> det_map; - // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) - for (const auto& exc_info : wfn_.det_exc_param_indx) { - det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - } + // std::unordered_map, DetExcParamIndx> det_map; + // // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) + // for (const auto& exc_info : wfn_.det_exc_param_indx) { + // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + // } // Find corresponding DetExcParamIndx for the current determinant - auto it = det_map.find(det_vector); + // auto it = det_map.find(det_vector); // Ensure we have the excitation parameters for this determinant - if (it != det_map.end()) { + if (idet < wfn_.det_exc_param_indx.size()) { const DetExcParamIndx& exc_info = it->second; // Loop over each parameter (paired and single excitations) From 2d9997fff9d7870a22fba20a1df4299b73557bbc Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 20:02:26 -0500 Subject: [PATCH 118/197] Recover the original definition of overlap and d_overlap function, discard dependency on the wfn object input --- pyci/src/ap1rogen.cpp | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index a5e7446..725001e 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -141,8 +141,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) std::size_t nword = (ulong)wfn_.nword; std::unordered_map, DetExcParamIndx> det_map; - // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) - for (const auto& exc_info : wfn_.det_exc_param_indx) { + // Populate the hash map (assume det_exc_param_indx is iterable) + for (const auto& exc_info : det_exc_param_indx) { det_map[exc_info.det] = exc_info; // Use exc_info.det as the key } @@ -154,7 +154,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) std::cout << "After fill_hartreefock_det rdet:" << std::endl; //print_vector("rdet", rdet); - const ulong *det = wfn_.det_ptr(idet); + // const ulong *det = det_ptr(idet); // std::vector det_vector(det, det + nword); // auto it = det_map.find(det_vector); @@ -162,7 +162,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) // std::cout << "Found det in det_map" << std::endl; // // std::cout << "Det: " << det_vector << std::endl; // // std::cout << "DetExcParamIndx: " << it->second << std::endl; - if (idet < wfn_.det_exc_param_indx.size()) { + if (idet < det_exc_param_indx.size()) { std::cout << "Det found in det_map" << std::endl; } else { std::cout << "Det not found in det_map" << std::endl; @@ -202,7 +202,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) nexc_list[idet] = nexc; generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, wfn_.nvir_up, wfn_.nvir); - wfn_.det_exc_param_indx.push_back(exc_info); + det_exc_param_indx.push_back(exc_info); } } } @@ -233,23 +233,25 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector det_vector(det, det + wfn_.nword); // // Find corresponding DetExcParamIndx for the current determinant // std::unordered_map, DetExcParamIndx> det_map; - // // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) - // for (const auto& exc_info : wfn_.det_exc_param_indx) { + // // Populate the hash map (assume det_exc_param_indx is iterable) + // for (const auto& exc_info : det_exc_param_indx) { // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key // } // auto it = det_map.find(det_vector); - if (idet < wfn_.det_exc_param_indx.size()) { + if (idet < det_exc_param_indx.size()) { // Access the excitation parameter indices const DetExcParamIndx& exc_info = it->second; @@ -281,18 +283,20 @@ double AP1roGeneralizedSenoObjective::compute_derivative( } -void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ +// void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ +void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ + // Loop over each determinant for (std::size_t idet = 0; idet != ndet; ++idet) { // Retrieve the corresponding determinant - const ulong* det = wfn_.det_ptr(idet); + // const ulong* det = det_ptr(idet); // std::vector det_vector(det, det + wfn_.nword); // Find corresponding DetExcParamIndx for the current determinant // std::unordered_map, DetExcParamIndx> det_map; - // // Populate the hash map (assume wfn_.det_exc_param_indx is iterable) - // for (const auto& exc_info : wfn_.det_exc_param_indx) { + // // Populate the hash map (assume det_exc_param_indx is iterable) + // for (const auto& exc_info : det_exc_param_indx) { // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key // } @@ -300,7 +304,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const si // auto it = det_map.find(det_vector); // Ensure we have the excitation parameters for this determinant - if (idet < wfn_.det_exc_param_indx.size()) { + if (idet < det_exc_param_indx.size()) { const DetExcParamIndx& exc_info = it->second; // Loop over each parameter (paired and single excitations) From 8e09435fae393a548959ddb33870c38c7fea64e3 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 21:32:19 -0500 Subject: [PATCH 119/197] Correct declaration of det_param_indx and init_overlap function for AP1roGen Objective --- pyci/include/pyci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 9ed3226..ffc571d 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -943,7 +943,7 @@ class AP1roGeneralizedSenoObjective : public Objective { std::vector&, std::size_t, std::size_t, std::size_t ); // Initializer for {d_,}overlap variables - void init_overlap(NonSingletCI &); + void init_overlap(const NonSingletCI &); // Permanent calculation: Ryser's Algorithm double permanent_calculation(const std::vector&, const double* ); From 794284df05da6c3890bc470b90959d14ca9c2c56 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 3 Dec 2024 21:33:51 -0500 Subject: [PATCH 120/197] Correct access to the det_exc_param_indx --- pyci/src/ap1rogen.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 725001e..97ef3dd 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -49,7 +49,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_ // Copy Constructor // obj is the constant reference to another object to be copied AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGeneralizedSenoObjective &obj) -: Objective::Objective(obj), nexc_list(obj.nexc_list) +: Objective::Objective(obj), nexc_list(obj.nexc_list), det_exc_param_indx(obj.det_exc_param_indx) { return; } @@ -57,7 +57,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGenerali // Move constructor // obj is the rvalue reference to another object to be moved AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&obj) noexcept -: Objective::Objective(obj), nexc_list(std::move(obj.nexc_list)) +: Objective::Objective(obj), nexc_list(std::move(obj.nexc_list)), det_exc_param_indx(std::move(obj.det_exc_param_indx)) { return; } @@ -125,7 +125,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector, DetExcParamIndx> det_map; + long nb = wfn_.nbasis; + long nocc = wfn_.nocc; + // std::unordered_map, DetExcParamIndx> det_map; // Populate the hash map (assume det_exc_param_indx is iterable) - for (const auto& exc_info : det_exc_param_indx) { - det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - } + // for (const auto& exc_info : det_exc_param_indx) { + // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + // } for (std::size_t idet = 0; idet != nconn; ++idet) { - std::vector rdet(wfn_.nword); - wfn_.fill_hartreefock_det(wfn_.nbasis, wfn_.nocc, &rdet[0]); + std::vector rdet(nword); + wfn_.fill_hartreefock_det(nb, nocc, &rdet[0]); std::cout << "After fill_hartreefock_det rdet:" << std::endl; //print_vector("rdet", rdet); - // const ulong *det = det_ptr(idet); + const ulong *det = wfn_.det_ptr(idet); // std::vector det_vector(det, det + nword); // auto it = det_map.find(det_vector); @@ -202,7 +204,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(NonSingletCI &wfn_) nexc_list[idet] = nexc; generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, wfn_.nvir_up, wfn_.nvir); - det_exc_param_indx.push_back(exc_info); + det_exc_param_indx[idet] = exc_info; } } } @@ -236,7 +238,7 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vectorsecond; + const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; double pair_permanent = permanent_calculation(exc_info.pair_inds, x); double single_permanent = permanent_calculation(exc_info.single_inds, x); @@ -305,7 +307,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { - const DetExcParamIndx& exc_info = it->second; + const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; // Loop over each parameter (paired and single excitations) std::size_t param_index = 0; From 0ea2f446d482c57a1333ff358d2418f8ce705a95 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 4 Dec 2024 12:38:19 -0500 Subject: [PATCH 121/197] Add print statement --- pyci/src/ap1rogen.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 97ef3dd..aa5cff9 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -165,9 +165,12 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) // // std::cout << "Det: " << det_vector << std::endl; // // std::cout << "DetExcParamIndx: " << it->second << std::endl; if (idet < det_exc_param_indx.size()) { - std::cout << "Det found in det_map" << std::endl; + std::cout << "idet: " << idet << " found in det_map" << std::endl; } else { - std::cout << "Det not found in det_map" << std::endl; + for (std::size_t k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << "iDet: " << idet << " not found in det_map" << std::endl; DetExcParamIndx exc_info; ulong word, hword, pword; std::size_t h, p, nexc = 0; @@ -193,8 +196,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) hword &= ~(1UL << h); pword &= ~(1UL << p); - std::cout << "hword" << hword << std::endl; - std::cout << "pword" << pword << std::endl; + std::cout << "hword: " << hword << std::endl; + std::cout << "pword: " << pword << std::endl; std::cout << "nexc: " << nexc << std::endl; std::cout << "hole_list: " << hole_idx << std::endl; std::cout << "part_list: " << part_idx << std::endl; From 727057a894300097f4515965a465138939e00a4d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 8 Dec 2024 13:04:38 -0500 Subject: [PATCH 122/197] Add extra keyword wfntype for pyci.sparse_op call for nonsingletci type wfn --- pyci/fanci/fanci.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index d9c1ed5..5227963 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -200,7 +200,7 @@ def __init__( wfn = fill_wavefunction(wfn, nproj, fill) # Compute CI matrix operator with nproj rows and len(wfn) columns - ci_op = pyci.sparse_op(ham, wfn, nrow=nproj, ncol=len(wfn), symmetric=False) + ci_op = pyci.sparse_op(ham, wfn, nrow=nproj, ncol=len(wfn), symmetric=False, wfntype="nonsingletci") # Compute arrays of occupations sspace = wfn.to_occ_array() From d6ededc043b0f9b57e1f31a36981d8f413ebd04e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 8 Dec 2024 18:49:47 -0500 Subject: [PATCH 123/197] Add condition for num_singles in generate partitions; restore det_exc_param_indx storage, ensure its size before new entry --- pyci/src/ap1rogen.cpp | 107 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 19 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index aa5cff9..7ce9da4 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -79,7 +79,9 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti std::vector> partitions; for (int p = 0; p <= std::min(e / 2 , max_pairs); ++p) { int s = e - 2 * p; - partitions.emplace_back(p, s); + if (s <= max_pairs) { + partitions.emplace_back(p, s); + } } return partitions; } @@ -87,11 +89,30 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, const std::vector& particles, int excitation_order, std::vector& pair_inds, std::vector& single_inds, long nocc, long nvir_up, long nvir) { + std::cout << "\nInside generate_excitations" << std::endl; + std::cout << "holes:" ; + for (const auto& hole : holes) { + std::cout << hole << " "; + } + std::cout << std::endl; + std::cout << "particles:" ; + for (const auto& particle : particles) { + std::cout << particle << " "; + } + std::cout << std::endl; int max_pairs = holes.size() / 2; auto partitions = generate_partitions(excitation_order, max_pairs); + std::cout << "Generated partitions" << std::endl; + + std::cout << "Partitions: " << std::endl; + for (const auto& [num_pairs, num_singles] : partitions) { + std::cout << num_pairs << " " << num_singles << std::endl; + } for (const auto& [num_pairs, num_singles] : partitions) { // Step 2: Generate combinations of pairs and singles + std::cout << "Generating combinations of pairs and singles" << std::endl; + std::cout << "num_pairs: " << num_pairs << ", num_singles: " << num_singles << std::endl; std::vector> hole_pairs, hole_singles; std::vector> part_pairs, part_singles; @@ -100,6 +121,15 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector(num_pairs))); hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); @@ -109,6 +139,8 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector rdet(nword); + AlignedVector rdet(nword); wfn_.fill_hartreefock_det(nb, nocc, &rdet[0]); - std::cout << "After fill_hartreefock_det rdet:" << std::endl; - //print_vector("rdet", rdet); + // std::cout << "After fill_hartreefock_det rdet:" ; + // for (std::size_t k = 0; k < nword; ++k) { + // std::cout << rdet[k] << " "; + // } + // std::cout << std::endl; + //wfn_.print_vector("rdet", rdet); const ulong *det = wfn_.det_ptr(idet); @@ -164,14 +209,29 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) // std::cout << "Found det in det_map" << std::endl; // // std::cout << "Det: " << det_vector << std::endl; // // std::cout << "DetExcParamIndx: " << it->second << std::endl; - if (idet < det_exc_param_indx.size()) { - std::cout << "idet: " << idet << " found in det_map" << std::endl; + // std::cout << "from storage: " << det_exc_param_indx[idet].det << std::endl; + ensure_struct_size(det_exc_param_indx, idet+1); + + if (!det_exc_param_indx[idet].det.empty()) { + std::cout << "\nidet: " << idet << " found in det_map" << std::endl; + std::cout << "Det from wfn: "; + for (std::size_t k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << std::endl; + std::cout << "det_exc_param_indx[idet].det: "; + for (std::size_t k = 0; k < nword; ++k) { + std::cout << det_exc_param_indx[idet].det[k] << " "; + } + std::cout << std::endl; + } else { + std::cout << "\nDet: " ; for (std::size_t k = 0; k < nword; ++k) { std::cout << det[k] << " "; } - std::cout << "iDet: " << idet << " not found in det_map" << std::endl; - DetExcParamIndx exc_info; + std::cout << ", at iDet: " << idet << ", not found in det_exc_param_indx" << std::endl; + ulong word, hword, pword; std::size_t h, p, nexc = 0; @@ -184,29 +244,38 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) word = rdet[iword] ^ det[iword]; //str for excitation hword = word & rdet[iword]; //str for hole pword = word & det[iword]; //str for particle + std::cout << "word: " << word << std::endl; + std::cout << "hword: " << hword << std::endl; + std::cout << "pword: " << pword << std::endl; while(hword){ h = Ctz(hword); p = Ctz(pword); std::size_t hole_idx = h + iword * Size(); - std::size_t part_idx = p + iword * Size() - wfn_.nocc_up; + std::size_t part_idx = p + iword * Size(); // - nocc_up; holes.push_back(hole_idx); particles.push_back(part_idx); hword &= ~(1UL << h); pword &= ~(1UL << p); - std::cout << "hword: " << hword << std::endl; - std::cout << "pword: " << pword << std::endl; - std::cout << "nexc: " << nexc << std::endl; - std::cout << "hole_list: " << hole_idx << std::endl; - std::cout << "part_list: " << part_idx << std::endl; + // std::cout << "word: " << word << std::endl; + // std::cout << "hword: " << hword << std::endl; + // std::cout << "pword: " << pword << std::endl; + // std::cout << "h: " << h << ", hole_idx: " << hole_idx << std::endl; + // std::cout << "p: " << p << ", part_idx: " << part_idx << std::endl; ++nexc; } } - nexc_list[idet] = nexc; - - generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, wfn_.nvir_up, wfn_.nvir); + //nexc_list[idet] = nexc; + std::cout << "nexc: " << nexc << std::endl; + DetExcParamIndx exc_info; + exc_info.det.resize(nword); + std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); + // std::cout << "\nCopied det" << std::endl; + generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, nvir_up, wfn_.nvir); + std::cout << "Generated excitations" << std::endl; + std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; det_exc_param_indx[idet] = exc_info; } } From 8b5a870bd926419120e53fb71bbe0ac38eceb525 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 8 Dec 2024 21:19:24 -0500 Subject: [PATCH 124/197] Add input nbasis to generate combinations, add pairing condition in generate combinatiosn --- pyci/src/ap1rogen.cpp | 53 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 7ce9da4..ca8cc08 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -63,7 +63,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSen } template -void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result) { +void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result, long nbasis) { std::vector mask(elems.size()); std::fill(mask.end() - k, mask.end() + k, true); do { @@ -71,7 +71,13 @@ void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& for (std::size_t i = 0; i < elems.size(); ++i) { if (mask[i]) combination.push_back(elems[i]); } - result.push_back(combination); + if (k == 2) { + if (combination.size() == 2 && (combination[1] - combination[0] == static_cast (nbasis))) { + result.push_back(combination); + } + } else { + result.push_back(combination); + } } while (std::next_permutation(mask.begin(), mask.end())); } @@ -88,7 +94,36 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, const std::vector& particles, int excitation_order, std::vector& pair_inds, - std::vector& single_inds, long nocc, long nvir_up, long nvir) { + std::vector& single_inds, long nocc, long nvir_up, long nvir, long nbasis) { + std::cout << "Inside generate_excitations" << std::endl; + AlignedVector> occ_pairs, vir_pairs; + AlignedVector occs_up, occs_dn, virs_up, virs_dn, temp_occs; + for (int i : holes) { + (i < nbasis ? occs_up : occs_dn).push_back(i); + } + for (int a : particles) { + (a < nbasis ? virs_up : virs_dn).push_back(a); + } + std::cout << "up dn set created\n"; + // Create an unordered set for fast lookup of occupied down-orbitals + std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); + std::unordered_set virs_set(particles.begin(), particles.end()); + // Generate occ_pairs and vir_pairs + for (long i : occs_up) { + if (occ_dn_set.find(i + nbasis) != occ_dn_set.end()) { + occ_pairs.push_back({i, i + nbasis}); + temp_occs.push_back(i); + temp_occs.push_back(i + nbasis); + } + } + std::cout << "occ_pairs created\n"; + for (long a : particles) { + if (virs_set.find(a + nbasis) != virs_set.end()) { + vir_pairs.push_back({a, a + nbasis}); + } + } + std::cout << "vir_pairs created\n"; + std::cout << "\nInside generate_excitations" << std::endl; std::cout << "holes:" ; for (const auto& hole : holes) { @@ -100,7 +135,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector> hole_pairs, hole_singles; std::vector> part_pairs, part_singles; - generate_combinations(holes, 2, hole_pairs); - generate_combinations(holes, 1, hole_singles); - generate_combinations(particles, 2, part_pairs); - generate_combinations(particles, 1, part_singles); + generate_combinations(holes, 2, hole_pairs, nbasis); + generate_combinations(holes, 1, hole_singles, nbasis); + generate_combinations(particles, 2, part_pairs, nbasis); + generate_combinations(particles, 1, part_singles, nbasis); // std::cout << "Generated hole_pairs: " << std::endl; // for (const auto& hole_pair : hole_pairs) { @@ -273,7 +308,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) exc_info.det.resize(nword); std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); // std::cout << "\nCopied det" << std::endl; - generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, nvir_up, wfn_.nvir); + generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, nvir_up, wfn_.nvir, nbasis); std::cout << "Generated excitations" << std::endl; std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; det_exc_param_indx[idet] = exc_info; From ba37de22a1d5e44051f7ef1c41eb327afd87fd77 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 11:43:57 -0500 Subject: [PATCH 125/197] Modify the generate_excitations function to accommodate unique combinations of singles and paired excitations --- pyci/src/ap1rogen.cpp | 70 +++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index ca8cc08..86b713d 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -94,7 +94,7 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, const std::vector& particles, int excitation_order, std::vector& pair_inds, - std::vector& single_inds, long nocc, long nvir_up, long nvir, long nbasis) { + std::vector& single_inds, long nbasis, const NonSingletCI &wfn_) { std::cout << "Inside generate_excitations" << std::endl; AlignedVector> occ_pairs, vir_pairs; AlignedVector occs_up, occs_dn, virs_up, virs_dn, temp_occs; @@ -152,8 +152,8 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector> part_pairs, part_singles; generate_combinations(holes, 2, hole_pairs, nbasis); - generate_combinations(holes, 1, hole_singles, nbasis); generate_combinations(particles, 2, part_pairs, nbasis); + generate_combinations(holes, 1, hole_singles, nbasis); generate_combinations(particles, 1, part_singles, nbasis); // std::cout << "Generated hole_pairs: " << std::endl; @@ -164,29 +164,55 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector(num_pairs))); - hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); - part_pairs.resize(std::min(part_pairs.size(), static_cast(num_pairs))); - part_singles.resize(std::min(part_singles.size(), static_cast(num_singles))); - + // hole_pairs.resize(std::min(hole_pairs.size(), static_cast(num_pairs))); + // hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); + // part_pairs.resize(std::min(part_pairs.size(), static_cast(num_pairs))); + // part_singles.resize(std::min(part_singles.size(), static_cast(num_singles))); + // Match pairs and singles - for (const auto& hole_pair : hole_pairs) { - for (const auto& part_pair : part_pairs) { - std::cout << "hole_pair: " << hole_pair[0] << " " << hole_pair[1] << std::endl; - std::cout << "part_pair: " << part_pair[0] << " " << part_pair[1] << std::endl; - // Check constraints - pair_inds.push_back(nvir_up * hole_pair[0] + part_pair[0]); - //pair_inds.push_back(wfn_.nvir_up * hole_pair[1] + part_pair[1]); + // for (const auto& hole_pair : hole_pairs) { + // for (const auto& part_pair : part_pairs) { + // std::cout << "hole_pair: " << hole_pair[0] << " " << hole_pair[1] << std::endl; + // std::cout << "part_pair: " << part_pair[0] << " " << part_pair[1] << std::endl; + // // Check constraints + // pair_inds.push_back(nvir_up * hole_pair[0] + part_pair[0]); + // //pair_inds.push_back(wfn_.nvir_up * hole_pair[1] + part_pair[1]); + // } + // } + + // for (const auto& hole_single : hole_singles) { + // for (const auto& part_single : part_singles) { + // // Check constraints + // std::cout << "h: " << hole_single[0] << ", p: " << part_single[0] << std::endl; + // single_inds.push_back(nvir_up * nocc / 2 + hole_single[0] * nvir + part_single[0]); + // } + // } + + // Iterate over all unique combintaions of pairs and singles + std::vector used_holes, used_parts; + for (const auto& hpair_comb : hole_pairs) { + for (const auto& ppair_comb : part_pairs){ + if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), + [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { + long pindx = wfn_.calc_pindex(hpair_comb[0], ppair_comb[0]); + pair_inds.push_back(pindx); + used_holes.insert(used_holes.end(), hpair_comb.begin(), hpair_comb.end()); + used_parts.insert(used_parts.end(), ppair_comb.begin(), ppair_comb.end()); + } } } - for (const auto& hole_single : hole_singles) { - for (const auto& part_single : part_singles) { - // Check constraints - std::cout << "h: " << hole_single[0] << ", p: " << part_single[0] << std::endl; - single_inds.push_back(nvir_up * nocc / 2 + hole_single[0] * nvir + part_single[0]); + // Now handle single excitations + for (const auto& hsingle_comb : hole_singles) { + for (const auto& psingle_comb : part_singles) { + if (used_holes.empty() || std::none_of(hsingle_comb.begin(), hsingle_comb.end(), + [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { + long sindx = wfn_.calc_sindex(hsingle_comb[0], psingle_comb[0]); + single_inds.push_back(sindx); + used_holes.push_back(hsingle_comb[0]); + used_parts.push_back(psingle_comb[0]); + } } } @@ -202,7 +228,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) std::cout << "wfn_.nocc: " << wfn_.nocc << "wfn_.nvir" << wfn_.nvir << std::endl; long nocc_up = wfn_.nocc / 2; long nbasis = wfn_.nbasis / 2; - long nvir_up = nbasis - nocc_up; + // long nvir_up = nbasis - nocc_up; nparam = nocc_up * (nbasis - nocc_up); //paired-doubles std::cout << "nparam (doubles): " << nparam << std::endl; @@ -308,7 +334,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) exc_info.det.resize(nword); std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); // std::cout << "\nCopied det" << std::endl; - generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, wfn_.nocc, nvir_up, wfn_.nvir, nbasis); + generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); std::cout << "Generated excitations" << std::endl; std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; det_exc_param_indx[idet] = exc_info; From ca32c142d0f4de5fbc680d9fda1c7a657443aa95 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 13:06:07 -0500 Subject: [PATCH 126/197] fix function declarations --- pyci/include/pyci.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index ffc571d..d711e1b 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -935,10 +935,10 @@ class AP1roGeneralizedSenoObjective : public Objective { std::vector&, long, const NonSingletCI &); // Generate partitions - std::vector> AP1roGeneralizedSenoObjective::generate_paritions(int , int); + std::vector> generate_paritions(int , int); // Generate excitations - void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& , + void generate_excitations(const std::vector& , const std::vector& , int , std::vector& , std::vector&, std::size_t, std::size_t, std::size_t ); @@ -955,10 +955,6 @@ class AP1roGeneralizedSenoObjective : public Objective { // Helper function for d_overlap double compute_derivative(const std::vector& excitation_indices, const double*, std::size_t ); - double AP1roGeneralizedSenoObjective::compute_derivative( - const std::vector& excitation_indices, - const double*, std::size_t, std::size_t ); - // Overlap gradient function // virtual void d_overlap(const NonSingletCI &, const size_t, const double *x, double *y); virtual void d_overlap(const size_t, const double *x, double *y); From ef0e7a2e654bd74615c3023a713b3b25abb7a247 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 15:03:53 -0500 Subject: [PATCH 127/197] Update the generate combinations --- pyci/src/ap1rogen.cpp | 101 ++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 86b713d..c179b2d 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -85,8 +85,11 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti std::vector> partitions; for (int p = 0; p <= std::min(e / 2 , max_pairs); ++p) { int s = e - 2 * p; - if (s <= max_pairs) { + std::cout << "p, s: " << p << " " << s << std::endl; + if (max_pairs > 0 && s <= max_pairs) { partitions.emplace_back(p, s); + } else if (max_pairs == 0) { + partitions.emplace_back(0, s); } } return partitions; @@ -99,11 +102,14 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector> occ_pairs, vir_pairs; AlignedVector occs_up, occs_dn, virs_up, virs_dn, temp_occs; for (int i : holes) { + // std::cout << "i: " << i << ", nbasis: " << nbasis << std::endl; (i < nbasis ? occs_up : occs_dn).push_back(i); } for (int a : particles) { + // std::cout << "a: " << a << ", nbasis: " << nbasis << std::endl; (a < nbasis ? virs_up : virs_dn).push_back(a); } + std::cout << "up dn set created\n"; // Create an unordered set for fast lookup of occupied down-orbitals std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); @@ -116,13 +122,13 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector(num_pairs))); - // hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); - // part_pairs.resize(std::min(part_pairs.size(), static_cast(num_pairs))); - // part_singles.resize(std::min(part_singles.size(), static_cast(num_singles))); - - // Match pairs and singles - // for (const auto& hole_pair : hole_pairs) { - // for (const auto& part_pair : part_pairs) { - // std::cout << "hole_pair: " << hole_pair[0] << " " << hole_pair[1] << std::endl; - // std::cout << "part_pair: " << part_pair[0] << " " << part_pair[1] << std::endl; - // // Check constraints - // pair_inds.push_back(nvir_up * hole_pair[0] + part_pair[0]); - // //pair_inds.push_back(wfn_.nvir_up * hole_pair[1] + part_pair[1]); - // } - // } - - // for (const auto& hole_single : hole_singles) { - // for (const auto& part_single : part_singles) { - // // Check constraints - // std::cout << "h: " << hole_single[0] << ", p: " << part_single[0] << std::endl; - // single_inds.push_back(nvir_up * nocc / 2 + hole_single[0] * nvir + part_single[0]); - // } - // } // Iterate over all unique combintaions of pairs and singles std::vector used_holes, used_parts; @@ -196,6 +171,9 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector 0) { + for (const auto& hsingle_comb : hole_singles) { + for (const auto& psingle_comb : part_singles) { + // if (used_holes.empty() || std::none_of(hsingle_comb.begin(), hsingle_comb.end(), + // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { long sindx = wfn_.calc_sindex(hsingle_comb[0], psingle_comb[0]); single_inds.push_back(sindx); - used_holes.push_back(hsingle_comb[0]); - used_parts.push_back(psingle_comb[0]); + std::cout << "Single index: " << sindx << std::endl; + std::cout << "h: " << hsingle_comb[0] << "p: " << psingle_comb[0] << std::endl; + // used_holes.push_back(hsingle_comb[0]); + // used_parts.push_back(psingle_comb[0]); + // } } } } @@ -512,3 +494,38 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // exc_info.pair_inds.push_back(wfn_.nvir_up * pair.second + vir_pair.second); // } // } + + + + // std::cout << "Generated hole_pairs: " << std::endl; + // for (const auto& hole_pair : hole_pairs) { + // for (const auto& elem: hole_pair) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + // } + + // Limit the number of pairs and singles to the requested partition + // hole_pairs.resize(std::min(hole_pairs.size(), static_cast(num_pairs))); + // hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); + // part_pairs.resize(std::min(part_pairs.size(), static_cast(num_pairs))); + // part_singles.resize(std::min(part_singles.size(), static_cast(num_singles))); + + // Match pairs and singles + // for (const auto& hole_pair : hole_pairs) { + // for (const auto& part_pair : part_pairs) { + // std::cout << "hole_pair: " << hole_pair[0] << " " << hole_pair[1] << std::endl; + // std::cout << "part_pair: " << part_pair[0] << " " << part_pair[1] << std::endl; + // // Check constraints + // pair_inds.push_back(nvir_up * hole_pair[0] + part_pair[0]); + // //pair_inds.push_back(wfn_.nvir_up * hole_pair[1] + part_pair[1]); + // } + // } + + // for (const auto& hole_single : hole_singles) { + // for (const auto& part_single : part_singles) { + // // Check constraints + // std::cout << "h: " << hole_single[0] << ", p: " << part_single[0] << std::endl; + // single_inds.push_back(nvir_up * nocc / 2 + hole_single[0] * nvir + part_single[0]); + // } + // } From 3173a7d8e1d32e259bb5888c800876ec84512d3e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 17:28:13 -0500 Subject: [PATCH 128/197] add bool for vir_pairs in generate_partitions --- pyci/include/pyci.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index d711e1b..b2b7d21 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -927,21 +927,13 @@ class AP1roGeneralizedSenoObjective : public Objective { void generate_combinations(const std::vector&, int , std::vector>&, long ); // Generate partitions - std::vector> generate_partitions(int , int); + std::vector> generate_partitions(int , int, bool); // Generate excitations void generate_excitations(const std::vector& , const std::vector& , int , std::vector& , std::vector&, long, const NonSingletCI &); - // Generate partitions - std::vector> generate_paritions(int , int); - - // Generate excitations - void generate_excitations(const std::vector& , - const std::vector& , int , std::vector& , - std::vector&, std::size_t, std::size_t, std::size_t ); - // Initializer for {d_,}overlap variables void init_overlap(const NonSingletCI &); From 42458d5a1d979b4f4d0c26b349f1138dcce20926 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 17:29:30 -0500 Subject: [PATCH 129/197] Update generate_exciations to consider appropriate pairs and singles --- pyci/src/ap1rogen.cpp | 62 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index c179b2d..818de45 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -81,15 +81,23 @@ void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& } while (std::next_permutation(mask.begin(), mask.end())); } -std::vector> AP1roGeneralizedSenoObjective::generate_partitions(int e, int max_pairs) { +std::vector> AP1roGeneralizedSenoObjective::generate_partitions(int e, int max_opairs, bool nvir_pairs) { std::vector> partitions; - for (int p = 0; p <= std::min(e / 2 , max_pairs); ++p) { + for (int p = 0; p <= std::min(e / 2 , max_opairs); ++p) { int s = e - 2 * p; - std::cout << "p, s: " << p << " " << s << std::endl; - if (max_pairs > 0 && s <= max_pairs) { - partitions.emplace_back(p, s); - } else if (max_pairs == 0) { + // std::cout << "p, s: " << p << " " << s << std::endl; + if (max_opairs > 0 && nvir_pairs && p) { + if (e % 2 !=0) { // if e is odd + partitions.emplace_back(p, s); + } + else if (e %2 == 0 && s <= (max_opairs - p)) { + partitions.emplace_back(p, s); + } + } else if (max_opairs == 0) { + // if (e % 2 ==0 && s <= max_opairs) { partitions.emplace_back(0, s); + // } else if + } } return partitions; @@ -142,8 +150,14 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector used_holes, used_parts; for (const auto& hpair_comb : hole_pairs) { for (const auto& ppair_comb : part_pairs){ - if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), - [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { + // if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), + // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { + if (!hpair_comb.empty() || !ppair_comb.empty()) { long pindx = wfn_.calc_pindex(hpair_comb[0], ppair_comb[0]); std::cout << "Pair index: " << pindx << std::endl; std::cout << "hpair_comb: " << hpair_comb[0] << " " << hpair_comb[1] << std::endl; @@ -177,26 +191,48 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector 0) { + if (num_singles > 0) { + // Filter holes and particles to exclude used ones + std::vector remaining_holes, remaining_particles; + + // Exclude used holes + std::copy_if(holes.begin(), holes.end(), std::back_inserter(remaining_holes), + [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) == used_holes.end(); }); + + // Exclude used particles + std::copy_if(particles.begin(), particles.end(), std::back_inserter(remaining_particles), + [&](std::size_t p) { return std::find(used_parts.begin(), used_parts.end(), p) == used_parts.end(); }); + + generate_combinations(remaining_holes, 1, hole_singles, nbasis); + generate_combinations(remaining_particles, 1, part_singles, nbasis); + for (const auto& hsingle_comb : hole_singles) { for (const auto& psingle_comb : part_singles) { // if (used_holes.empty() || std::none_of(hsingle_comb.begin(), hsingle_comb.end(), // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { + // Ensure the selected single excitations do not reuse already used indices + if (std::find(used_holes.begin(), used_holes.end(), hsingle_comb[0]) == used_holes.end() && + std::find(used_parts.begin(), used_parts.end(), psingle_comb[0]) == used_parts.end()) { long sindx = wfn_.calc_sindex(hsingle_comb[0], psingle_comb[0]); single_inds.push_back(sindx); std::cout << "Single index: " << sindx << std::endl; std::cout << "h: " << hsingle_comb[0] << "p: " << psingle_comb[0] << std::endl; // used_holes.push_back(hsingle_comb[0]); // used_parts.push_back(psingle_comb[0]); - // } + } } } } + else { + single_inds.clear(); + } } } From 3b665501637bbd802a3059c0c4f16927a688b44a Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 18:04:40 -0500 Subject: [PATCH 130/197] Update sparse_op call for ci_op considering extra keyword for nonsingletci_wfn to invoke the appropriate constructor --- pyci/fanci/fanci.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index 5227963..e4577f3 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -199,8 +199,12 @@ def __init__( # Generate determinant spaces wfn = fill_wavefunction(wfn, nproj, fill) + print("type", type(wfn)) # Compute CI matrix operator with nproj rows and len(wfn) columns - ci_op = pyci.sparse_op(ham, wfn, nrow=nproj, ncol=len(wfn), symmetric=False, wfntype="nonsingletci") + if type(wfn).__name__ == "nonsingletci_wfn": + ci_op = pyci.sparse_op(ham, wfn, nrow=nproj, ncol=len(wfn), symmetric=False, wfntype="nonsingletci") + else: + ci_op = pyci.sparse_op(ham, wfn, nrow=nproj, ncol=len(wfn), symmetric=False) # Compute arrays of occupations sspace = wfn.to_occ_array() From 5fadc97e1d3597cb60e24293df7ea98e7a02b079 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 18:05:06 -0500 Subject: [PATCH 131/197] Add print statments in overlap --- pyci/src/ap1rogen.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 818de45..f43f4aa 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -388,7 +388,7 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector Date: Mon, 9 Dec 2024 20:48:39 -0500 Subject: [PATCH 132/197] Sort final indices of params before storing the data --- pyci/src/ap1rogen.cpp | 110 +++++++++++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 33 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index f43f4aa..bb23328 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,8 +14,9 @@ * along with PyCI. If not, see . */ #include -#include +#include #include + namespace pyci { // See apig.cpp for reference @@ -66,6 +67,7 @@ template void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result, long nbasis) { std::vector mask(elems.size()); std::fill(mask.end() - k, mask.end() + k, true); + // std::fill(mask.begin(), mask.begin() + k, true); do { std::vector combination; for (std::size_t i = 0; i < elems.size(); ++i) { @@ -210,6 +212,8 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& excitation_inds, const double* x) { std::size_t num_excitations = excitation_inds.size(); - if (num_excitations == 0) return 1.0; + if (num_excitations == 0) { + return 1.0; + } else if (num_excitations == 1) { + return x[excitation_inds[0]]; + } double permanent = 0.0; std::size_t subset_count = 1UL << num_excitations; @@ -378,11 +405,23 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector::quiet_NaN(); + } rowsumprod *= rowsum; } + if (std::isnan(rowsumprod) || std::isinf(rowsumprod)) { + std::cerr << "Error: rowsumprod is NaN or inf at subset " << subset << std::endl; + return std::numeric_limits::quiet_NaN(); + } permanent += rowsumprod * (1 - ((__builtin_popcount(subset) & 1) << 1)); } permanent *= ((num_excitations % 2 == 1) ? -1 : 1); + if (std::isnan(permanent) || std::isinf(permanent)) { + std::cerr << "Error: permanent is NaN or inf" << std::endl; + return std::numeric_limits::quiet_NaN(); + } return permanent; } @@ -391,27 +430,15 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d std::cout << "\nInside overlap" << std::endl; for (std::size_t idet = 0; idet != ndet; ++idet) { - //Retrieve the DetExcParamIndx object from the hash map - // const ulong* det = det_ptr(idet); - - // // std::vector det_vector(det, det + wfn_.nword); - // // Find corresponding DetExcParamIndx for the current determinant - // std::unordered_map, DetExcParamIndx> det_map; - // // Populate the hash map (assume det_exc_param_indx is iterable) - // for (const auto& exc_info : det_exc_param_indx) { - // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - // } - - // auto it = det_map.find(det_vector); std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; if (idet < det_exc_param_indx.size()) { - std::cout << "idet" << idet << " found in storage" << std::endl; + std::cout << "idet: " << idet << " found in storage" << std::endl; // Access the excitation parameter indices const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; - double pair_permanent = permanent_calculation(exc_info.pair_inds, x); double single_permanent = permanent_calculation(exc_info.single_inds, x); + std::cout << "exc_info.pair_inds: "; for (const auto& pid : exc_info.pair_inds) { std::cout << pid << " " << x[pid] << " "; @@ -454,24 +481,11 @@ double AP1roGeneralizedSenoObjective::compute_derivative( // void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - + std::cout << "Computing d_overlap" << std::endl; // Loop over each determinant for (std::size_t idet = 0; idet != ndet; ++idet) { - // Retrieve the corresponding determinant - // const ulong* det = det_ptr(idet); - // std::vector det_vector(det, det + wfn_.nword); - // Find corresponding DetExcParamIndx for the current determinant - // std::unordered_map, DetExcParamIndx> det_map; - // // Populate the hash map (assume det_exc_param_indx is iterable) - // for (const auto& exc_info : det_exc_param_indx) { - // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - // } - - // Find corresponding DetExcParamIndx for the current determinant - // auto it = det_map.find(det_vector); - // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; @@ -581,3 +595,33 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // single_inds.push_back(nvir_up * nocc / 2 + hole_single[0] * nvir + part_single[0]); // } // } + + + //Retrieve the DetExcParamIndx object from the hash map + // const ulong* det = det_ptr(idet); + + // // std::vector det_vector(det, det + wfn_.nword); + // // Find corresponding DetExcParamIndx for the current determinant + // std::unordered_map, DetExcParamIndx> det_map; + // // Populate the hash map (assume det_exc_param_indx is iterable) + // for (const auto& exc_info : det_exc_param_indx) { + // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + // } + + // auto it = det_map.find(det_vector); + + + // Retrieve the corresponding determinant + // const ulong* det = det_ptr(idet); + + // std::vector det_vector(det, det + wfn_.nword); + // Find corresponding DetExcParamIndx for the current determinant + // std::unordered_map, DetExcParamIndx> det_map; + // // Populate the hash map (assume det_exc_param_indx is iterable) + // for (const auto& exc_info : det_exc_param_indx) { + // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key + // } + + // Find corresponding DetExcParamIndx for the current determinant + // auto it = det_map.find(det_vector); + From 6bd95010d2c98372c821e9aa018a2ed6402d3a25 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 21:10:54 -0500 Subject: [PATCH 133/197] Correct the pindex --- pyci/src/nonsingletci.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 2943f09..a5cdbdf 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -164,15 +164,17 @@ long NonSingletCI::calc_sindex(const long occ, const long vir) const { } long NonSingletCI::calc_pindex(const long occ, const long vir) const { - long o = 0; - long v = 0; + long o, v; + // Assuming that only alpha orbitals are provided in the input if (vir < nbasis / 2) { v = vir - nocc / 2; } else { v = vir - nocc; } if (occ >= nbasis / 2) { - o = occ - nbasis / 2; + o = occ - (nbasis / 2 - nocc / 2); + } else { + o = occ; } long idx = (nbasis / 2 - nocc / 2) * o + v; return idx; From a6f627a68a7f0f1b321d72edc7e57a1b769a7118 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 9 Dec 2024 22:04:16 -0500 Subject: [PATCH 134/197] Correct the overlap function and declare two vectors to store the permanents for singles and doubles --- pyci/include/pyci.h | 2 + pyci/src/ap1rogen.cpp | 92 ++++++++++++++++++++++++++++++------------- 2 files changed, 66 insertions(+), 28 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index b2b7d21..2c74acc 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -901,6 +901,8 @@ class AP1roGeneralizedSenoObjective : public Objective { // of {d_,}overlap here: std::vector nexc_list; std::vector det_exc_param_indx; // Det and excitation details + std::vector s_permanent; + std::vector p_permanent; public: // Keep in mind the {DOCI,FullCI,GenCI}Wfn class names in diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index bb23328..fde67bd 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -428,6 +428,8 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, const double* x, - std::size_t excitation_idx) { + std::size_t iparam) { + + // double derivative = 0.0; + + // std::vector modified_x(x, x + nparam); + // modified_x[excitation_inds[excitation_idx]] = 1.0; + // derivative = permanent_calculation(excitation_inds, modified_x.data()); - double derivative = 0.0; + // return derivative; + + // check if iparam is within excitation_inds + auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); + if (it == excitation_inds.end()) { + return 0.0; + } - std::vector modified_x(x, x + nparam); - modified_x[excitation_inds[excitation_idx]] = 1.0; - derivative = permanent_calculation(excitation_inds, modified_x.data()); + // Create a reduced excitation_inds excluding iparam + std::vector reduced_inds = excitation_inds; + reduced_inds.erase(it); - return derivative; + double reduced_permanent = permanent_calculation(reduced_inds, x); + + return reduced_permanent; } + + + // void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ std::cout << "Computing d_overlap" << std::endl; @@ -489,37 +513,49 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; - + double pair_permanent = p_permanent[idet]; + double single_permanent = s_permanent[idet]; + std::cout << "pair_permanent: " << pair_permanent << std::endl; + std::cout << "single_permanent: " << single_permanent << std::endl; + + for (std::size_t i = 0; i < nparam; ++i) { + std::cout << "computing deriv for i: " << i << std::endl; + double d_pair = compute_derivative(exc_info.pair_inds, x, i); + double d_single = compute_derivative(exc_info.single_inds, x, i); + std::cout << "d index:" << idet * nparam + i << std::endl; + y[idet * nparam + i] = d_pair * single_permanent + pair_permanent * d_single; + } + // Loop over each parameter (paired and single excitations) - std::size_t param_index = 0; + // std::size_t param_index = 0; // Derivative for paired excitations - for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { - // Get the excitation index for the pair - const std::size_t excitation_idx = exc_info.pair_inds[i]; + // for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { + // // Get the excitation index for the pair + // const std::size_t excitation_idx = exc_info.pair_inds[i]; - // Compute the derivative of the permanent with respect to this excitation - double derivative = compute_derivative(exc_info.pair_inds, x, excitation_idx); + // // Compute the derivative of the permanent with respect to this excitation + // double derivative = compute_derivative(exc_info.pair_inds, x, excitation_idx); - // Store the result in the output vector d_ovlp (size ndet * nparam) - y[idet * nparam + param_index] = derivative; + // // Store the result in the output vector d_ovlp (size ndet * nparam) + // y[idet * nparam + param_index] = derivative; - ++param_index; - } + // ++param_index; + // } // Derivative for single excitations - for (std::size_t i = 0; i < exc_info.single_inds.size(); ++i) { - // Get the excitation index for the single - const std::size_t excitation_idx = exc_info.single_inds[i]; + // for (std::size_t i = 0; i < exc_info.single_inds.size(); ++i) { + // // Get the excitation index for the single + // const std::size_t excitation_idx = exc_info.single_inds[i]; - // Compute the derivative of the permanent with respect to this excitation - double derivative = compute_derivative(exc_info.single_inds, x, excitation_idx); + // // Compute the derivative of the permanent with respect to this excitation + // double derivative = compute_derivative(exc_info.single_inds, x, excitation_idx); - // Store the result in the output vector d_ovlp (size ndet * nparam) - y[idet * nparam + param_index] = derivative; + // // Store the result in the output vector d_ovlp (size ndet * nparam) + // y[idet * nparam + param_index] *= derivative; - ++param_index; - } + // ++param_index; + // } } else { std::cout << "Determinant " << idet << " not found in det_map" << std::endl; From 09dede223a183f21bc50fb9b731225e6aee82f2d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 10 Dec 2024 16:48:36 -0500 Subject: [PATCH 135/197] Update checks for single_inds and pair_inds structure elements --- pyci/src/ap1rogen.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index fde67bd..0d1ca8f 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -235,7 +235,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector Date: Tue, 10 Dec 2024 17:03:07 -0500 Subject: [PATCH 136/197] Initialize det_exc_param_indx in init_overlap to store data for all dets, remove dependency on the the previous storage from nonsingletci --- pyci/src/ap1rogen.cpp | 180 +++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 109 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 0d1ca8f..26f8865 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -190,11 +190,10 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector, DetExcParamIndx> det_map; - - // Populate the hash map (assume det_exc_param_indx is iterable) - // for (const auto& exc_info : det_exc_param_indx) { - // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - // } for (std::size_t idet = 0; idet != nconn; ++idet) { AlignedVector rdet(nword); wfn_.fill_hartreefock_det(nb, nocc, &rdet[0]); - - // std::cout << "After fill_hartreefock_det rdet:" ; - // for (std::size_t k = 0; k < nword; ++k) { - // std::cout << rdet[k] << " "; - // } - // std::cout << std::endl; - //wfn_.print_vector("rdet", rdet); - const ulong *det = wfn_.det_ptr(idet); - - // std::vector det_vector(det, det + nword); - // auto it = det_map.find(det_vector); - // if (it != det_map.end()) { - // std::cout << "Found det in det_map" << std::endl; - // // std::cout << "Det: " << det_vector << std::endl; - // // std::cout << "DetExcParamIndx: " << it->second << std::endl; - // std::cout << "from storage: " << det_exc_param_indx[idet].det << std::endl; ensure_struct_size(det_exc_param_indx, idet+1); - if (!det_exc_param_indx[idet].det.empty()) { - std::cout << "\nidet: " << idet << " found in det_map" << std::endl; - std::cout << "Det from wfn: "; + std::cout << "\nDet: " ; + for (std::size_t k = 0; k < nword; ++k) { + std::cout << det[k] << " "; + } + std::cout << ", at iDet: " << idet << ", not found in det_exc_param_indx" << std::endl; + + ulong word, hword, pword; + std::size_t h, p, nexc = 0; + + std::vector holes; + std::vector particles; + + // Collect holes and particles + for (std::size_t iword = 0; iword != nword; ++iword) + { + word = rdet[iword] ^ det[iword]; //str for excitation + hword = word & rdet[iword]; //str for hole + pword = word & det[iword]; //str for particle + std::cout << "word: " << word << std::endl; + std::cout << "hword: " << hword << std::endl; + std::cout << "pword: " << pword << std::endl; + while(hword){ + h = Ctz(hword); + p = Ctz(pword); + + std::size_t hole_idx = h + iword * Size(); + std::size_t part_idx = p + iword * Size(); // - nocc_up; + + holes.push_back(hole_idx); + particles.push_back(part_idx); + + hword &= ~(1UL << h); + pword &= ~(1UL << p); + // std::cout << "word: " << word << std::endl; + // std::cout << "hword: " << hword << std::endl; + // std::cout << "pword: " << pword << std::endl; + // std::cout << "h: " << h << ", hole_idx: " << hole_idx << std::endl; + // std::cout << "p: " << p << ", part_idx: " << part_idx << std::endl; + ++nexc; + } + } + //nexc_list[idet] = nexc; + std::cout << "nexc: " << nexc << std::endl; + DetExcParamIndx exc_info; + exc_info.det.resize(nword); + exc_info.pair_inds[0] = -1; + exc_info.single_inds[0] = -1; + std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); + // std::cout << "\nCopied det" << std::endl; + generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); + std::cout << "Generated excitations" << std::endl; + std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + std::sort(exc_info.pair_inds.begin(), exc_info.pair_inds.end()); + std::sort(exc_info.single_inds.begin(), exc_info.single_inds.end()); + if (idet == 41) { + std::cout << "Det: "; for (std::size_t k = 0; k < nword; ++k) { std::cout << det[k] << " "; } std::cout << std::endl; - std::cout << "det_exc_param_indx[idet].det: "; - for (std::size_t k = 0; k < nword; ++k) { - std::cout << det_exc_param_indx[idet].det[k] << " "; + std::cout << "exc_info.pair_inds: "; + for (const auto& pid : exc_info.pair_inds) { + std::cout << pid << " "; } std::cout << std::endl; - - } else { - std::cout << "\nDet: " ; - for (std::size_t k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << ", at iDet: " << idet << ", not found in det_exc_param_indx" << std::endl; - - ulong word, hword, pword; - std::size_t h, p, nexc = 0; - - std::vector holes; - std::vector particles; - - // Collect holes and particles - for (std::size_t iword = 0; iword != nword; ++iword) - { - word = rdet[iword] ^ det[iword]; //str for excitation - hword = word & rdet[iword]; //str for hole - pword = word & det[iword]; //str for particle - std::cout << "word: " << word << std::endl; - std::cout << "hword: " << hword << std::endl; - std::cout << "pword: " << pword << std::endl; - while(hword){ - h = Ctz(hword); - p = Ctz(pword); - - std::size_t hole_idx = h + iword * Size(); - std::size_t part_idx = p + iword * Size(); // - nocc_up; - - holes.push_back(hole_idx); - particles.push_back(part_idx); - - hword &= ~(1UL << h); - pword &= ~(1UL << p); - // std::cout << "word: " << word << std::endl; - // std::cout << "hword: " << hword << std::endl; - // std::cout << "pword: " << pword << std::endl; - // std::cout << "h: " << h << ", hole_idx: " << hole_idx << std::endl; - // std::cout << "p: " << p << ", part_idx: " << part_idx << std::endl; - ++nexc; - } - } - //nexc_list[idet] = nexc; - std::cout << "nexc: " << nexc << std::endl; - DetExcParamIndx exc_info; - exc_info.det.resize(nword); - std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); - // std::cout << "\nCopied det" << std::endl; - generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); - std::cout << "Generated excitations" << std::endl; - std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - std::sort(exc_info.pair_inds.begin(), exc_info.pair_inds.end()); - std::sort(exc_info.single_inds.begin(), exc_info.single_inds.end()); - if (idet == 41) { - std::cout << "Det: "; - for (std::size_t k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - std::cout << "exc_info.pair_inds: "; - for (const auto& pid : exc_info.pair_inds) { - std::cout << pid << " "; - } - std::cout << std::endl; - std::cout << "exc_info.single_inds: "; - for (const auto& sid : exc_info.single_inds) { - std::cout << sid << " "; - } - std::cout << std::endl; + std::cout << "exc_info.single_inds: "; + for (const auto& sid : exc_info.single_inds) { + std::cout << sid << " "; } - det_exc_param_indx[idet] = exc_info; + std::cout << std::endl; } + det_exc_param_indx[idet] = exc_info; } } From cc0cb8fa0886982a4e779116b868d404dd3e0bd6 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 10 Dec 2024 20:19:09 -0500 Subject: [PATCH 137/197] Add default value for stored param indices --- pyci/include/pyci.h | 1 + pyci/src/ap1rogen.cpp | 150 ++++++++++++++++++++++++++---------------- 2 files changed, 94 insertions(+), 57 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 2c74acc..3bc78f8 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -903,6 +903,7 @@ class AP1roGeneralizedSenoObjective : public Objective { std::vector det_exc_param_indx; // Det and excitation details std::vector s_permanent; std::vector p_permanent; + double default_value; public: // Keep in mind the {DOCI,FullCI,GenCI}Wfn class names in diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 26f8865..b95cf7b 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,7 +14,7 @@ * along with PyCI. If not, see . */ #include -#include +#include #include namespace pyci { @@ -58,7 +58,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGenerali // Move constructor // obj is the rvalue reference to another object to be moved AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&obj) noexcept -: Objective::Objective(obj), nexc_list(std::move(obj.nexc_list)), det_exc_param_indx(std::move(obj.det_exc_param_indx)) +: Objective::Objective(obj), nexc_list(std::move(obj.nexc_list)) { return; } @@ -174,32 +174,38 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector> hole_pairs, hole_singles; std::vector> part_pairs, part_singles; - generate_combinations(holes, 2, hole_pairs, nbasis); - generate_combinations(particles, 2, part_pairs, nbasis); + // Iterate over all unique combintaions of pairs and singles + std::vector used_holes, used_parts; + if (num_pairs > 0) { + generate_combinations(holes, 2, hole_pairs, nbasis); + generate_combinations(particles, 2, part_pairs, nbasis); + std::cout << "Generated hole_pairs" << std::endl; - // Iterate over all unique combintaions of pairs and singles - std::vector used_holes, used_parts; - for (const auto& hpair_comb : hole_pairs) { - for (const auto& ppair_comb : part_pairs){ - // if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), - // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { - if (!hpair_comb.empty() || !ppair_comb.empty()) { - long pindx = wfn_.calc_pindex(hpair_comb[0], ppair_comb[0]); - std::cout << "Pair index: " << pindx << std::endl; - std::cout << "hpair_comb: " << hpair_comb[0] << " " << hpair_comb[1] << std::endl; - std::cout << "ppair_comb: " << ppair_comb[0] << " " << ppair_comb[1] << std::endl; - pair_inds.clear(); - pair_inds.push_back(pindx); - used_holes.insert(used_holes.end(), hpair_comb.begin(), hpair_comb.end()); - used_parts.insert(used_parts.end(), ppair_comb.begin(), ppair_comb.end()); + + for (const auto& hpair_comb : hole_pairs) { + for (const auto& ppair_comb : part_pairs){ + std::cout << "Handling pair excitations" << std::endl; + // if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), + // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { + if (!hpair_comb.empty() || !ppair_comb.empty()) { + long pindx = wfn_.calc_pindex(hpair_comb[0], ppair_comb[0]); + std::cout << "Pair index: " << pindx << std::endl; + std::cout << "hpair_comb: " << hpair_comb[0] << " " << hpair_comb[1] << std::endl; + std::cout << "ppair_comb: " << ppair_comb[0] << " " << ppair_comb[1] << std::endl; + pair_inds.clear(); + pair_inds.push_back(pindx); + used_holes.insert(used_holes.end(), hpair_comb.begin(), hpair_comb.end()); + used_parts.insert(used_parts.end(), ppair_comb.begin(), ppair_comb.end()); + } } } } // Now handle single excitations if (num_singles > 0) { + std::cout << "Handling single excitations" << std::endl; // Filter holes and particles to exclude used ones std::vector remaining_holes, remaining_particles; @@ -234,12 +240,22 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector::quiet_NaN(); std::cout << "Inside init_overlap" << std::endl; // Initialize your class-specific variables here // init_Overlap objective for the AP1roGSDspin_sen-o @@ -253,8 +269,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) std::cout << "nparam (doubles): " << nparam << std::endl; nparam += wfn_.nocc * (2* nbasis - wfn_.nocc); // beta singles std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; - // det_exc_param_indx = wfn_.det_exc_param_indx; - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + + ovlp.resize(wfn_.ndet); d_ovlp.resize(wfn_.ndet * nparam); @@ -270,12 +286,16 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) wfn_.fill_hartreefock_det(nb, nocc, &rdet[0]); const ulong *det = wfn_.det_ptr(idet); ensure_struct_size(det_exc_param_indx, idet+1); - - std::cout << "\nDet: " ; + std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + std::cout << "\n---------> Det: " ; + bool are_same = true; for (std::size_t k = 0; k < nword; ++k) { std::cout << det[k] << " "; + if (rdet[k] != det[k]) { + are_same = false; + break; + } } - std::cout << ", at iDet: " << idet << ", not found in det_exc_param_indx" << std::endl; ulong word, hword, pword; std::size_t h, p, nexc = 0; @@ -289,7 +309,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) word = rdet[iword] ^ det[iword]; //str for excitation hword = word & rdet[iword]; //str for hole pword = word & det[iword]; //str for particle - std::cout << "word: " << word << std::endl; + std::cout << "\nword: " << word << std::endl; std::cout << "hword: " << hword << std::endl; std::cout << "pword: " << pword << std::endl; while(hword){ @@ -314,13 +334,17 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } //nexc_list[idet] = nexc; std::cout << "nexc: " << nexc << std::endl; + std::cout << "Ensured struct size" << std::endl; DetExcParamIndx exc_info; exc_info.det.resize(nword); - exc_info.pair_inds[0] = -1; - exc_info.single_inds[0] = -1; + exc_info.pair_inds.resize(1); + exc_info.single_inds.resize(1); + exc_info.pair_inds[0] = default_value; + exc_info.single_inds[0] = default_value; + std::cout << "Assigned first elem as -1 to both pair_inds and single_inds" << std::endl; std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); // std::cout << "\nCopied det" << std::endl; - generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); + if (!are_same) generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); std::cout << "Generated excitations" << std::endl; std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; std::sort(exc_info.pair_inds.begin(), exc_info.pair_inds.end()); @@ -401,9 +425,17 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d // Access the excitation parameter indices const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; - double pair_permanent = permanent_calculation(exc_info.pair_inds, x); - double single_permanent = permanent_calculation(exc_info.single_inds, x); - + double pair_permanent, single_permanent; + if (exc_info.pair_inds[0] == default_value) { + pair_permanent = 0.0; + } else { + pair_permanent = permanent_calculation(exc_info.pair_inds, x); + } + if (exc_info.single_inds[0] == default_value) { + single_permanent = 0.0; + } else { + single_permanent = permanent_calculation(exc_info.single_inds, x); + } p_permanent[idet] = pair_permanent; s_permanent[idet] = single_permanent; @@ -415,7 +447,7 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d for (const auto& sid : exc_info.single_inds) { std::cout << sid << " "; } - std::cout << "pair_permanent: " << pair_permanent << std::endl; + std::cout << "\npair_permanent: " << pair_permanent << std::endl; std::cout << "single_permanent: " << single_permanent << std::endl; if (y != nullptr && idet < ndet) { y[idet] = pair_permanent * single_permanent; @@ -468,7 +500,7 @@ double AP1roGeneralizedSenoObjective::compute_derivative( // void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - std::cout << "Computing d_overlap" << std::endl; + std::cout << "\nComputing d_overlap" << std::endl; // std::cout << "Size of d_ovlp: " << y.size() << std::endl; // Loop over each determinant for (std::size_t idet = 0; idet != ndet; ++idet) @@ -476,41 +508,45 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { - const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; + std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + + DetExcParamIndx& exc_info = det_exc_param_indx[idet]; double pair_permanent = p_permanent[idet]; double single_permanent = s_permanent[idet]; std::cout << "pair_permanent: " << pair_permanent << std::endl; std::cout << "single_permanent: " << single_permanent << std::endl; - for (std::size_t i = 0; i < nparam; ++i) { - std::cout << "computing deriv for i: " << i << std::endl; + for (std::size_t iparam = 0; iparam < nparam; ++iparam) { + std::cout << "computing deriv for i: " << iparam << std::endl; double d_pair = 0.0; double d_single = 0.0; - - if (exc_info.pair_inds.empty()) { - std::cerr << "Error: pair_inds() returned a null pointer." << std::endl; - } else if (exc_info.pair_inds[0] == -1) { - d_pair = 0.0; - } else { - std::cout << "exc_info.pair_inds: "; - for (const auto& sid : exc_info.pair_inds) { + std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; + std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; + for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { + std::cout << exc_info.pair_inds[i] << " "; + std::cout << exc_info.single_inds[i] << " "; + } + std::cout << "\n"; + if (exc_info.single_inds[0] != default_value) { + std::cout << "exc_info.single_inds: "; + for (const auto sid : exc_info.single_inds) { std::cout << sid << " "; } - d_pair = compute_derivative(exc_info.pair_inds, x, i); + std::cout << "\nCalling compute deriv for single_inds\n"; + d_single = compute_derivative(exc_info.single_inds, x, iparam); + std::cout << "calling done\n"; } - if (exc_info.single_inds.empty()) { - std::cerr << "Error: single_inds() returned a null pointer." << std::endl; - } else if (exc_info.single_inds[0] == -1) { - d_single = 0.0; - } else { - std::cout << "exc_info.single_inds: "; - for (const auto& sid : exc_info.single_inds) { + std::cout << "\nd_single: " << d_single << "\n" ; + if (exc_info.pair_inds[0] != default_value) { + std::cout << "exc_info.pair_inds: "; + for (const auto sid : exc_info.pair_inds) { std::cout << sid << " "; } - d_single = compute_derivative(exc_info.single_inds, x, i); + d_pair = compute_derivative(exc_info.pair_inds, x, iparam); } - std::cout << "d index:" << idet * nparam + i << std::endl; - y[idet * nparam + i] = d_pair * single_permanent + pair_permanent * d_single; + + std::cout << "\nderiv index:" << idet * nparam + iparam << std::endl; + y[idet * nparam + iparam] = d_pair * single_permanent + pair_permanent * d_single; } // Loop over each parameter (paired and single excitations) @@ -547,8 +583,8 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x else { std::cout << "Determinant " << idet << " not found in det_map" << std::endl; // Set all derivatives to zero if determinant is not found - for (std::size_t i = 0; i < nparam; ++i) { - y[idet * nparam + i] = 0.0; + for (std::size_t iparam = 0; iparam < nparam; ++iparam) { + y[idet * nparam + iparam] = 0.0; } } } From 6ae9477076062b526067880ce247026a032d689d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 14:44:12 -0500 Subject: [PATCH 138/197] Changing the default indices for params from default_value to -1.0 --- pyci/src/ap1rogen.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index b95cf7b..4573c94 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -339,8 +339,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) exc_info.det.resize(nword); exc_info.pair_inds.resize(1); exc_info.single_inds.resize(1); - exc_info.pair_inds[0] = default_value; - exc_info.single_inds[0] = default_value; + exc_info.pair_inds[0] = -1.0; + exc_info.single_inds[0] = -1.0; std::cout << "Assigned first elem as -1 to both pair_inds and single_inds" << std::endl; std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); // std::cout << "\nCopied det" << std::endl; @@ -426,12 +426,12 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d // Access the excitation parameter indices const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; double pair_permanent, single_permanent; - if (exc_info.pair_inds[0] == default_value) { + if (exc_info.pair_inds[0] == -1.0) { pair_permanent = 0.0; } else { pair_permanent = permanent_calculation(exc_info.pair_inds, x); } - if (exc_info.single_inds[0] == default_value) { + if (exc_info.single_inds[0] == -1.0) { single_permanent = 0.0; } else { single_permanent = permanent_calculation(exc_info.single_inds, x); @@ -508,6 +508,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { + std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; DetExcParamIndx& exc_info = det_exc_param_indx[idet]; @@ -527,7 +528,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x std::cout << exc_info.single_inds[i] << " "; } std::cout << "\n"; - if (exc_info.single_inds[0] != default_value) { + if (exc_info.single_inds[0] != -1.0) { std::cout << "exc_info.single_inds: "; for (const auto sid : exc_info.single_inds) { std::cout << sid << " "; @@ -537,7 +538,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x std::cout << "calling done\n"; } std::cout << "\nd_single: " << d_single << "\n" ; - if (exc_info.pair_inds[0] != default_value) { + if (exc_info.pair_inds[0] != -1.0) { std::cout << "exc_info.pair_inds: "; for (const auto sid : exc_info.pair_inds) { std::cout << sid << " "; From bef28f4b8fdeed6e47474c23fd1855a044f55be4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 14:45:23 -0500 Subject: [PATCH 139/197] Fix input for fill_virs in add_row --- pyci/src/sparseop.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 6893499..f426a37 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -565,9 +565,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); // !Check nword or nword2 fill_occs(wfn.nword, rdet_up, occs); - fill_virs(wfn.nword, nbasis, rdet_up, virs); + fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); - long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis / 2) - 1)); + long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis) - 1)); long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; From 8400b8ea48a5a1ca3c8b52b0183f517a1eef7277 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 18:10:31 -0500 Subject: [PATCH 140/197] Updated matrix elements terms in add_row --- pyci/src/sparseop.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index f426a37..6fc5a36 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -711,8 +711,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { // add 2-0 matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + ham.two_mo[koffset + n1 * jj + ll]); append(indices, jdet); } excite_det(ll, kk, det_dn); @@ -735,11 +734,12 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + val1 += ham.two_mo[koffset + n1 * jj + kk]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } // add the matrix element append(data, sign_up * val1); @@ -845,12 +845,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + koffset = ioffset + n2 * kk + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + val1 += ham.two_mo[koffset + n1 * jj + kk]; } // add the matrix element append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); @@ -886,8 +887,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { // add 0-2 matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + ham.two_mo[koffset + n1 * jj + ll] ); append(indices, jdet); } excite_det(ll, kk, det_up); From 1261f7d752356b4416e615716565645b38bb6b96 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 20:56:26 -0500 Subject: [PATCH 141/197] Update the matrix elements calculations and clean up the add_row function --- pyci/src/sparseop.cpp | 74 +++++++++++-------------------------------- 1 file changed, 18 insertions(+), 56 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 6fc5a36..3a4c586 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -618,7 +618,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; val2 += ham.two_mo[ioffset + n2 * kk + n1 * ii + kk]; } - // loop over spin-up virtual indices + // first excitation: alpha -> alpha for (j = 0; j < nvir_up; ++j) { jj = virs_up[j]; // alpha -> alpha excitation elements @@ -648,7 +648,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitation: beta -> alpha for (l = 0; l < nvir_up; ++l) { ll = virs_up[l]; // beta -> alpha excitation elements @@ -664,7 +664,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-down virtual indices + // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; // 1-1 excitation elements @@ -685,7 +685,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // // second excitation: alpha -> alpha for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; // alpha -> alpha excitation elements @@ -701,7 +701,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-dn virtual indices + // second excitation: alpha -> beta for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // alpha -> beta excitation elements @@ -720,10 +720,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(jj, ii, det_up); } - // loop over spin-dn virtual indices + // first excitation: alpha -> beta for (j = 0; j < nvir_dn; ++j) { jj = virs_dn[j]; - // alpha -> beta excitation elements excite_det(ii, jj, det_up); sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); jdet = wfn.index_det(det_up); @@ -749,7 +748,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitaiton: beta -> alpha for (l = 0; l < nvir_up; ++l) { ll = virs_up[l]; // beta -> alpha excitation elements @@ -765,7 +764,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-down virtual indices + // sedond excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; // 1-1 excitation elements @@ -782,27 +781,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(ll, kk, det_up); } } - // loop over spin-up occupied indices + // second excitation: alpha -> beta for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices - // for (l = j + 1; l < nvir_up; ++l) { - // ll = virs_up[l]; - // // alpha -> alpha excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // add 2-0 matrix element - // append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - // (ham.two_mo[koffset + n1 * jj + ll] - - // ham.two_mo[koffset + n1 * ll + jj])); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // loop over spin-dn virtual indices for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // alpha -> beta excitation elements @@ -833,10 +815,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long koffset = ioffset + n2 * kk; val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; } - // loop over spin-up virtual indices + // first excitation: beta -> alpha for (j = 0; j < nvir_up; ++j) { jj = virs_up[j]; - // beta -> alpha excitation elements excite_det(ii, jj, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn @@ -845,26 +826,24 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; - koffset = ioffset + n2 * kk + koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk]; + val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; } // add the matrix element append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); } - // loop over spin-down occupied indices + // for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitation: beta -> alpha for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; - // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if excited determinant is in wfn @@ -877,7 +856,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-down virtual indices + // seond excitation: beta -> beta for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements @@ -895,10 +874,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(jj, ii, det_up); } - // loop over spin-down virtual indices + // first excitation: beta -> beta for (j = 0; j < nvir_dn; ++j) { jj = virs_dn[j]; - // beta -> beta excitation elements excite_det(ii, jj, det_up); jdet = wfn.index_det(det_up); // check if 0-1 excited determinant is in wfn @@ -918,27 +896,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); } - // loop over spin-down occupied indices + // second excitation: beta -> beta for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices - // for (l = j + 1; l < nvir_up; ++l) { - // ll = virs_up[l]; - // // beta -> alpha excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // add 0-2 matrix element - // append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - // (ham.two_mo[koffset + n1 * jj + ll] - - // ham.two_mo[koffset + n1 * ll + jj])); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // loop over spin-down virtual indices + for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements From 265dbe23a6dd8c50a19e06fb3eac192fc83a145d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 21:13:17 -0500 Subject: [PATCH 142/197] add temporary counter in the add_row function for NonSingletCI to count no. of cols in a row --- pyci/src/sparseop.cpp | 51 ++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 3a4c586..275db26 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -600,7 +600,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long break; } } - // std::cout << "ham.one_mo.size(): " << ham.one_mo.size() << std::endl; + int counter = 0; + // loop over spin-up occupied indices for (i = 0; i < nocc_up; ++i) { ii = occs_up[i]; @@ -626,9 +627,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); jdet = wfn.index_det(det_up); - // check if 1-0 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // compute 1-0 matrix element + counter += 1; + // compute the matrix element val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; @@ -639,7 +641,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; } - // add 1-0 matrix element append(data, sign_up * val1); append(indices, jdet); std::cout << "jdet: " << jdet << std::endl; @@ -654,9 +655,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll]); @@ -667,12 +668,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - // 1-1 excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_dn) * ham.two_mo[koffset + n1 * jj + ll]); @@ -685,7 +685,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - // // second excitation: alpha -> alpha + // second excitation: alpha -> alpha for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; // alpha -> alpha excitation elements @@ -693,7 +693,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element + counter += 1; + // add the matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -709,7 +710,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * ham.two_mo[koffset + n1 * jj + ll]); append(indices, jdet); @@ -728,6 +729,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + counter += 1; // compute the matrix element val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { @@ -754,9 +756,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll]); @@ -767,12 +768,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // sedond excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - // 1-1 excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll]); @@ -792,7 +792,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -822,7 +822,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // compute the matrix element + counter += 1; val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; @@ -848,7 +848,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -864,7 +864,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll] ); append(indices, jdet); @@ -879,9 +879,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jj = virs_dn[j]; excite_det(ii, jj, det_up); jdet = wfn.index_det(det_up); - // check if 0-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // compute 0-1 matrix element + counter += 1; val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; @@ -892,7 +892,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } - // add 0-1 matrix element + append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); } @@ -908,7 +908,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -926,6 +926,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(indices, idet); } std::cout << "Insinde nonsinglet add_row indices.size(): " << indices.size() << std::endl; + std::cout << "Counter: " << counter << std::endl; // add pointer to next row's indices append(indptr, indices.size()); } From 2843ee81f49859db4714c31c0ae9c4c821c2e219 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 21:15:54 -0500 Subject: [PATCH 143/197] Set default indices stored for dets to -1 long --- pyci/src/ap1rogen.cpp | 80 +++++++++++++++++++++++-------------------- pyci/src/squantop.cpp | 2 +- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 4573c94..6504172 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -339,8 +339,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) exc_info.det.resize(nword); exc_info.pair_inds.resize(1); exc_info.single_inds.resize(1); - exc_info.pair_inds[0] = -1.0; - exc_info.single_inds[0] = -1.0; + exc_info.pair_inds[0] = -1; + exc_info.single_inds[0] = -1; std::cout << "Assigned first elem as -1 to both pair_inds and single_inds" << std::endl; std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); // std::cout << "\nCopied det" << std::endl; @@ -412,7 +412,6 @@ double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, - const double* x, - std::size_t iparam) { +double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector& excitation_inds, + const double* x, + std::size_t iparam) { // double derivative = 0.0; @@ -484,7 +482,9 @@ double AP1roGeneralizedSenoObjective::compute_derivative( if (it == excitation_inds.end()) { return 0.0; } - + if (excitation_inds[0] == -1) { + return 0.0; + } // Create a reduced excitation_inds excluding iparam std::vector reduced_inds = excitation_inds; reduced_inds.erase(it); @@ -511,41 +511,45 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - DetExcParamIndx& exc_info = det_exc_param_indx[idet]; + const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; double pair_permanent = p_permanent[idet]; double single_permanent = s_permanent[idet]; std::cout << "pair_permanent: " << pair_permanent << std::endl; std::cout << "single_permanent: " << single_permanent << std::endl; for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - std::cout << "computing deriv for i: " << iparam << std::endl; - double d_pair = 0.0; - double d_single = 0.0; + std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; + std::cout << "nparam: " << nparam << std::endl; + double d_pair, d_single; std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; - for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { - std::cout << exc_info.pair_inds[i] << " "; - std::cout << exc_info.single_inds[i] << " "; - } - std::cout << "\n"; - if (exc_info.single_inds[0] != -1.0) { - std::cout << "exc_info.single_inds: "; - for (const auto sid : exc_info.single_inds) { - std::cout << sid << " "; - } - std::cout << "\nCalling compute deriv for single_inds\n"; - d_single = compute_derivative(exc_info.single_inds, x, iparam); - std::cout << "calling done\n"; - } + // for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { + // std::cout << exc_info.pair_inds[i] << " "; + // std::cout << exc_info.single_inds[i] << " "; + // } + // std::cout << "\nSize of x: " << &x.size() << std::endl; + d_pair = compute_derivative(exc_info.pair_inds, x, iparam); + d_single = compute_derivative(exc_info.single_inds, x, iparam); + + + // std::size_t idx = 0; + // if (exc_info.pair_inds[idx] != -1) { + // std::cout << "exc_info.pair_inds: "; + // for (const auto pid : exc_info.pair_inds) { + // std::cout << pid << " "; + // } + // d_pair = compute_derivative(exc_info.pair_inds, x, iparam); + // } + // if (exc_info.single_inds[idx] != -1) { + // std::cout << "exc_info.single_inds: "; + // for (const auto sid : exc_info.single_inds) { + // std::cout << sid << " "; + // } + // std::cout << "\nCalling compute deriv for single_inds\n"; + // d_single = compute_derivative(exc_info.single_inds, x, iparam); + // std::cout << "calling done\n"; + // } std::cout << "\nd_single: " << d_single << "\n" ; - if (exc_info.pair_inds[0] != -1.0) { - std::cout << "exc_info.pair_inds: "; - for (const auto sid : exc_info.pair_inds) { - std::cout << sid << " "; - } - d_pair = compute_derivative(exc_info.pair_inds, x, iparam); - } - std::cout << "\nderiv index:" << idet * nparam + iparam << std::endl; y[idet * nparam + iparam] = d_pair * single_permanent + pair_permanent * d_single; } diff --git a/pyci/src/squantop.cpp b/pyci/src/squantop.cpp index f656593..fca0788 100644 --- a/pyci/src/squantop.cpp +++ b/pyci/src/squantop.cpp @@ -112,7 +112,7 @@ SQuantOp::SQuantOp(const std::string &filename) { h = reinterpret_cast(h_array.request().ptr); v = reinterpret_cast(v_array.request().ptr); w = reinterpret_cast(w_array.request().ptr); - std::cout << "size of h: " << h_array.request().size << std::endl; + std::cout << "size of h: file" << h_array.request().size << std::endl; long n1, n2, n3; n1 = nbasis; n2 = n1 * n1; From f7aa442278354f23443d76c82676ae73ba4524c7 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 11:53:22 -0500 Subject: [PATCH 144/197] Update permanent calculation algorithm, add extra structure PermanentResult to capture and report error message --- pyci/include/pyci.h | 24 +++++++++++---- pyci/src/ap1rogen.cpp | 69 +++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 3bc78f8..f5c8d62 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -887,6 +887,22 @@ class APIGObjective : public Objective { virtual void d_overlap(const size_t, const double *x, double *y); }; + + +struct PermanentResult { + std::optional value; + std::string error_message; + + // Constructor for successful result + PermanentResult(double val) + : value(val), error_message("") {} + + // Constructor for error result + PermanentResult(const std::string& error) + : value(std::nullopt), error_message(error) {} + + +}; // Specialize base template class for AP1roGSDGeneralized_sen-o against GenCI Wfn class AP1roGeneralizedSenoObjective : public Objective { public: @@ -897,13 +913,11 @@ class AP1roGeneralizedSenoObjective : public Objective { using Objective::d_ovlp; // Overlap gradient matrix - // Declare variables you want to store to faciliate the computation - // of {d_,}overlap here: - std::vector nexc_list; + // double default_value; std::vector det_exc_param_indx; // Det and excitation details + std::vector nexc_list; std::vector s_permanent; std::vector p_permanent; - double default_value; public: // Keep in mind the {DOCI,FullCI,GenCI}Wfn class names in @@ -941,7 +955,7 @@ class AP1roGeneralizedSenoObjective : public Objective { void init_overlap(const NonSingletCI &); // Permanent calculation: Ryser's Algorithm - double permanent_calculation(const std::vector&, const double* ); + PermanentResult permanent_calculation(const std::vector&, const double* ); // Overlap function // virtual void overlap(const NonSingletCI &, const double *x, double *y); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 6504172..7f49390 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -15,6 +15,7 @@ #include #include +#include #include namespace pyci { @@ -371,43 +372,44 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } -double AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, const double* x) { - std::size_t num_excitations = excitation_inds.size(); - if (num_excitations == 0) { - return 1.0; - } else if (num_excitations == 1) { - return x[excitation_inds[0]]; - } - +PermanentResult AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, const double* x) { + // Ryser's Algorithm + std::size_t n = static_cast(std::sqrt(excitation_inds.size())); + if (n == 0) return 1.0; + if (n == 1) return x[excitation_inds[0]]; + double permanent = 0.0; - std::size_t subset_count = 1UL << num_excitations; + std::size_t subset_count = 1UL << n; // 2^n subsets for (std::size_t subset = 0; subset < subset_count; ++subset) { double rowsumprod = 1.0; - for (std::size_t j = 0; j < num_excitations; ++j) { + for (std::size_t i = 0; i < n; ++i) { double rowsum = 0.0; - for (std::size_t j = 0; j < num_excitations; ++j) { + for (std::size_t j = 0; j < n; ++j) { if (subset & (1UL << j)) { - rowsum += x[excitation_inds[j]]; + rowsum += x[excitation_inds[i * n + j]]; } } if (std::isnan(rowsum) || std::isinf(rowsum)) { - std::cerr << "Error: rowsum is NaN or inf at subset " << subset << ", excitation " << j << std::endl; - return std::numeric_limits::quiet_NaN(); + return {std::nullopt, "Error: rowsum is invalid (NaN or Inf) at subset " + + std::to_string(subset) + ", row " + std::to_string(i)}; } rowsumprod *= rowsum; } if (std::isnan(rowsumprod) || std::isinf(rowsumprod)) { - std::cerr << "Error: rowsumprod is NaN or inf at subset " << subset << std::endl; - return std::numeric_limits::quiet_NaN(); + return {std::nullopt, "Error: rowsumprod is invalid (NaN or Inf) at subset " + + std::to_string(subset)}; } + + // multiply by the parity of the subset permanent += rowsumprod * (1 - ((__builtin_popcount(subset) & 1) << 1)); } - permanent *= ((num_excitations % 2 == 1) ? -1 : 1); + // If n (matrix size) is odd, multiply by -1 + permanent *= ((n % 2 == 1) ? -1 : 1); + if (std::isnan(permanent) || std::isinf(permanent)) { - std::cerr << "Error: permanent is NaN or inf" << std::endl; - return std::numeric_limits::quiet_NaN(); + return {std::nullopt, "Error: permanent is invalid (NaN or Inf)"}; } return permanent; } @@ -416,25 +418,35 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d std::cout << "\nInside overlap" << std::endl; p_permanent.resize(ndet); s_permanent.resize(ndet); + for (std::size_t idet = 0; idet != ndet; ++idet) { - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + if (idet < det_exc_param_indx.size()) { std::cout << "idet: " << idet << " found in storage" << std::endl; // Access the excitation parameter indices const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; - double pair_permanent, single_permanent; - if (exc_info.pair_inds[0] == -1) { - pair_permanent = 1.0; + double pair_permanent = 1.0; + double single_permanent = 1.0; + + if (exc_info.pair_inds[0] != -1) { + pair_permanent = *pair_result.value; } else { - pair_permanent = permanent_calculation(exc_info.pair_inds, x); + std::cerr << "Error in pair_permanent: " << pair_result.error_message << std::endl; + pair_permanent = 0.0; // Default to 0 or another appropriate fallback } - if (exc_info.single_inds[0] == -1) { - single_permanent = 1.0; - } else { - single_permanent = permanent_calculation(exc_info.single_inds, x); + + if (exc_info.single_inds[0] != -1) { + auto single_result = permanent_calculation(exc_info.single_inds, x); + if (single_result.value) { + single_permanent = *single_result.value; + } else { + std::cerr << "Error in single_permanent: " << single_result.error_message << std::endl; + single_permanent = 0.0; // Default to 0 or another appropriate fallback + } } + p_permanent[idet] = pair_permanent; s_permanent[idet] = single_permanent; @@ -448,6 +460,7 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d } std::cout << "\npair_permanent: " << pair_permanent << std::endl; std::cout << "single_permanent: " << single_permanent << std::endl; + if (y != nullptr && idet < ndet) { y[idet] = pair_permanent * single_permanent; } else { From e4b15145687f1ec531fbe3a312028e3c34afb98d Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 12:19:18 -0500 Subject: [PATCH 145/197] Update the bool return for the overlap and corresponding helper functions --- pyci/include/pyci.h | 19 +------- pyci/src/ap1rogen.cpp | 102 ++++++++++++++---------------------------- 2 files changed, 36 insertions(+), 85 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index f5c8d62..228830b 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -888,21 +888,6 @@ class APIGObjective : public Objective { }; - -struct PermanentResult { - std::optional value; - std::string error_message; - - // Constructor for successful result - PermanentResult(double val) - : value(val), error_message("") {} - - // Constructor for error result - PermanentResult(const std::string& error) - : value(std::nullopt), error_message(error) {} - - -}; // Specialize base template class for AP1roGSDGeneralized_sen-o against GenCI Wfn class AP1roGeneralizedSenoObjective : public Objective { public: @@ -955,14 +940,14 @@ class AP1roGeneralizedSenoObjective : public Objective { void init_overlap(const NonSingletCI &); // Permanent calculation: Ryser's Algorithm - PermanentResult permanent_calculation(const std::vector&, const double* ); + bool permanent_calculation(const std::vector&, const double*, double&); // Overlap function // virtual void overlap(const NonSingletCI &, const double *x, double *y); virtual void overlap(const std::size_t, const double *x, double *y); // Helper function for d_overlap - double compute_derivative(const std::vector& excitation_indices, const double*, std::size_t ); + bool compute_derivative(const std::vector& excitation_indices, const double*, std::size_t, double& ); // Overlap gradient function // virtual void d_overlap(const NonSingletCI &, const size_t, const double *x, double *y); diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 7f49390..21fd09d 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -256,7 +256,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector::quiet_NaN(); + // default_value = std::numeric_limits::quiet_NaN(); std::cout << "Inside init_overlap" << std::endl; // Initialize your class-specific variables here // init_Overlap objective for the AP1roGSDspin_sen-o @@ -372,13 +372,12 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } -PermanentResult AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, const double* x) { +bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector& excitation_inds, const double* x, double& permanent) { // Ryser's Algorithm std::size_t n = static_cast(std::sqrt(excitation_inds.size())); - if (n == 0) return 1.0; - if (n == 1) return x[excitation_inds[0]]; + if (n == 0) {permanent = 1.0; return true;} + if (n == 1) {permanent = x[excitation_inds[0]]; return true;} - double permanent = 0.0; std::size_t subset_count = 1UL << n; // 2^n subsets for (std::size_t subset = 0; subset < subset_count; ++subset) { @@ -392,14 +391,14 @@ PermanentResult AP1roGeneralizedSenoObjective::permanent_calculation(const std:: } } if (std::isnan(rowsum) || std::isinf(rowsum)) { - return {std::nullopt, "Error: rowsum is invalid (NaN or Inf) at subset " + - std::to_string(subset) + ", row " + std::to_string(i)}; + std::cerr << "Error: rowsum is invalid (NaN or Inf) at subset " << subset << std::endl; + return false; } rowsumprod *= rowsum; } if (std::isnan(rowsumprod) || std::isinf(rowsumprod)) { - return {std::nullopt, "Error: rowsumprod is invalid (NaN or Inf) at subset " + - std::to_string(subset)}; + std::cerr << "Error: rowsumprod is invalid (NaN or Inf) at subset " << subset << std::endl; + return false; } // multiply by the parity of the subset @@ -409,9 +408,10 @@ PermanentResult AP1roGeneralizedSenoObjective::permanent_calculation(const std:: permanent *= ((n % 2 == 1) ? -1 : 1); if (std::isnan(permanent) || std::isinf(permanent)) { - return {std::nullopt, "Error: permanent is invalid (NaN or Inf)"}; + std::cerr << "Error: permanent is invalid (NaN or Inf)" << std::endl; + return false; } - return permanent; + return true; } void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { @@ -431,19 +431,16 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d double single_permanent = 1.0; if (exc_info.pair_inds[0] != -1) { - pair_permanent = *pair_result.value; - } else { - std::cerr << "Error in pair_permanent: " << pair_result.error_message << std::endl; - pair_permanent = 0.0; // Default to 0 or another appropriate fallback + if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { + std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; + pair_permanent = 0.0; // Default to 0 or another appropriate fallback + } } if (exc_info.single_inds[0] != -1) { - auto single_result = permanent_calculation(exc_info.single_inds, x); - if (single_result.value) { - single_permanent = *single_result.value; - } else { - std::cerr << "Error in single_permanent: " << single_result.error_message << std::endl; - single_permanent = 0.0; // Default to 0 or another appropriate fallback + if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { + std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; + single_permanent = 0.0; // Default value on error } } @@ -478,9 +475,9 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d } -double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector& excitation_inds, +bool AP1roGeneralizedSenoObjective::compute_derivative(const std::vector& excitation_inds, const double* x, - std::size_t iparam) { + std::size_t iparam, double& reduced_permanent) { // double derivative = 0.0; @@ -492,19 +489,18 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector // check if iparam is within excitation_inds auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); - if (it == excitation_inds.end()) { - return 0.0; - } - if (excitation_inds[0] == -1) { - return 0.0; - } + if (it == excitation_inds.end()) reduced_permanent = 0.0; + if (excitation_inds[0] == -1) reduced_permanent = 1.0; + // Create a reduced excitation_inds excluding iparam std::vector reduced_inds = excitation_inds; reduced_inds.erase(it); - double reduced_permanent = permanent_calculation(reduced_inds, x); + if (permanent_calculation(reduced_inds, x, reduced_permanent)) { + return reduced_permanent; + } - return reduced_permanent; + return false; } @@ -533,7 +529,8 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x for (std::size_t iparam = 0; iparam < nparam; ++iparam) { std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; std::cout << "nparam: " << nparam << std::endl; - double d_pair, d_single; + double dpair = 0.0; + double dsingle = 0.0; std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; // for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { @@ -541,8 +538,8 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // std::cout << exc_info.single_inds[i] << " "; // } // std::cout << "\nSize of x: " << &x.size() << std::endl; - d_pair = compute_derivative(exc_info.pair_inds, x, iparam); - d_single = compute_derivative(exc_info.single_inds, x, iparam); + compute_derivative(exc_info.pair_inds, x, iparam, dpair); + compute_derivative(exc_info.single_inds, x, iparam, dsingle); // std::size_t idx = 0; @@ -562,42 +559,11 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // d_single = compute_derivative(exc_info.single_inds, x, iparam); // std::cout << "calling done\n"; // } - std::cout << "\nd_single: " << d_single << "\n" ; + std::cout << "\ndsingle: " << dsingle << "\n" ; std::cout << "\nderiv index:" << idet * nparam + iparam << std::endl; - y[idet * nparam + iparam] = d_pair * single_permanent + pair_permanent * d_single; + y[idet * nparam + iparam] = dpair * single_permanent + pair_permanent * dsingle; } - - // Loop over each parameter (paired and single excitations) - // std::size_t param_index = 0; - - // Derivative for paired excitations - // for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { - // // Get the excitation index for the pair - // const std::size_t excitation_idx = exc_info.pair_inds[i]; - - // // Compute the derivative of the permanent with respect to this excitation - // double derivative = compute_derivative(exc_info.pair_inds, x, excitation_idx); - - // // Store the result in the output vector d_ovlp (size ndet * nparam) - // y[idet * nparam + param_index] = derivative; - - // ++param_index; - // } - - // Derivative for single excitations - // for (std::size_t i = 0; i < exc_info.single_inds.size(); ++i) { - // // Get the excitation index for the single - // const std::size_t excitation_idx = exc_info.single_inds[i]; - - // // Compute the derivative of the permanent with respect to this excitation - // double derivative = compute_derivative(exc_info.single_inds, x, excitation_idx); - - // // Store the result in the output vector d_ovlp (size ndet * nparam) - // y[idet * nparam + param_index] *= derivative; - - // ++param_index; - // } - } +} else { std::cout << "Determinant " << idet << " not found in det_map" << std::endl; // Set all derivatives to zero if determinant is not found From b9fe6a9ca4daab1d3ec8cd5c833b2b2d5ac1cd72 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 12:23:46 -0500 Subject: [PATCH 146/197] update the varible type for max_pairs in generate_excitations --- pyci/src/ap1rogen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 21fd09d..6db1ed6 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -152,7 +152,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector>s::size_type max_pairs = occ_pairs.size(); bool nvir_pairs = false; if (max_pairs == vir_pairs.size()) { nvir_pairs = true; From 3dc62875afe2e1fbcba12f029352fa585d530b05 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 12:29:53 -0500 Subject: [PATCH 147/197] Fix the order of initialization in the constructor and declaration of members: nexc_list, det_exc_param_indx struct --- pyci/src/ap1rogen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 6db1ed6..f0cc339 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -51,7 +51,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_ // Copy Constructor // obj is the constant reference to another object to be copied AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGeneralizedSenoObjective &obj) -: Objective::Objective(obj), nexc_list(obj.nexc_list), det_exc_param_indx(obj.det_exc_param_indx) +: Objective::Objective(obj), det_exc_param_indx(obj.det_exc_param_indx), nexc_list(obj.nexc_list) { return; } @@ -59,7 +59,7 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGenerali // Move constructor // obj is the rvalue reference to another object to be moved AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&obj) noexcept -: Objective::Objective(obj), nexc_list(std::move(obj.nexc_list)) +: Objective::Objective(obj), det_exc_param_indx(obj.det_exc_param_indx), nexc_list(std::move(obj.nexc_list)) { return; } @@ -152,7 +152,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector>s::size_type max_pairs = occ_pairs.size(); + std::vector>::size_type max_pairs = occ_pairs.size(); bool nvir_pairs = false; if (max_pairs == vir_pairs.size()) { nvir_pairs = true; From 5e8d9d06f124914469b0b64a33b068b17798724a Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 12:35:00 -0500 Subject: [PATCH 148/197] fix the warning issues for the accessing the pairs --- pyci/src/ap1rogen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index f0cc339..ca14b9f 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -164,11 +164,13 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector Date: Wed, 11 Dec 2024 21:13:17 -0500 Subject: [PATCH 149/197] add temporary counter in the add_row function for NonSingletCI to count no. of cols in a row --- pyci/src/sparseop.cpp | 51 ++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 6893499..1ad7458 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -600,7 +600,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long break; } } - // std::cout << "ham.one_mo.size(): " << ham.one_mo.size() << std::endl; + int counter = 0; + // loop over spin-up occupied indices for (i = 0; i < nocc_up; ++i) { ii = occs_up[i]; @@ -626,9 +627,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); jdet = wfn.index_det(det_up); - // check if 1-0 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // compute 1-0 matrix element + counter += 1; + // compute the matrix element val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; @@ -639,7 +641,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; } - // add 1-0 matrix element append(data, sign_up * val1); append(indices, jdet); std::cout << "jdet: " << jdet << std::endl; @@ -654,9 +655,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll]); @@ -667,12 +668,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-down virtual indices for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - // 1-1 excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_dn) * ham.two_mo[koffset + n1 * jj + ll]); @@ -685,7 +685,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitation: alpha -> alpha for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; // alpha -> alpha excitation elements @@ -693,7 +693,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element + counter += 1; + // add the matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -709,7 +710,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -730,6 +731,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + counter += 1; // compute the matrix element val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { @@ -755,9 +757,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll]); @@ -768,12 +769,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-down virtual indices for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - // 1-1 excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // check if 1-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 1-1 matrix element + counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * ham.two_mo[koffset + n1 * jj + ll]); @@ -810,7 +810,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 2-0 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -841,7 +841,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // compute the matrix element + counter += 1; val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; @@ -868,7 +868,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -884,7 +884,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -901,9 +901,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // beta -> beta excitation elements excite_det(ii, jj, det_up); jdet = wfn.index_det(det_up); - // check if 0-1 excited determinant is in wfn + // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // compute 0-1 matrix element + counter += 1; val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; @@ -914,7 +914,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } - // add 0-1 matrix element + append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); } @@ -946,7 +946,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // add 0-2 matrix element + counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -964,6 +964,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(indices, idet); } std::cout << "Insinde nonsinglet add_row indices.size(): " << indices.size() << std::endl; + std::cout << "Counter: " << counter << std::endl; // add pointer to next row's indices append(indptr, indices.size()); } From 32e72b510c7c5294c2cf54e6bb211271068e9863 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 20:56:26 -0500 Subject: [PATCH 150/197] Update the matrix elements calculations and clean up the add_row function --- pyci/src/sparseop.cpp | 73 +++++++++++-------------------------------- 1 file changed, 18 insertions(+), 55 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 1ad7458..9a1d818 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -619,7 +619,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; val2 += ham.two_mo[ioffset + n2 * kk + n1 * ii + kk]; } - // loop over spin-up virtual indices + // first excitation: alpha -> alpha for (j = 0; j < nvir_up; ++j) { jj = virs_up[j]; // alpha -> alpha excitation elements @@ -649,7 +649,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitation: beta -> alpha for (l = 0; l < nvir_up; ++l) { ll = virs_up[l]; // beta -> alpha excitation elements @@ -665,7 +665,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-down virtual indices + // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; excite_det(kk, ll, det_dn); @@ -702,7 +702,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-dn virtual indices + // second excitation: alpha -> beta for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // alpha -> beta excitation elements @@ -722,10 +722,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(jj, ii, det_up); } - // loop over spin-dn virtual indices + // first excitation: alpha -> beta for (j = 0; j < nvir_dn; ++j) { jj = virs_dn[j]; - // alpha -> beta excitation elements excite_det(ii, jj, det_up); sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); jdet = wfn.index_det(det_up); @@ -751,7 +750,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitaiton: beta -> alpha for (l = 0; l < nvir_up; ++l) { ll = virs_up[l]; // beta -> alpha excitation elements @@ -766,7 +765,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-down virtual indices + // sedond excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; excite_det(kk, ll, det_up); @@ -782,27 +781,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(ll, kk, det_up); } } - // loop over spin-up occupied indices + // second excitation: alpha -> beta for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices - // for (l = j + 1; l < nvir_up; ++l) { - // ll = virs_up[l]; - // // alpha -> alpha excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // add 2-0 matrix element - // append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - // (ham.two_mo[koffset + n1 * jj + ll] - - // ham.two_mo[koffset + n1 * ll + jj])); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // loop over spin-dn virtual indices for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // alpha -> beta excitation elements @@ -833,10 +815,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long koffset = ioffset + n2 * kk; val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; } - // loop over spin-up virtual indices + // first excitation: beta -> alpha for (j = 0; j < nvir_up; ++j) { jj = virs_up[j]; - // beta -> alpha excitation elements excite_det(ii, jj, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn @@ -845,25 +826,24 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; } // add the matrix element append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); } - // loop over spin-down occupied indices + // for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices + // second excitation: beta -> alpha for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; - // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if excited determinant is in wfn @@ -876,7 +856,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // loop over spin-down virtual indices + // seond excitation: beta -> beta for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements @@ -895,10 +875,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(jj, ii, det_up); } - // loop over spin-down virtual indices + // first excitation: beta -> beta for (j = 0; j < nvir_dn; ++j) { jj = virs_dn[j]; - // beta -> beta excitation elements excite_det(ii, jj, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn @@ -918,27 +897,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); } - // loop over spin-down occupied indices + // second excitation: beta -> beta for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // loop over spin-up virtual indices - // for (l = j + 1; l < nvir_up; ++l) { - // ll = virs_up[l]; - // // beta -> alpha excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // add 0-2 matrix element - // append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - // (ham.two_mo[koffset + n1 * jj + ll] - - // ham.two_mo[koffset + n1 * ll + jj])); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // loop over spin-down virtual indices + for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements From c1ab6cd0abfc2ac78994fa32f9efbe2916f6028e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 18:10:31 -0500 Subject: [PATCH 151/197] Updated matrix elements terms in add_row --- pyci/src/sparseop.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 9a1d818..18da955 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -712,8 +712,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + ham.two_mo[koffset + n1 * jj + ll]); append(indices, jdet); } excite_det(ll, kk, det_dn); @@ -736,11 +735,12 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + val1 += ham.two_mo[koffset + n1 * jj + kk]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } // add the matrix element append(data, sign_up * val1); @@ -826,12 +826,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; - koffset = ioffset + n2 * kk; + koffset = ioffset + n2 * kk val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + koffset = ioffset + n2 * kk; + val1 += ham.two_mo[koffset + n1 * jj + kk]; } // add the matrix element append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); @@ -866,8 +867,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + ham.two_mo[koffset + n1 * jj + ll] ); append(indices, jdet); } excite_det(ll, kk, det_up); From b05a6ea20656a48732bdf65345be3682b923f06b Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 11 Dec 2024 14:45:23 -0500 Subject: [PATCH 152/197] Fix input for fill_virs in add_row --- pyci/src/sparseop.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 18da955..ac856f5 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -565,9 +565,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); // !Check nword or nword2 fill_occs(wfn.nword, rdet_up, occs); - fill_virs(wfn.nword, nbasis, rdet_up, virs); + fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); - long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis / 2) - 1)); + long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis) - 1)); long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; From f777e4f37897942e3af3c1329b2a40de6596b1cd Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 15:41:36 -0500 Subject: [PATCH 153/197] Correct the matrix elements for NonSingletCI in add_row: If matrix elements differ by >=1 orbitals, then the matrix elements will be zero if number of alphas (betas) in orbitals unique to K != number of alphas (betas) in orbitals unique to L --- pyci/src/sparseop.cpp | 155 +++++++++++++++++------------------------- 1 file changed, 62 insertions(+), 93 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 275db26..0427651 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -554,7 +554,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); long ioffset, koffset, sign_up; long nbasis = wfn.nbasis / 2; - long n1 = nbasis; // Check if nbasis or nbasis * 2! + long n1 = nbasis; long n2 = n1 * n1; long n3 = n1 * n2; double val1, val2 = 0.0; @@ -562,13 +562,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long const ulong *rdet_dn = rdet_up + nbasis; std::cout << "rdet_up: " << *rdet_up << std::endl; ulong *det_dn = det_up + nbasis; - std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); // !Check nword or nword2 + std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); fill_occs(wfn.nword, rdet_up, occs); fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis) - 1)); - long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); + long nocc_dn = wfn.nocc - nocc_up; long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; long nvir = nvir_up + nvir_dn; @@ -645,77 +645,74 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(indices, jdet); std::cout << "jdet: " << jdet << std::endl; } - // loop over spin-down occupied indices - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; + // loop over spin-up occupied indices + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; koffset = ioffset + n2 * kk; - // second excitation: beta -> alpha - for (l = 0; l < nvir_up; ++l) { + // second excitation: alpha -> alpha + for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; - // beta -> alpha excitation elements + // alpha -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]); + counter += 1; + // add the matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); append(indices, jdet); } - excite_det(ll, kk, det_up); + excite_det(ll, kk, det_up); } - // second excitation: beta -> beta - for (l = 0; l < nvir_dn; ++l) { + // second excitation: alpha -> beta + for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; + // alpha -> beta excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_dn) * - ham.two_mo[koffset + n1 * jj + ll]); + append(data, 0.0); append(indices, jdet); } - excite_det(ll, kk, det_dn); + excite_det(ll, kk, det_dn); } } - // loop over spin-up occupied indices - for (k = i + 1; k < nocc_up; ++k) { - kk = occs_up[k]; + + // loop over spin-down occupied indices + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // second excitation: alpha -> alpha - for (l = j + 1; l < nvir_up; ++l) { + // second excitation: beta -> alpha + for (l = 0; l < nvir_up; ++l) { ll = virs_up[l]; - // alpha -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - // add the matrix element - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + counter += 1; + append(data, 0.0); append(indices, jdet); } - excite_det(ll, kk, det_up); + excite_det(ll, kk, det_up); } - // second excitation: alpha -> beta - for (l = j + 1; l < nvir_dn; ++l) { + // second excitation: beta -> beta + for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - // alpha -> beta excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * - ham.two_mo[koffset + n1 * jj + ll]); + append(data, sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_dn) * + ham.two_mo[koffset + n1 * jj + ll]); append(indices, jdet); } - excite_det(ll, kk, det_dn); + excite_det(ll, kk, det_dn); } } excite_det(jj, ii, det_up); @@ -730,22 +727,28 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - // compute the matrix element - val1 = ham.one_mo[n1 * ii + jj]; - for (k = 0; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk]; - } - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; - } // add the matrix element - append(data, sign_up * val1); + append(data, 0.0); append(indices, jdet); } + // second excitation: alpha -> beta + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + for (l = j + 1; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // alpha -> beta excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + counter += 1; + append(data, 0.0); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + } // loop over spin-down occupied indices for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; @@ -760,7 +763,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]); + (-ham.two_mo[koffset + n1 * ll + jj])); append(indices, jdet); } excite_det(ll, kk, det_up); @@ -773,34 +776,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]); + append(data, 0.0); append(indices, jdet); } excite_det(ll, kk, det_up); } } - // second excitation: alpha -> beta - for (k = i + 1; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk; - for (l = j + 1; l < nvir_dn; ++l) { - ll = virs_dn[l]; - // alpha -> beta excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } - } + excite_det(jj, ii, det_up); } } @@ -823,21 +805,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - val1 = ham.one_mo[n1 * ii + jj]; - for (k = 0; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; - } - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; - } // add the matrix element - append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); + append(data, 0.0); append(indices, jdet); } - // + for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; @@ -849,15 +821,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + append(data, 0.0); append(indices, jdet); } excite_det(ll, kk, det_up); } // seond excitation: beta -> beta - for (l = j + 1; l < nvir_dn; ++l) { + for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements excite_det(kk, ll, det_up); @@ -865,8 +835,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll] ); + append(data, 0.0); append(indices, jdet); } excite_det(ll, kk, det_up); From d344701f3386505bfd89ffc558d75f5f87de9db8 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 15:41:36 -0500 Subject: [PATCH 154/197] Correct the matrix elements for NonSingletCI in add_row: If matrix elements differ by >=1 orbitals, then the matrix elements will be zero if number of alphas (betas) in orbitals unique to K != number of alphas (betas) in orbitals unique to L --- pyci/src/sparseop.cpp | 156 +++++++++++++++++------------------------- 1 file changed, 62 insertions(+), 94 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index ac856f5..34fe508 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -554,7 +554,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); long ioffset, koffset, sign_up; long nbasis = wfn.nbasis / 2; - long n1 = nbasis; // Check if nbasis or nbasis * 2! + long n1 = nbasis; long n2 = n1 * n1; long n3 = n1 * n2; double val1, val2 = 0.0; @@ -562,13 +562,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long const ulong *rdet_dn = rdet_up + nbasis; std::cout << "rdet_up: " << *rdet_up << std::endl; ulong *det_dn = det_up + nbasis; - std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); // !Check nword or nword2 + std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); fill_occs(wfn.nword, rdet_up, occs); fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis) - 1)); - long nocc_dn = wfn.nocc - nocc_up; // std:popcount(det_up>> wfn.nbasis / 2); + long nocc_dn = wfn.nocc - nocc_up; long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; long nvir = nvir_up + nvir_dn; @@ -645,77 +645,74 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(indices, jdet); std::cout << "jdet: " << jdet << std::endl; } - // loop over spin-down occupied indices - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; + // loop over spin-up occupied indices + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; koffset = ioffset + n2 * kk; - // second excitation: beta -> alpha - for (l = 0; l < nvir_up; ++l) { + // second excitation: alpha -> alpha + for (l = j + 1; l < nvir_up; ++l) { ll = virs_up[l]; - // beta -> alpha excitation elements + // alpha -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]); + counter += 1; + // add the matrix element + append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); append(indices, jdet); } - excite_det(ll, kk, det_up); + excite_det(ll, kk, det_up); } - // second excitation: beta -> beta + // second excitation: alpha -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; + // alpha -> beta excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_dn) * - ham.two_mo[koffset + n1 * jj + ll]); + append(data, 0.0); append(indices, jdet); } - excite_det(ll, kk, det_dn); + excite_det(ll, kk, det_dn); } } - // loop over spin-up occupied indices - for (k = i + 1; k < nocc_up; ++k) { - kk = occs_up[k]; + + // loop over spin-down occupied indices + for (k = 0; k < nocc_dn; ++k) { + kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // second excitation: alpha -> alpha - for (l = j + 1; l < nvir_up; ++l) { + // second excitation: beta -> alpha + for (l = j+1; l < nvir_up; ++l) { ll = virs_up[l]; - // alpha -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - // add the matrix element - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + counter += 1; + append(data, 0.0); append(indices, jdet); } - excite_det(ll, kk, det_up); + excite_det(ll, kk, det_up); } - // second excitation: alpha -> beta - for (l = j + 1; l < nvir_dn; ++l) { + // second excitation: beta -> beta + for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - // alpha -> beta excitation elements excite_det(kk, ll, det_dn); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_dn) * - ham.two_mo[koffset + n1 * jj + ll]); + append(data, sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_dn) * + ham.two_mo[koffset + n1 * jj + ll]); append(indices, jdet); } - excite_det(ll, kk, det_dn); + excite_det(ll, kk, det_dn); } } excite_det(jj, ii, det_up); @@ -730,22 +727,28 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - // compute the matrix element - val1 = ham.one_mo[n1 * ii + jj]; - for (k = 0; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk]; - } - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; - } // add the matrix element - append(data, sign_up * val1); + append(data, 0.0); append(indices, jdet); } + // second excitation: alpha -> beta + for (k = i + 1; k < nocc_up; ++k) { + kk = occs_up[k]; + koffset = ioffset + n2 * kk; + for (l = j + 1; l < nvir_dn; ++l) { + ll = virs_dn[l]; + // alpha -> beta excitation elements + excite_det(kk, ll, det_up); + jdet = wfn.index_det(det_up); + // check if the excited determinant is in wfn + if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + counter += 1; + append(data, 0.0); + append(indices, jdet); + } + excite_det(ll, kk, det_up); + } + } // loop over spin-down occupied indices for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; @@ -760,47 +763,26 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long counter += 1; append(data, sign_up * phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]); + (-ham.two_mo[koffset + n1 * ll + jj])); append(indices, jdet); } excite_det(ll, kk, det_up); } // sedond excitation: beta -> beta - for (l = 0; l < nvir_dn; ++l) { + for (l = j+1; l < nvir_dn; ++l) { ll = virs_dn[l]; excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]); + append(data, 0.0); append(indices, jdet); } excite_det(ll, kk, det_up); } } - // second excitation: alpha -> beta - for (k = i + 1; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk; - for (l = j + 1; l < nvir_dn; ++l) { - ll = virs_dn[l]; - // alpha -> beta excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } - } + excite_det(jj, ii, det_up); } } @@ -823,22 +805,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - val1 = ham.one_mo[n1 * ii + jj]; - for (k = 0; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; - } - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk]; - } // add the matrix element - append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); + append(data, 0.0); append(indices, jdet); } - // + for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; @@ -850,15 +821,13 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + append(data, 0.0); append(indices, jdet); } excite_det(ll, kk, det_up); } // seond excitation: beta -> beta - for (l = j + 1; l < nvir_dn; ++l) { + for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements excite_det(kk, ll, det_up); @@ -866,8 +835,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll] ); + append(data, 0.0); append(indices, jdet); } excite_det(ll, kk, det_up); From b494617f190561c43a84080e4fb0bc0d136e3cbb Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 12 Dec 2024 15:41:36 -0500 Subject: [PATCH 155/197] Correct the matrix elements for NonSingletCI in add_row: If matrix elements differ by >=1 orbitals, then the matrix elements will be zero if number of alphas (betas) in orbitals unique to K != number of alphas (betas) in orbitals unique to L --- pyci/src/sparseop.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 0427651..34fe508 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -667,7 +667,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(ll, kk, det_up); } // second excitation: alpha -> beta - for (l = j + 1; l < nvir_dn; ++l) { + for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; // alpha -> beta excitation elements excite_det(kk, ll, det_dn); @@ -687,7 +687,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; koffset = ioffset + n2 * kk; // second excitation: beta -> alpha - for (l = 0; l < nvir_up; ++l) { + for (l = j+1; l < nvir_up; ++l) { ll = virs_up[l]; excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); @@ -769,7 +769,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(ll, kk, det_up); } // sedond excitation: beta -> beta - for (l = 0; l < nvir_dn; ++l) { + for (l = j+1; l < nvir_dn; ++l) { ll = virs_dn[l]; excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); From a286acdf932eb7912e6db9edd0297a1882545b77 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Fri, 13 Dec 2024 13:29:46 -0500 Subject: [PATCH 156/197] Initialize the permanent with 0.0 and ensure all inds are getting stored and not wiping down the previous ones before adding a new one in the generate_excitation function --- pyci/src/ap1rogen.cpp | 53 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index ca14b9f..c080f9f 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -197,7 +197,9 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector(std::sqrt(excitation_inds.size())); if (n == 0) {permanent = 1.0; return true;} if (n == 1) {permanent = x[excitation_inds[0]]; return true;} - + permanent = 0.0; std::size_t subset_count = 1UL << n; // 2^n subsets - + // std::cout << "\npermanent: " << permanent << std::endl; for (std::size_t subset = 0; subset < subset_count; ++subset) { double rowsumprod = 1.0; for (std::size_t i = 0; i < n; ++i) { double rowsum = 0.0; for (std::size_t j = 0; j < n; ++j) { + // std::cout << "\ni: " << i << ", j: " << j << ", rowsum: " << rowsum << std::endl; if (subset & (1UL << j)) { rowsum += x[excitation_inds[i * n + j]]; + // std::cout << "x[" << excitation_inds[i * n + j] << "]: " << x[excitation_inds[i * n + j]] << std::endl; } + // std::cout << "updated rowsum: " << rowsum << std::endl; } if (std::isnan(rowsum) || std::isinf(rowsum)) { std::cerr << "Error: rowsum is invalid (NaN or Inf) at subset " << subset << std::endl; return false; } rowsumprod *= rowsum; + // std::cout << "rowsumprod: " << rowsumprod << std::endl; } if (std::isnan(rowsumprod) || std::isinf(rowsumprod)) { std::cerr << "Error: rowsumprod is invalid (NaN or Inf) at subset " << subset << std::endl; @@ -404,10 +418,13 @@ bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector Date: Mon, 16 Dec 2024 12:45:59 -0500 Subject: [PATCH 157/197] Add_row function for NonSingletCI: correctly accesss the MOs, same indices for up, dn spin orbs --- pyci/src/sparseop.cpp | 144 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 125 insertions(+), 19 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 34fe508..b2d5036 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -266,6 +266,8 @@ void SparseOp::add_row(const SQuantOp &ham, const DOCIWfn &wfn, const long idet, long jdet, jmin = symmetric ? idet : Max(); double val1 = 0.0, val2 = 0.0; wfn.copy_det(idet, det); + std::cout << "Inside add_row DOCIWfn" << std::endl; + std::cout << "rdet: " << *wfn.det_ptr(idet) << std::endl; fill_occs(wfn.nword, det, occs); fill_virs(wfn.nword, wfn.nbasis, det, virs); // loop over occupied indices @@ -284,6 +286,7 @@ void SparseOp::add_row(const SQuantOp &ham, const DOCIWfn &wfn, const long idet, jdet = wfn.index_det(det); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "det: " << *det << std::endl; // add single/"pair"-excited matrix element append(data, ham.v[k * wfn.nbasis + l]); append(indices, jdet); @@ -296,6 +299,10 @@ void SparseOp::add_row(const SQuantOp &ham, const DOCIWfn &wfn, const long idet, append(data, val1 + val2 * 2); append(indices, idet); } + std::cout << "data: " ; + for (auto i : data) { + std::cout << i << " "; + } // add pointer to next row's indices append(indptr, indices.size()); } @@ -605,18 +612,22 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-up occupied indices for (i = 0; i < nocc_up; ++i) { ii = occs_up[i]; + if (ii >= nbasis) ii -= nbasis; ioffset = n3 * ii; + ii = occs_up[i]; // compute part of diagonal matrix element val2 += ham.one_mo[(n1 + 1) * ii]; for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; + if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; - std::cout << "ii, kk: " << ii << ", " << kk << std::endl; + } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; + if (kk >= nbasis) kk -= nbasis; val2 += ham.two_mo[ioffset + n2 * kk + n1 * ii + kk]; } // first excitation: alpha -> alpha @@ -629,20 +640,28 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + if (jj >= nbasis) jj -= nbasis; + // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; // compute the matrix element val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; + if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; + if (kk >= nbasis) kk -= nbasis; val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; } append(data, sign_up * val1); append(indices, jdet); + jj = virs_up[j]; + + std::cout << "ii, jj: " << ii << ", " << jj << std::endl; + std::cout << "s_val: " << val1 << std::endl; std::cout << "jdet: " << jdet << std::endl; } // loop over spin-up occupied indices @@ -655,14 +674,22 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // alpha -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); + // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "aaaa: " << *det_up << std::endl; // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "1_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])) << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; + // add the matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); - append(indices, jdet); + append(indices, jdet); } excite_det(ll, kk, det_up); } @@ -670,15 +697,18 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; // alpha -> beta excitation elements - excite_det(kk, ll, det_dn); + excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "2_val: 0.0" << std::endl; counter += 1; append(data, 0.0); append(indices, jdet); } - excite_det(ll, kk, det_dn); + excite_det(ll, kk, det_up); } } @@ -693,6 +723,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "3_val: 0.0" << std::endl; counter += 1; append(data, 0.0); append(indices, jdet); @@ -702,17 +735,36 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - excite_det(kk, ll, det_dn); + excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); + // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "aabb ndet_up: " << *det_up << std::endl; // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "\nii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + if (jj >= nbasis) jj -= nbasis; + if (kk >= nbasis) kk -= nbasis; + if (ll >= nbasis) ll -= nbasis; + + std::cout << "updated ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + + std::cout << "4_val: " << (sign_up * + phase_single_det(wfn.nword, kk, ll, rdet_up) * + ham.two_mo[koffset + n1 * jj + ll]) << std::endl; counter += 1; + // append(data, sign_up * + // phase_single_det(wfn.nword, kk, ll, rdet_up) * + // ham.two_mo[koffset + n1 * jj + ll]); append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_dn) * - ham.two_mo[koffset + n1 * jj + ll]); + phase_single_det(wfn.nword, kk, ll, rdet_up) * + ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); append(indices, jdet); + ll = virs_dn[l]; + kk = occs_dn[k]; + jj = virs_up[j]; } - excite_det(ll, kk, det_dn); + excite_det(ll, kk, det_up); } } excite_det(jj, ii, det_up); @@ -726,6 +778,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, jj: " << ii << ", " << jj << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "s_val: 0.0" << std::endl; counter += 1; // add the matrix element append(data, 0.0); @@ -742,6 +797,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "5_val: 0.0" << std::endl; counter += 1; append(data, 0.0); append(indices, jdet); @@ -756,15 +814,23 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // second excitaiton: beta -> alpha for (l = 0; l < nvir_up; ++l) { ll = virs_up[l]; - // beta -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - counter += 1; - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - (-ham.two_mo[koffset + n1 * ll + jj])); - append(indices, jdet); + // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "ndet_up: " << *det_up << std::endl; + if (kk < nbasis) kk -= nbasis; + if (ll < nbasis) ll -= nbasis; + // std::cout << "6_val: " << (sign_up * + // phase_single_det(wfn.nword, kk, ll, rdet_up) * + // (-ham.two_mo[koffset + n1 * ll + jj])) << std::endl; + // counter += 1; + // append(data, sign_up * + // phase_single_det(wfn.nword, kk, ll, rdet_up) * + // (-ham.two_mo[koffset + n1 * ll + jj])); + // append(indices, jdet); + kk = occs_dn[k]; + ll = virs_up[l]; } excite_det(ll, kk, det_up); } @@ -775,6 +841,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "7_val: 0.0" << std::endl; counter += 1; append(data, 0.0); append(indices, jdet); @@ -789,14 +858,17 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-down occupied indices for (i = 0; i < nocc_dn; ++i) { ii = occs_dn[i]; + if (ii >= nbasis) ii -= nbasis; ioffset = n3 * ii; // compute part of diagonal matrix element val2 += ham.one_mo[(n1 + 1) * ii]; for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; + if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; - } + } + ii = occs_dn[i]; // first excitation: beta -> alpha for (j = 0; j < nvir_up; ++j) { jj = virs_up[j]; @@ -804,6 +876,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, jj: " << ii << ", " << jj << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "s_val: 0.0" << std::endl; counter += 1; // add the matrix element append(data, 0.0); @@ -820,6 +895,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "8_val: 0.0" << std::endl; counter += 1; append(data, 0.0); append(indices, jdet); @@ -834,6 +912,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "9_val: 0.0" << std::endl; counter += 1; append(data, 0.0); append(indices, jdet); @@ -850,6 +931,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + if (jj >= nbasis) jj -= nbasis; + std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { @@ -858,30 +941,44 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; + if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); + jj = virs_dn[j]; } // second excitation: beta -> beta for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; + if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; - + kk = occs_dn[k]; for (l = j + 1; l < nvir_dn; ++l) { ll = virs_dn[l]; // beta -> beta excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); + // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "bbbb: " << *det_up << std::endl; // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + if (kk >= nbasis) kk -= nbasis; + if (ll >= nbasis) ll -= nbasis; + std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + std::cout << "ndet_up: " << *det_up << std::endl; + std::cout << "10_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])) << std::endl; counter += 1; append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); append(indices, jdet); + ll = virs_dn[l]; + kk = occs_dn[k]; } excite_det(ll, kk, det_up); } @@ -891,13 +988,22 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } // add diagonal element to matrix if (idet < ncol) { + counter += 1; append(data, val2); append(indices, idet); - } - std::cout << "Insinde nonsinglet add_row indices.size(): " << indices.size() << std::endl; - std::cout << "Counter: " << counter << std::endl; + }; // add pointer to next row's indices append(indptr, indices.size()); + + + std::cout << "Insinde nonsinglet add_row indices.size(): " << indices.size() << std::endl; + std::cout << "Counter: " << counter << std::endl; + std::cout << "val2: " << val2 << std::endl; + std::cout << "data: :"; + for (auto i : data) { + std::cout << i << " "; + } + std::cout << std::endl; } From 8b502de1f24a7c4e902bd576153cac75cb68fb8a Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 16 Dec 2024 16:04:45 -0500 Subject: [PATCH 158/197] Remove repeating generation of det using alpha beta --> beta alpha excitation which will be same as alpha beta --> alpha beta; remove unused variables rdet_dn, det_dn --- pyci/src/sparseop.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index b2d5036..159be4a 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -566,9 +566,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long n3 = n1 * n2; double val1, val2 = 0.0; const ulong *rdet_up = wfn.det_ptr(idet); - const ulong *rdet_dn = rdet_up + nbasis; - std::cout << "rdet_up: " << *rdet_up << std::endl; - ulong *det_dn = det_up + nbasis; std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); fill_occs(wfn.nword, rdet_up, occs); @@ -811,29 +808,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; koffset = ioffset + n2 * kk; - // second excitaiton: beta -> alpha - for (l = 0; l < nvir_up; ++l) { - ll = virs_up[l]; - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "ndet_up: " << *det_up << std::endl; - if (kk < nbasis) kk -= nbasis; - if (ll < nbasis) ll -= nbasis; - // std::cout << "6_val: " << (sign_up * - // phase_single_det(wfn.nword, kk, ll, rdet_up) * - // (-ham.two_mo[koffset + n1 * ll + jj])) << std::endl; - // counter += 1; - // append(data, sign_up * - // phase_single_det(wfn.nword, kk, ll, rdet_up) * - // (-ham.two_mo[koffset + n1 * ll + jj])); - // append(indices, jdet); - kk = occs_dn[k]; - ll = virs_up[l]; - } - excite_det(ll, kk, det_up); - } // sedond excitation: beta -> beta for (l = j+1; l < nvir_dn; ++l) { ll = virs_dn[l]; From 1d933cd1276369ab90ba997f8b1f15997407fe83 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 17 Dec 2024 12:40:29 -0500 Subject: [PATCH 159/197] Fix compute_derivative to avoid invalid pointer error --- pyci/src/ap1rogen.cpp | 240 ++++++++++++++++++++++++++++-------------- 1 file changed, 162 insertions(+), 78 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index c080f9f..240dea9 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -279,8 +279,9 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) - ovlp.resize(wfn_.ndet); - d_ovlp.resize(wfn_.ndet * nparam); + ovlp.resize(nconn); + d_ovlp.resize(nconn * nparam); + det_exc_param_indx.resize(nconn); std::cout << "Size of d_ovlp: " << d_ovlp.size() << std::endl; std::size_t nword = (ulong)wfn_.nword; @@ -388,7 +389,10 @@ bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector(std::sqrt(excitation_inds.size())); if (n == 0) {permanent = 1.0; return true;} - if (n == 1) {permanent = x[excitation_inds[0]]; return true;} + if (n == 1) { + permanent = x[excitation_inds[0]]; + std::cout << "I'm here, perm: " << permanent << std::endl; + return true;} permanent = 0.0; std::size_t subset_count = 1UL << n; // 2^n subsets // std::cout << "\npermanent: " << permanent << std::endl; @@ -433,10 +437,58 @@ bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector excitation_inds, + const double* x, std::size_t iparam) { + std::cout << "\nComputing derivative" << std::endl; + + double reduced_permanent = 0.0; + std::cout << "excitation_inds: "; + for (const auto& eid : excitation_inds) { + std::cout << eid << " "; + } + std::cout << std::endl; + std::cout << "iparam: " << iparam << std::endl; + // Check if excitation_inds is empty, first element is -1 + if (excitation_inds[0] == -1) {return 0.0;} + + + // check if iparam is within excitation_inds + auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); + + // If iparam is not in excitation_inds, return 0 + if (it == excitation_inds.end()) {return 0.0;} + + if (excitation_inds.size() == 1 && excitation_inds[0] == iparam) { + reduced_permanent = 1.0; + return reduced_permanent; + } + // Modify x such that it excludes the parameter at index iparam + std::vector modified_x(x, x + nparam); + modified_x[iparam] = 1.0; + + + std::cout << "Modified x: "; + for (const auto& rid : modified_x) { + std::cout << rid << " "; + } + std::cout << std::endl; + permanent_calculation(excitation_inds, modified_x.data(), reduced_permanent); + + if (std::isnan(reduced_permanent) || std::isinf(reduced_permanent)) { + std::cerr << "Error: reduced_permanent is invalid (NaN or Inf)" << std::endl; + return 0.0; + } + std::cout << "\nreduced_permanent: " << reduced_permanent << std::endl; + return reduced_permanent; +} + + + void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { std::cout << "\nInside overlap" << std::endl; - p_permanent.resize(ndet); - s_permanent.resize(ndet); + std::cout << "ndet: " << ndet << std::endl; + p_permanent.resize(nconn); + s_permanent.resize(nconn); std::cout << "Input params: "; for (std::size_t i = 0; i < nparam; ++i) { std::cout << x[i] << " "; @@ -457,11 +509,6 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; double pair_permanent = 1.0; double single_permanent = 1.0; - // std::cout << "Pair indices: "; - // for (const auto& pid : exc_info.pair_inds) { - // std::cout << pid << " "; - // } - // std::cout << std::endl; if (exc_info.pair_inds[0] != -1) { if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { @@ -502,78 +549,133 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d y[idet] = 0.0; s_permanent[idet] = 0.0; p_permanent[idet] = 0.0; - } } } -bool AP1roGeneralizedSenoObjective::compute_derivative(const std::vector& excitation_inds, - const double* x, - std::size_t iparam, double& reduced_permanent) { - - // double derivative = 0.0; - - // std::vector modified_x(x, x + nparam); - // modified_x[excitation_inds[excitation_idx]] = 1.0; - // derivative = permanent_calculation(excitation_inds, modified_x.data()); - - // return derivative; - - // check if iparam is within excitation_inds - auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); - if (it == excitation_inds.end()) reduced_permanent = 0.0; - if (excitation_inds[0] == -1) reduced_permanent = 1.0; - - // Create a reduced excitation_inds excluding iparam - std::vector reduced_inds = excitation_inds; - reduced_inds.erase(it); - - if (permanent_calculation(reduced_inds, x, reduced_permanent)) { - return reduced_permanent; - } - - return false; -} - - - - - // void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - std::cout << "\nComputing d_overlap" << std::endl; - // std::cout << "Size of d_ovlp: " << y.size() << std::endl; - // Loop over each determinant - for (std::size_t idet = 0; idet != ndet; ++idet) - { + std::cout << "\n------>Computing d_overlap" << std::endl; + // std::cout << "Size of s_permanent: " << s_permanent.size() << std::endl; + // std::cout << "Size of p_permanent: " << p_permanent.size() << std::endl; + // std::cout << "ndet: " << ndet << std::endl; + for (std::size_t idet = 0; idet != ndet; ++idet) { // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { - - std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + const DetExcParamIndx exc_info = det_exc_param_indx[idet]; + double pair_permanent = 1.0; + double single_permanent = 1.0; + if (idet < s_permanent.size() && idet < p_permanent.size()) { + std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; + pair_permanent = p_permanent[idet]; + single_permanent = s_permanent[idet]; + } + else { + std::cout << "\nidet: " << idet << " not found in storage" << std::endl; + if (exc_info.pair_inds[0] != -1) { + if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { + std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; + // pair_permanent = 0.0; // Default to 0 or another appropriate fallback + } + } - const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; - double pair_permanent = p_permanent[idet]; - double single_permanent = s_permanent[idet]; - std::cout << "pair_permanent: " << pair_permanent << std::endl; + if (exc_info.single_inds[0] != -1) { + if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { + std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; + // single_permanent = 0.0; // Default value on error + } + } + + } + + + // std::vector pair_inds = exc_info.pair_inds; + // std::vector single_inds = exc_info.single_inds; + + std::cout << "\npair_permanent: " << pair_permanent << std::endl; std::cout << "single_permanent: " << single_permanent << std::endl; for (std::size_t iparam = 0; iparam < nparam; ++iparam) { std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; - std::cout << "nparam: " << nparam << std::endl; + // std::cout << "nparam: " << nparam << std::endl; + // std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; + // std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; + // std::cout << "size of y array: " << &y.size() << std::endl; double dpair = 0.0; double dsingle = 0.0; - std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; - std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; + std::cout << "exc_info.single_inds: "; + for (const auto& sid : exc_info.single_inds) { + std::cout << sid << " "; + } + std::cout << std::endl; + std::cout << "exc_info.pair_inds: "; + for (const auto& pid : exc_info.pair_inds) { + std::cout << pid << " "; + } + std::cout << std::endl; + if (exc_info.single_inds[0] != -1) { + dsingle = compute_derivative(exc_info.single_inds, x, iparam); + // std::cout << "dsingle: " << dsingle << std::endl; + } + std::cout << "dsingle: " << dsingle << std::endl; + + if (exc_info.pair_inds[0] != -1) { + dpair = compute_derivative(exc_info.pair_inds, x, iparam); + // std::cout << "dpair: " << dpair << std::endl; + } + std::cout << "dpair: " << dpair << std::endl; + + + // std::cout << "dpair: " << dpair << std::endl; + // std::cout << "dsingle: " << dsingle << "\n" ; + std::cout << "deriv index:" << idet * nparam + iparam << std::endl; + std::cout << "final deriv: " << dpair * single_permanent + dsingle * pair_permanent << " wrt iparam: " << iparam << std::endl; + + y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; + } + } + else { + std::cout << "Determinant " << idet << " not found in det_map" << std::endl; + // Set all derivatives to zero if determinant is not found + for (std::size_t iparam = 0; iparam < nparam; ++iparam) { + y[ndet * iparam + idet] = 0.0; + } + } + } +} + + +} // namespace pyci + + + // double derivative = 0.0; + // std::vector modified_x(x, x + nparam); + // modified_x[excitation_inds[excitation_idx]] = 1.0; + // derivative = permanent_calculation(excitation_inds, modified_x.data()); + // return derivative; + + // for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { // std::cout << exc_info.pair_inds[i] << " "; // std::cout << exc_info.single_inds[i] << " "; // } // std::cout << "\nSize of x: " << &x.size() << std::endl; - compute_derivative(exc_info.pair_inds, x, iparam, dpair); - compute_derivative(exc_info.single_inds, x, iparam, dsingle); + + // if (exc_info.pair_inds[0] != -1) { + // if (!compute_derivative(exc_info.pair_inds, x, iparam, dpair)) { + // std::cerr << "Error calculating derivative pair_permanent for idet" << idet << std::endl; + // // pair_permanent = 0.0; // Default to 0 or another appropriate fallback + // } + // } + // if (exc_info.pair_inds[0] != -1) { + // if (!compute_derivative(exc_info.single_inds, x, iparam, dsingle)) { + // std::cerr << "Error calculating derivative singles_permanent for idet" << idet << std::endl; + // // pair_permanent = 0.0; // Default to 0 or another appropriate fallback + // } + // } // std::size_t idx = 0; // if (exc_info.pair_inds[idx] != -1) { @@ -592,25 +694,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // d_single = compute_derivative(exc_info.single_inds, x, iparam); // std::cout << "calling done\n"; // } - std::cout << "\ndsingle: " << dsingle << "\n" ; - std::cout << "\nderiv index:" << idet * nparam + iparam << std::endl; - y[idet * nparam + iparam] = dpair * single_permanent + pair_permanent * dsingle; - } -} - else { - std::cout << "Determinant " << idet << " not found in det_map" << std::endl; - // Set all derivatives to zero if determinant is not found - for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - y[idet * nparam + iparam] = 0.0; - } - } - } -} - - -} // namespace pyci - - + // std::vector> occ_pairs; // for (std::size_t hole in holes) { From cf04dd6054c4b6a650f8de5d634883f0ea4f86ef Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 17 Dec 2024 12:43:11 -0500 Subject: [PATCH 160/197] update function declarations for the compute_derivative and update the order of declarations for the rest of the functions for AP1roGSDGeneralized_sen-o --- pyci/include/pyci.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 228830b..e01b1de 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -942,15 +942,13 @@ class AP1roGeneralizedSenoObjective : public Objective { // Permanent calculation: Ryser's Algorithm bool permanent_calculation(const std::vector&, const double*, double&); + // Helper function for d_overlap + double compute_derivative(const std::vector , const double*, std::size_t); + // Overlap function - // virtual void overlap(const NonSingletCI &, const double *x, double *y); virtual void overlap(const std::size_t, const double *x, double *y); - // Helper function for d_overlap - bool compute_derivative(const std::vector& excitation_indices, const double*, std::size_t, double& ); - // Overlap gradient function - // virtual void d_overlap(const NonSingletCI &, const size_t, const double *x, double *y); virtual void d_overlap(const size_t, const double *x, double *y); }; From 214b3ac27ba698bd8674d0fa24cd055cae2c0979 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 17 Dec 2024 14:14:09 -0500 Subject: [PATCH 161/197] Restate the nparams --- pyci/src/ap1rogen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 240dea9..f961aa3 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -274,8 +274,8 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) nparam = nocc_up * (nbasis - nocc_up); //paired-doubles std::cout << "nparam (doubles): " << nparam << std::endl; - // nparam += wfn_.nocc * (2* nbasis - wfn_.nocc); // beta singles - // std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; + nparam += wfn_.nocc * (wfn_.nbasis - wfn_.nocc); // beta singles + std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; From 9bbb3c93bd050b929a8b23eb541cbe09fb2f910c Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 18 Dec 2024 21:09:40 -0500 Subject: [PATCH 162/197] correct koffset in a loop in add_row, comment all elements =0 --- pyci/src/sparseop.cpp | 348 +++++++++++++++++++++--------------------- 1 file changed, 171 insertions(+), 177 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 159be4a..0065c58 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -609,15 +609,12 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-up occupied indices for (i = 0; i < nocc_up; ++i) { ii = occs_up[i]; - if (ii >= nbasis) ii -= nbasis; ioffset = n3 * ii; - ii = occs_up[i]; // compute part of diagonal matrix element val2 += ham.one_mo[(n1 + 1) * ii]; for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; - if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; @@ -644,7 +641,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; - if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } @@ -657,9 +653,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(indices, jdet); jj = virs_up[j]; - std::cout << "ii, jj: " << ii << ", " << jj << std::endl; - std::cout << "s_val: " << val1 << std::endl; - std::cout << "jdet: " << jdet << std::endl; + // std::cout << "ii, jj: " << ii << ", " << jj << std::endl; + // std::cout << "s_val: " << val1 << std::endl; + // std::cout << "jdet: " << jdet << std::endl; } // loop over spin-up occupied indices for (k = i + 1; k < nocc_up; ++k) { @@ -675,11 +671,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // std::cout << "aaaa: " << *det_up << std::endl; // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "1_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])) << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; + // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "1_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + // (ham.two_mo[koffset + n1 * jj + ll] - + // ham.two_mo[koffset + n1 * ll + jj])) << std::endl; + // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; // add the matrix element @@ -691,71 +687,69 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long excite_det(ll, kk, det_up); } // second excitation: alpha -> beta - for (l = 0; l < nvir_dn; ++l) { - ll = virs_dn[l]; - // alpha -> beta excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "2_val: 0.0" << std::endl; - counter += 1; - append(data, 0.0); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } + // for (l = 0; l < nvir_dn; ++l) { + // ll = virs_dn[l]; + // // alpha -> beta excitation elements + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // // std::cout << "2_val: 0.0" << std::endl; + // counter += 1; + // append(data, 0.0); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } } // loop over spin-down occupied indices for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; + if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; // second excitation: beta -> alpha - for (l = j+1; l < nvir_up; ++l) { - ll = virs_up[l]; - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "3_val: 0.0" << std::endl; - counter += 1; - append(data, 0.0); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } + // for (l = j+1; l < nvir_up; ++l) { + // ll = virs_up[l]; + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // // std::cout << "3_val: 0.0" << std::endl; + // counter += 1; + // append(data, 0.0); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; + kk = occs_dn[k]; excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; // std::cout << "aabb ndet_up: " << *det_up << std::endl; // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "\nii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; + // std::cout << "\nii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "ndet_up: " << *det_up << std::endl; + double sign = phase_single_det(wfn.nword, kk, ll, rdet_up); if (jj >= nbasis) jj -= nbasis; if (kk >= nbasis) kk -= nbasis; if (ll >= nbasis) ll -= nbasis; - std::cout << "updated ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "updated ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "4_val: " << (sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[koffset + n1 * jj + ll]) << std::endl; + // std::cout << "4_val: " << (sign_up * + // phase_single_det(wfn.nword, kk, ll, rdet_up) * + // ham.two_mo[koffset + n1 * jj + ll]) << std::endl; counter += 1; - // append(data, sign_up * - // phase_single_det(wfn.nword, kk, ll, rdet_up) * - // ham.two_mo[koffset + n1 * jj + ll]); - append(data, sign_up * - phase_single_det(wfn.nword, kk, ll, rdet_up) * - ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); + append(data, sign_up * sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); append(indices, jdet); ll = virs_dn[l]; kk = occs_dn[k]; @@ -768,66 +762,66 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } // first excitation: alpha -> beta - for (j = 0; j < nvir_dn; ++j) { - jj = virs_dn[j]; - excite_det(ii, jj, det_up); - sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, jj: " << ii << ", " << jj << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "s_val: 0.0" << std::endl; - counter += 1; - // add the matrix element - append(data, 0.0); - append(indices, jdet); - } + // for (j = 0; j < nvir_dn; ++j) { + // jj = virs_dn[j]; + // excite_det(ii, jj, det_up); + // sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ii, jj: " << ii << ", " << jj << std::endl; + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "s_val: 0.0" << std::endl; + // counter += 1; + // // add the matrix element + // append(data, 0.0); + // append(indices, jdet); + // } // second excitation: alpha -> beta - for (k = i + 1; k < nocc_up; ++k) { - kk = occs_up[k]; - koffset = ioffset + n2 * kk; - for (l = j + 1; l < nvir_dn; ++l) { - ll = virs_dn[l]; - // alpha -> beta excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "5_val: 0.0" << std::endl; - counter += 1; - append(data, 0.0); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } - } + // for (k = i + 1; k < nocc_up; ++k) { + // kk = occs_up[k]; + // koffset = ioffset + n2 * kk; + // for (l = j + 1; l < nvir_dn; ++l) { + // ll = virs_dn[l]; + // // alpha -> beta excitation elements + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "5_val: 0.0" << std::endl; + // counter += 1; + // append(data, 0.0); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } + // } // loop over spin-down occupied indices - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - // sedond excitation: beta -> beta - for (l = j+1; l < nvir_dn; ++l) { - ll = virs_dn[l]; - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "7_val: 0.0" << std::endl; - counter += 1; - append(data, 0.0); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } - } - - excite_det(jj, ii, det_up); - } + // for (k = 0; k < nocc_dn; ++k) { + // kk = occs_dn[k]; + // koffset = ioffset + n2 * kk; + // // sedond excitation: beta -> beta + // for (l = j+1; l < nvir_dn; ++l) { + // ll = virs_dn[l]; + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "7_val: 0.0" << std::endl; + // counter += 1; + // append(data, 0.0); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } + // } + + // excite_det(jj, ii, det_up); + // } } // loop over spin-down occupied indices for (i = 0; i < nocc_dn; ++i) { @@ -844,60 +838,60 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } ii = occs_dn[i]; // first excitation: beta -> alpha - for (j = 0; j < nvir_up; ++j) { - jj = virs_up[j]; - excite_det(ii, jj, det_up); - jdet = wfn.index_det(det_up); - // check if the excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, jj: " << ii << ", " << jj << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "s_val: 0.0" << std::endl; - counter += 1; - // add the matrix element - append(data, 0.0); - append(indices, jdet); - } + // for (j = 0; j < nvir_up; ++j) { + // jj = virs_up[j]; + // excite_det(ii, jj, det_up); + // jdet = wfn.index_det(det_up); + // // check if the excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ii, jj: " << ii << ", " << jj << std::endl; + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "s_val: 0.0" << std::endl; + // counter += 1; + // // add the matrix element + // append(data, 0.0); + // append(indices, jdet); + // } - for (k = i + 1; k < nocc_dn; ++k) { - kk = occs_dn[k]; - koffset = ioffset + n2 * kk; - // second excitation: beta -> alpha - for (l = j + 1; l < nvir_up; ++l) { - ll = virs_up[l]; - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "8_val: 0.0" << std::endl; - counter += 1; - append(data, 0.0); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } - // seond excitation: beta -> beta - for (l = 0; l < nvir_dn; ++l) { - ll = virs_dn[l]; - // beta -> beta excitation elements - excite_det(kk, ll, det_up); - jdet = wfn.index_det(det_up); - // check if excited determinant is in wfn - if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "9_val: 0.0" << std::endl; - counter += 1; - append(data, 0.0); - append(indices, jdet); - } - excite_det(ll, kk, det_up); - } - } - excite_det(jj, ii, det_up); - } + // for (k = i + 1; k < nocc_dn; ++k) { + // kk = occs_dn[k]; + // koffset = ioffset + n2 * kk; + // // second excitation: beta -> alpha + // for (l = j + 1; l < nvir_up; ++l) { + // ll = virs_up[l]; + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "8_val: 0.0" << std::endl; + // counter += 1; + // append(data, 0.0); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } + // // seond excitation: beta -> beta + // for (l = 0; l < nvir_dn; ++l) { + // ll = virs_dn[l]; + // // beta -> beta excitation elements + // excite_det(kk, ll, det_up); + // jdet = wfn.index_det(det_up); + // // check if excited determinant is in wfn + // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // // std::cout << "ndet_up: " << *det_up << std::endl; + // // std::cout << "9_val: 0.0" << std::endl; + // counter += 1; + // append(data, 0.0); + // append(indices, jdet); + // } + // excite_det(ll, kk, det_up); + // } + // } + // excite_det(jj, ii, det_up); + // } // first excitation: beta -> beta for (j = 0; j < nvir_dn; ++j) { jj = virs_dn[j]; @@ -906,7 +900,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { if (jj >= nbasis) jj -= nbasis; - std::cout << "ndet_up: " << *det_up << std::endl; + // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; val1 = ham.one_mo[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { @@ -919,10 +913,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long koffset = ioffset + n2 * kk; val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } - + jj = virs_dn[j]; append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); - jj = virs_dn[j]; + } // second excitation: beta -> beta for (k = i + 1; k < nocc_dn; ++k) { @@ -939,17 +933,17 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // std::cout << "bbbb: " << *det_up << std::endl; // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + double sign = phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up); if (kk >= nbasis) kk -= nbasis; if (ll >= nbasis) ll -= nbasis; - std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - std::cout << "ndet_up: " << *det_up << std::endl; - std::cout << "10_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])) << std::endl; + // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; + // std::cout << "ndet_up: " << *det_up << std::endl; + // std::cout << "10_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * + // (ham.two_mo[koffset + n1 * jj + ll] - + // ham.two_mo[koffset + n1 * ll + jj])) << std::endl; counter += 1; - append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + append(data, sign * (ham.two_mo[koffset + n1 * jj + ll] - + ham.two_mo[koffset + n1 * ll + jj])); append(indices, jdet); ll = virs_dn[l]; kk = occs_dn[k]; From d5fa6cbf87e62f3c0a23b6c8f0cbf2ddead9fa8e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:16:51 -0500 Subject: [PATCH 163/197] Remove matrix elements =0, remove print statements --- pyci/src/sparseop.cpp | 225 +----------------------------------------- 1 file changed, 2 insertions(+), 223 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 0065c58..8b92801 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -68,7 +68,6 @@ SparseOp::SparseOp(const SQuantOp &ham, const GenCIWfn &wfn, const long rows, co : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), ecore(ham.ecore), symmetric(symm) { append(indptr, 0); - std::cout << "Inside SparseOp constructor" << std::endl; update(ham, wfn, nrow, ncol, 0); } @@ -77,8 +76,6 @@ SparseOp::SparseOp(const SQuantOp &ham, const NonSingletCI &wfn, const long rows : nrow((rows > -1) ? rows : wfn.ndet), ncol((cols > -1) ? cols : wfn.ndet), size(0), ecore(ham.ecore), symmetric(symm) { append(indptr, 0); - std::cout << "Inside SparseOp NonSingletCI constructor" << std::endl; - std::cout << "nrow: " << nrow << ", ncol: " << ncol << std::endl; update(ham, wfn, nrow, ncol, 0); } @@ -201,45 +198,35 @@ template void SparseOp::py_update(const SQuantOp &ham, const NonSingletCI &wfn); template void SparseOp::update(const SQuantOp &ham, const WfnType &wfn, const long rows, const long cols, const long startrow) { - std::cout << "Inside SparseOp update" << std::endl; - std::cout << "Type of WfnType: " << typeid(WfnType).name() << std::endl; - AlignedVector det(wfn.nword2); AlignedVector occs(wfn.nocc); AlignedVector virs(wfn.nvir); - std::cout << "wfn.nvir: " << wfn.nvir << std::endl; shape = pybind11::make_tuple(pybind11::cast(rows), pybind11::cast(cols)); nrow = rows; ncol = cols; - std::cout << "nrow: " << nrow << std::endl; indptr.reserve(nrow + 1); for (long idet = startrow; idet < rows; ++idet) { add_row(ham, wfn, idet, &det[0], &occs[0], &virs[0]); sort_row(idet); } size = indices.size(); - std::cout << "size: " << size << std::endl; } void SparseOp::update(const SQuantOp &ham, const NonSingletCI &wfn, const long rows, const long cols, const long startrow) { - std::cout << "Inside NonsingletCI SparseOp update" << std::endl; AlignedVector det(wfn.nword); AlignedVector occs(wfn.nocc); AlignedVector virs(wfn.nbasis - wfn.nocc); - std::cout << "wfn.nvir: " << wfn.nvir << std::endl; shape = pybind11::make_tuple(pybind11::cast(rows), pybind11::cast(cols)); nrow = rows; ncol = cols; - std::cout << "nrow: " << nrow << std::endl; indptr.reserve(nrow + 1); for (long idet = startrow; idet < rows; ++idet) { add_row(ham, wfn, idet, &det[0], &occs[0], &virs[0]); sort_row(idet); } size = indices.size(); - std::cout << "size: " << size << std::endl; } @@ -266,8 +253,6 @@ void SparseOp::add_row(const SQuantOp &ham, const DOCIWfn &wfn, const long idet, long jdet, jmin = symmetric ? idet : Max(); double val1 = 0.0, val2 = 0.0; wfn.copy_det(idet, det); - std::cout << "Inside add_row DOCIWfn" << std::endl; - std::cout << "rdet: " << *wfn.det_ptr(idet) << std::endl; fill_occs(wfn.nword, det, occs); fill_virs(wfn.nword, wfn.nbasis, det, virs); // loop over occupied indices @@ -286,7 +271,6 @@ void SparseOp::add_row(const SQuantOp &ham, const DOCIWfn &wfn, const long idet, jdet = wfn.index_det(det); // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - std::cout << "det: " << *det << std::endl; // add single/"pair"-excited matrix element append(data, ham.v[k * wfn.nbasis + l]); append(indices, jdet); @@ -299,10 +283,7 @@ void SparseOp::add_row(const SQuantOp &ham, const DOCIWfn &wfn, const long idet, append(data, val1 + val2 * 2); append(indices, idet); } - std::cout << "data: " ; - for (auto i : data) { - std::cout << i << " "; - } + // add pointer to next row's indices append(indptr, indices.size()); } @@ -554,10 +535,6 @@ void SparseOp::add_row(const SQuantOp &ham, const GenCIWfn &wfn, const long idet void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long idet, ulong *det_up, long *occs, long *virs) { - std::cout << "---Inside add_row NonSingletCI--" << std::endl; - std::cout << "idet: " << idet << std::endl; - std::cout << "wfn.nbasis: " << wfn.nbasis << std::endl; - std::cout << "wfn.nword: " << wfn.nword << std::endl; long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); long ioffset, koffset, sign_up; long nbasis = wfn.nbasis / 2; @@ -576,18 +553,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long nvir_up = nbasis - nocc_up; long nvir_dn = nbasis - nocc_dn; long nvir = nvir_up + nvir_dn; - std::cout << "nocc_up: " << nocc_up << ", nocc_dn: " << nocc_dn << std::endl; - std::cout << "nvir_up: " << nvir_up << ", nvir_dn: " << nvir_dn << std::endl; - std::cout << "Occs: " ; - for (i = 0; i < wfn.nocc; ++i) { - std::cout << occs[i] << " "; - } - std::cout << std::endl; - std::cout << "Virs: " ; - for (i = 0; i < (nvir); ++i) { - std::cout << virs[i] << " "; - } - std::cout << std::endl; long *virs_up = virs; long *virs_dn = nullptr; for (long i = 0; i < nvir; ++i) { @@ -652,10 +617,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(data, sign_up * val1); append(indices, jdet); jj = virs_up[j]; - - // std::cout << "ii, jj: " << ii << ", " << jj << std::endl; - // std::cout << "s_val: " << val1 << std::endl; - // std::cout << "jdet: " << jdet << std::endl; } // loop over spin-up occupied indices for (k = i + 1; k < nocc_up; ++k) { @@ -667,17 +628,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // alpha -> alpha excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "aaaa: " << *det_up << std::endl; // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "1_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - // (ham.two_mo[koffset + n1 * jj + ll] - - // ham.two_mo[koffset + n1 * ll + jj])) << std::endl; - // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; - // add the matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - @@ -686,23 +639,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(ll, kk, det_up); } - // second excitation: alpha -> beta - // for (l = 0; l < nvir_dn; ++l) { - // ll = virs_dn[l]; - // // alpha -> beta excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // // std::cout << "2_val: 0.0" << std::endl; - // counter += 1; - // append(data, 0.0); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } } // loop over spin-down occupied indices @@ -710,30 +646,12 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long kk = occs_dn[k]; if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; - // second excitation: beta -> alpha - // for (l = j+1; l < nvir_up; ++l) { - // ll = virs_up[l]; - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // // std::cout << "3_val: 0.0" << std::endl; - // counter += 1; - // append(data, 0.0); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; kk = occs_dn[k]; excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "aabb ndet_up: " << *det_up << std::endl; // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { // std::cout << "\nii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; @@ -742,12 +660,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long if (jj >= nbasis) jj -= nbasis; if (kk >= nbasis) kk -= nbasis; if (ll >= nbasis) ll -= nbasis; - - // std::cout << "updated ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - - // std::cout << "4_val: " << (sign_up * - // phase_single_det(wfn.nword, kk, ll, rdet_up) * - // ham.two_mo[koffset + n1 * jj + ll]) << std::endl; counter += 1; append(data, sign_up * sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); append(indices, jdet); @@ -760,68 +672,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } excite_det(jj, ii, det_up); } - - // first excitation: alpha -> beta - // for (j = 0; j < nvir_dn; ++j) { - // jj = virs_dn[j]; - // excite_det(ii, jj, det_up); - // sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ii, jj: " << ii << ", " << jj << std::endl; - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "s_val: 0.0" << std::endl; - // counter += 1; - // // add the matrix element - // append(data, 0.0); - // append(indices, jdet); - // } - // second excitation: alpha -> beta - // for (k = i + 1; k < nocc_up; ++k) { - // kk = occs_up[k]; - // koffset = ioffset + n2 * kk; - // for (l = j + 1; l < nvir_dn; ++l) { - // ll = virs_dn[l]; - // // alpha -> beta excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "5_val: 0.0" << std::endl; - // counter += 1; - // append(data, 0.0); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // } - // loop over spin-down occupied indices - // for (k = 0; k < nocc_dn; ++k) { - // kk = occs_dn[k]; - // koffset = ioffset + n2 * kk; - // // sedond excitation: beta -> beta - // for (l = j+1; l < nvir_dn; ++l) { - // ll = virs_dn[l]; - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "7_val: 0.0" << std::endl; - // counter += 1; - // append(data, 0.0); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // } - - // excite_det(jj, ii, det_up); - // } } // loop over spin-down occupied indices for (i = 0; i < nocc_dn; ++i) { @@ -837,61 +687,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; } ii = occs_dn[i]; - // first excitation: beta -> alpha - // for (j = 0; j < nvir_up; ++j) { - // jj = virs_up[j]; - // excite_det(ii, jj, det_up); - // jdet = wfn.index_det(det_up); - // // check if the excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ii, jj: " << ii << ", " << jj << std::endl; - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "s_val: 0.0" << std::endl; - // counter += 1; - // // add the matrix element - // append(data, 0.0); - // append(indices, jdet); - // } - - // for (k = i + 1; k < nocc_dn; ++k) { - // kk = occs_dn[k]; - // koffset = ioffset + n2 * kk; - // // second excitation: beta -> alpha - // for (l = j + 1; l < nvir_up; ++l) { - // ll = virs_up[l]; - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "8_val: 0.0" << std::endl; - // counter += 1; - // append(data, 0.0); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // // seond excitation: beta -> beta - // for (l = 0; l < nvir_dn; ++l) { - // ll = virs_dn[l]; - // // beta -> beta excitation elements - // excite_det(kk, ll, det_up); - // jdet = wfn.index_det(det_up); - // // check if excited determinant is in wfn - // if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // // std::cout << "ndet_up: " << *det_up << std::endl; - // // std::cout << "9_val: 0.0" << std::endl; - // counter += 1; - // append(data, 0.0); - // append(indices, jdet); - // } - // excite_det(ll, kk, det_up); - // } - // } - // excite_det(jj, ii, det_up); - // } + // first excitation: beta -> beta for (j = 0; j < nvir_dn; ++j) { jj = virs_dn[j]; @@ -929,18 +725,11 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // beta -> beta excitation elements excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); - // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "bbbb: " << *det_up << std::endl; // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { double sign = phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up); if (kk >= nbasis) kk -= nbasis; if (ll >= nbasis) ll -= nbasis; - // std::cout << "ii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "ndet_up: " << *det_up << std::endl; - // std::cout << "10_val: " << (phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - // (ham.two_mo[koffset + n1 * jj + ll] - - // ham.two_mo[koffset + n1 * ll + jj])) << std::endl; counter += 1; append(data, sign * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -962,16 +751,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long }; // add pointer to next row's indices append(indptr, indices.size()); - - - std::cout << "Insinde nonsinglet add_row indices.size(): " << indices.size() << std::endl; - std::cout << "Counter: " << counter << std::endl; - std::cout << "val2: " << val2 << std::endl; - std::cout << "data: :"; - for (auto i : data) { - std::cout << i << " "; - } - std::cout << std::endl; } From 6ce631e1e2e763d96781015cd56b90268b7d36e7 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:23:57 -0500 Subject: [PATCH 164/197] Clean up the unnecessary code, comment print lines --- pyci/src/ap1rogen.cpp | 411 ++++++++++++++---------------------------- 1 file changed, 133 insertions(+), 278 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index f961aa3..f35ff80 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -88,7 +88,7 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti std::vector> partitions; for (int p = 0; p <= std::min(e / 2 , max_opairs); ++p) { int s = e - 2 * p; - // std::cout << "p, s: " << p << " " << s << std::endl; + // //std::cout << "p, s: " << p << " " << s << std::endl; if (max_opairs > 0 && nvir_pairs && p) { if (e % 2 !=0) { // if e is odd partitions.emplace_back(p, s); @@ -109,11 +109,11 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, const std::vector& particles, int excitation_order, std::vector& pair_inds, std::vector& single_inds, long nbasis, const NonSingletCI &wfn_) { - std::cout << "Inside generate_excitations" << std::endl; + //std::cout << "Inside generate_excitations" << std::endl; AlignedVector> occ_pairs, vir_pairs; AlignedVector occs_up, occs_dn, virs_up, virs_dn, temp_occs; for (int i : holes) { - // std::cout << "i: " << i << ", nbasis: " << nbasis << std::endl; + // //std::cout << "i: " << i << ", nbasis: " << nbasis << std::endl; (i < nbasis ? occs_up : occs_dn).push_back(i); } for (int a : particles) { @@ -121,7 +121,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector occ_dn_set(occs_dn.begin(), occs_dn.end()); std::unordered_set virs_set(particles.begin(), particles.end()); @@ -141,17 +141,18 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector>::size_type max_pairs = occ_pairs.size(); bool nvir_pairs = false; if (max_pairs == vir_pairs.size()) { @@ -159,21 +160,21 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector> hole_pairs, hole_singles; std::vector> part_pairs, part_singles; @@ -183,20 +184,20 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector 0) { generate_combinations(holes, 2, hole_pairs, nbasis); generate_combinations(particles, 2, part_pairs, nbasis); - std::cout << "Generated hole_pairs" << std::endl; + // std::cout << "Generated hole_pairs" << std::endl; for (const auto& hpair_comb : hole_pairs) { for (const auto& ppair_comb : part_pairs){ - std::cout << "Handling pair excitations" << std::endl; + // std::cout << "Handling pair excitations" << std::endl; // if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { if (!hpair_comb.empty() || !ppair_comb.empty()) { long pindx = wfn_.calc_pindex(hpair_comb[0], ppair_comb[0]); - std::cout << "Pair index: " << pindx << std::endl; - std::cout << "hpair_comb: " << hpair_comb[0] << " " << hpair_comb[1] << std::endl; - std::cout << "ppair_comb: " << ppair_comb[0] << " " << ppair_comb[1] << std::endl; + // std::cout << "Pair index: " << pindx << std::endl; + // std::cout << "hpair_comb: " << hpair_comb[0] << " " << hpair_comb[1] << std::endl; + // std::cout << "ppair_comb: " << ppair_comb[0] << " " << ppair_comb[1] << std::endl; if (pair_inds[0] == -1) { pair_inds.clear(); } @@ -210,7 +211,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector 0) { - std::cout << "Handling single excitations" << std::endl; + // std::cout << "Handling single excitations" << std::endl; // Filter holes and particles to exclude used ones std::vector remaining_holes, remaining_particles; @@ -239,23 +240,23 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector::quiet_NaN(); - std::cout << "Inside init_overlap" << std::endl; + // std::cout << "Inside init_overlap" << std::endl; // Initialize your class-specific variables here // init_Overlap objective for the AP1roGSDspin_sen-o - std::cout << "wfn_.nocc_up: " << wfn_.nocc_up << "wfn_.nvir_up" << wfn_.nvir_up << std::endl; - std::cout << "wfn_.nocc: " << wfn_.nocc << "wfn_.nvir" << wfn_.nvir << std::endl; + // std::cout << "wfn_.nocc_up: " << wfn_.nocc_up << "wfn_.nvir_up" << wfn_.nvir_up << std::endl; + // std::cout << "wfn_.nocc: " << wfn_.nocc << "wfn_.nvir" << wfn_.nvir << std::endl; long nocc_up = wfn_.nocc / 2; long nbasis = wfn_.nbasis / 2; // long nvir_up = nbasis - nocc_up; nparam = nocc_up * (nbasis - nocc_up); //paired-doubles - std::cout << "nparam (doubles): " << nparam << std::endl; + // std::cout << "nparam (doubles): " << nparam << std::endl; nparam += wfn_.nocc * (wfn_.nbasis - wfn_.nocc); // beta singles - std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; + // std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; ovlp.resize(nconn); d_ovlp.resize(nconn * nparam); det_exc_param_indx.resize(nconn); - std::cout << "Size of d_ovlp: " << d_ovlp.size() << std::endl; + // std::cout << "Size of d_ovlp: " << d_ovlp.size() << std::endl; std::size_t nword = (ulong)wfn_.nword; long nb = wfn_.nbasis; @@ -294,11 +295,11 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) wfn_.fill_hartreefock_det(nb, nocc, &rdet[0]); const ulong *det = wfn_.det_ptr(idet); ensure_struct_size(det_exc_param_indx, idet+1); - std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - std::cout << "\n---------> Det: " ; + // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // std::cout << "\n---------> Det: " ; bool are_same = true; for (std::size_t k = 0; k < nword; ++k) { - std::cout << det[k] << " "; + // std::cout << det[k] << " "; if (rdet[k] != det[k]) { are_same = false; break; @@ -317,9 +318,9 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) word = rdet[iword] ^ det[iword]; //str for excitation hword = word & rdet[iword]; //str for hole pword = word & det[iword]; //str for particle - std::cout << "\nword: " << word << std::endl; - std::cout << "hword: " << hword << std::endl; - std::cout << "pword: " << pword << std::endl; + // std::cout << "\nword: " << word << std::endl; + // std::cout << "hword: " << hword << std::endl; + // std::cout << "pword: " << pword << std::endl; while(hword){ h = Ctz(hword); p = Ctz(pword); @@ -341,44 +342,38 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) } } //nexc_list[idet] = nexc; - std::cout << "nexc: " << nexc << std::endl; - std::cout << "Ensured struct size" << std::endl; + // std::cout << "nexc: " << nexc << std::endl; + // std::cout << "Ensured struct size" << std::endl; DetExcParamIndx exc_info; exc_info.det.resize(nword); exc_info.pair_inds.resize(1); exc_info.single_inds.resize(1); exc_info.pair_inds[0] = -1; exc_info.single_inds[0] = -1; - std::cout << "Assigned first elem as -1 to both pair_inds and single_inds" << std::endl; + // std::cout << "Assigned first elem as -1 to both pair_inds and single_inds" << std::endl; std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); // std::cout << "\nCopied det" << std::endl; if (!are_same) generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); - std::cout << "Generated excitations" << std::endl; - std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // std::cout << "Generated excitations" << std::endl; + // std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; std::sort(exc_info.pair_inds.begin(), exc_info.pair_inds.end()); std::sort(exc_info.single_inds.begin(), exc_info.single_inds.end()); - if (idet == 41) { - std::cout << "Det: "; - for (std::size_t k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - std::cout << "exc_info.pair_inds: "; - for (const auto& pid : exc_info.pair_inds) { - std::cout << pid << " "; - } - std::cout << std::endl; - std::cout << "exc_info.single_inds: "; - for (const auto& sid : exc_info.single_inds) { - std::cout << sid << " "; - } - std::cout << std::endl; - } - // if (exc_info.pair_inds.empty()) { - // exc_info.pair_inds[0] = -1; - // } - // if (exc_info.single_inds.empty()) { - // exc_info.single_inds[0] = -1; + // if (idet == 41) { + // std::cout << "Det: "; + // for (std::size_t k = 0; k < nword; ++k) { + // std::cout << det[k] << " "; + // } + // std::cout << std::endl; + // std::cout << "exc_info.pair_inds: "; + // for (const auto& pid : exc_info.pair_inds) { + // std::cout << pid << " "; + // } + // std::cout << std::endl; + // std::cout << "exc_info.single_inds: "; + // for (const auto& sid : exc_info.single_inds) { + // std::cout << sid << " "; + // } + // std::cout << std::endl; // } det_exc_param_indx[idet] = exc_info; } @@ -391,7 +386,7 @@ bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector excitation_inds, const double* x, std::size_t iparam) { - std::cout << "\nComputing derivative" << std::endl; + // std::cout << "\nComputing derivative" << std::endl; double reduced_permanent = 0.0; - std::cout << "excitation_inds: "; - for (const auto& eid : excitation_inds) { - std::cout << eid << " "; - } - std::cout << std::endl; - std::cout << "iparam: " << iparam << std::endl; + // std::cout << "excitation_inds: "; + // for (const auto& eid : excitation_inds) { + // std::cout << eid << " "; + // } + // std::cout << std::endl; + // std::cout << "iparam: " << iparam << std::endl; // Check if excitation_inds is empty, first element is -1 if (excitation_inds[0] == -1) {return 0.0;} @@ -467,43 +462,43 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector modified_x[iparam] = 1.0; - std::cout << "Modified x: "; - for (const auto& rid : modified_x) { - std::cout << rid << " "; - } - std::cout << std::endl; + // std::cout << "Modified x: "; + // for (const auto& rid : modified_x) { + // std::cout << rid << " "; + // } + // std::cout << std::endl; permanent_calculation(excitation_inds, modified_x.data(), reduced_permanent); if (std::isnan(reduced_permanent) || std::isinf(reduced_permanent)) { std::cerr << "Error: reduced_permanent is invalid (NaN or Inf)" << std::endl; return 0.0; } - std::cout << "\nreduced_permanent: " << reduced_permanent << std::endl; + // std::cout << "\nreduced_permanent: " << reduced_permanent << std::endl; return reduced_permanent; } void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { - std::cout << "\nInside overlap" << std::endl; - std::cout << "ndet: " << ndet << std::endl; + // std::cout << "\nInside overlap" << std::endl; + // std::cout << "ndet: " << ndet << std::endl; p_permanent.resize(nconn); s_permanent.resize(nconn); - std::cout << "Input params: "; - for (std::size_t i = 0; i < nparam; ++i) { - std::cout << x[i] << " "; - } - std::cout << std::endl; - std::cout << "Ovlp: " ; - for (std::size_t i = 0; i < ndet; ++i) { - std::cout << y[i] << " "; - } - std::cout << std::endl; + // std::cout << "Input params: "; + // for (std::size_t i = 0; i < nparam; ++i) { + // std::cout << x[i] << " "; + // } + // std::cout << std::endl; + // std::cout << "Ovlp: " ; + // for (std::size_t i = 0; i < ndet; ++i) { + // std::cout << y[i] << " "; + // } + // std::cout << std::endl; for (std::size_t idet = 0; idet != ndet; ++idet) { // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; if (idet < det_exc_param_indx.size()) { - std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; + // std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; // Access the excitation parameter indices const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; @@ -527,23 +522,23 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d p_permanent[idet] = pair_permanent; s_permanent[idet] = single_permanent; - std::cout << "exc_info.pair_inds, x[idx]: "; - for (const auto& pid : exc_info.pair_inds) { - std::cout << pid << ", " << x[pid] << " "; - } - std::cout << "\nexc_info.single_inds: "; - for (const auto& sid : exc_info.single_inds) { - std::cout << sid << " "; - } - std::cout << "\npair_permanent: " << pair_permanent << std::endl; - std::cout << "single_permanent: " << single_permanent << std::endl; + // std::cout << "exc_info.pair_inds, x[idx]: "; + // for (const auto& pid : exc_info.pair_inds) { + // std::cout << pid << ", " << x[pid] << " "; + // } + // std::cout << "\nexc_info.single_inds: "; + // for (const auto& sid : exc_info.single_inds) { + // std::cout << sid << " "; + // } + // std::cout << "\npair_permanent: " << pair_permanent << std::endl; + // std::cout << "single_permanent: " << single_permanent << std::endl; if (y != nullptr && idet < ndet) { y[idet] = pair_permanent * single_permanent; } else { std::cerr << "y is nullptr or idet is out of bounds" << std::endl; } - std::cout << "y[" << idet << "]: " << y[idet] << std::endl; + // std::cout << "y[" << idet << "]: " << y[idet] << std::endl; } else { std::cout << "idet" << idet << " not found in storage" << std::endl; y[idet] = 0.0; @@ -556,7 +551,7 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d // void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - std::cout << "\n------>Computing d_overlap" << std::endl; + // std::cout << "\n------>Computing d_overlap" << std::endl; // std::cout << "Size of s_permanent: " << s_permanent.size() << std::endl; // std::cout << "Size of p_permanent: " << p_permanent.size() << std::endl; // std::cout << "ndet: " << ndet << std::endl; @@ -568,12 +563,12 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x double pair_permanent = 1.0; double single_permanent = 1.0; if (idet < s_permanent.size() && idet < p_permanent.size()) { - std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; + // std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; pair_permanent = p_permanent[idet]; single_permanent = s_permanent[idet]; } else { - std::cout << "\nidet: " << idet << " not found in storage" << std::endl; + // std::cout << "\nidet: " << idet << " not found in storage" << std::endl; if (exc_info.pair_inds[0] != -1) { if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; @@ -589,13 +584,9 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x } } - - - // std::vector pair_inds = exc_info.pair_inds; - // std::vector single_inds = exc_info.single_inds; - - std::cout << "\npair_permanent: " << pair_permanent << std::endl; - std::cout << "single_permanent: " << single_permanent << std::endl; + + // std::cout << "\npair_permanent: " << pair_permanent << std::endl; + // std::cout << "single_permanent: " << single_permanent << std::endl; for (std::size_t iparam = 0; iparam < nparam; ++iparam) { std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; @@ -606,38 +597,39 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x double dpair = 0.0; double dsingle = 0.0; std::cout << "exc_info.single_inds: "; - for (const auto& sid : exc_info.single_inds) { - std::cout << sid << " "; - } - std::cout << std::endl; - std::cout << "exc_info.pair_inds: "; - for (const auto& pid : exc_info.pair_inds) { - std::cout << pid << " "; - } - std::cout << std::endl; + // for (const auto& sid : exc_info.single_inds) { + // std::cout << sid << " "; + // } + // std::cout << std::endl; + // std::cout << "exc_info.pair_inds: "; + // for (const auto& pid : exc_info.pair_inds) { + // std::cout << pid << " "; + // } + // std::cout << std::endl; + if (exc_info.single_inds[0] != -1) { dsingle = compute_derivative(exc_info.single_inds, x, iparam); // std::cout << "dsingle: " << dsingle << std::endl; } - std::cout << "dsingle: " << dsingle << std::endl; + // std::cout << "dsingle: " << dsingle << std::endl; if (exc_info.pair_inds[0] != -1) { dpair = compute_derivative(exc_info.pair_inds, x, iparam); // std::cout << "dpair: " << dpair << std::endl; } - std::cout << "dpair: " << dpair << std::endl; + // std::cout << "dpair: " << dpair << std::endl; // std::cout << "dpair: " << dpair << std::endl; // std::cout << "dsingle: " << dsingle << "\n" ; - std::cout << "deriv index:" << idet * nparam + iparam << std::endl; - std::cout << "final deriv: " << dpair * single_permanent + dsingle * pair_permanent << " wrt iparam: " << iparam << std::endl; + // std::cout << "deriv index:" << idet * nparam + iparam << std::endl; + // std::cout << "final deriv: " << dpair * single_permanent + dsingle * pair_permanent << " wrt iparam: " << iparam << std::endl; y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; } } else { - std::cout << "Determinant " << idet << " not found in det_map" << std::endl; + // std::cout << "Determinant " << idet << " not found in det_map" << std::endl; // Set all derivatives to zero if determinant is not found for (std::size_t iparam = 0; iparam < nparam; ++iparam) { y[ndet * iparam + idet] = 0.0; @@ -648,140 +640,3 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x } // namespace pyci - - - // double derivative = 0.0; - // std::vector modified_x(x, x + nparam); - // modified_x[excitation_inds[excitation_idx]] = 1.0; - // derivative = permanent_calculation(excitation_inds, modified_x.data()); - // return derivative; - - - // for (std::size_t i = 0; i < exc_info.pair_inds.size(); ++i) { - // std::cout << exc_info.pair_inds[i] << " "; - // std::cout << exc_info.single_inds[i] << " "; - // } - // std::cout << "\nSize of x: " << &x.size() << std::endl; - - // if (exc_info.pair_inds[0] != -1) { - // if (!compute_derivative(exc_info.pair_inds, x, iparam, dpair)) { - // std::cerr << "Error calculating derivative pair_permanent for idet" << idet << std::endl; - // // pair_permanent = 0.0; // Default to 0 or another appropriate fallback - // } - // } - - // if (exc_info.pair_inds[0] != -1) { - // if (!compute_derivative(exc_info.single_inds, x, iparam, dsingle)) { - // std::cerr << "Error calculating derivative singles_permanent for idet" << idet << std::endl; - // // pair_permanent = 0.0; // Default to 0 or another appropriate fallback - // } - // } - - // std::size_t idx = 0; - // if (exc_info.pair_inds[idx] != -1) { - // std::cout << "exc_info.pair_inds: "; - // for (const auto pid : exc_info.pair_inds) { - // std::cout << pid << " "; - // } - // d_pair = compute_derivative(exc_info.pair_inds, x, iparam); - // } - // if (exc_info.single_inds[idx] != -1) { - // std::cout << "exc_info.single_inds: "; - // for (const auto sid : exc_info.single_inds) { - // std::cout << sid << " "; - // } - // std::cout << "\nCalling compute deriv for single_inds\n"; - // d_single = compute_derivative(exc_info.single_inds, x, iparam); - // std::cout << "calling done\n"; - // } - - -// std::vector> occ_pairs; -// for (std::size_t hole in holes) { -// std::size_t conjugate = hole + wfn_.nbasis / 2; -// if(std::find(holes.begin(), holes.end(), conjugate) != holes.end()) { -// occ_pairs.push_back(std::make_pair(hole, conjugate)); -// // exc_info.pair_inds.push_back(wfn_.nvir_up * hole); -// } -// } - -// std::vector vir_pairs; -// for (std::size_t part in particles) { -// std::size_t conjugate = part + wfn_.nbasis / 2; -// if(std::find(particles.begin(), particles.end(), conjugate) != particles.end()) { -// vir_pairs.push_back(std::make_pair(part, conjugate)); -// // exc_info.pair_inds.push_back(wfn_.nvir_up * part); -// } -// } - -// for (const auto& pair : occ_pairs) { -// for (const auto& vir_pair : vir_pairs) { -// exc_info.pair_inds.push_back(wfn_.nvir_up * pair.first + vir_pair.first); -// exc_info.pair_inds.push_back(wfn_.nvir_up * pair.second + vir_pair.second); -// } -// } - - - - // std::cout << "Generated hole_pairs: " << std::endl; - // for (const auto& hole_pair : hole_pairs) { - // for (const auto& elem: hole_pair) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - // } - - // Limit the number of pairs and singles to the requested partition - // hole_pairs.resize(std::min(hole_pairs.size(), static_cast(num_pairs))); - // hole_singles.resize(std::min(hole_singles.size(), static_cast(num_singles))); - // part_pairs.resize(std::min(part_pairs.size(), static_cast(num_pairs))); - // part_singles.resize(std::min(part_singles.size(), static_cast(num_singles))); - - // Match pairs and singles - // for (const auto& hole_pair : hole_pairs) { - // for (const auto& part_pair : part_pairs) { - // std::cout << "hole_pair: " << hole_pair[0] << " " << hole_pair[1] << std::endl; - // std::cout << "part_pair: " << part_pair[0] << " " << part_pair[1] << std::endl; - // // Check constraints - // pair_inds.push_back(nvir_up * hole_pair[0] + part_pair[0]); - // //pair_inds.push_back(wfn_.nvir_up * hole_pair[1] + part_pair[1]); - // } - // } - - // for (const auto& hole_single : hole_singles) { - // for (const auto& part_single : part_singles) { - // // Check constraints - // std::cout << "h: " << hole_single[0] << ", p: " << part_single[0] << std::endl; - // single_inds.push_back(nvir_up * nocc / 2 + hole_single[0] * nvir + part_single[0]); - // } - // } - - - //Retrieve the DetExcParamIndx object from the hash map - // const ulong* det = det_ptr(idet); - - // // std::vector det_vector(det, det + wfn_.nword); - // // Find corresponding DetExcParamIndx for the current determinant - // std::unordered_map, DetExcParamIndx> det_map; - // // Populate the hash map (assume det_exc_param_indx is iterable) - // for (const auto& exc_info : det_exc_param_indx) { - // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - // } - - // auto it = det_map.find(det_vector); - - - // Retrieve the corresponding determinant - // const ulong* det = det_ptr(idet); - - // std::vector det_vector(det, det + wfn_.nword); - // Find corresponding DetExcParamIndx for the current determinant - // std::unordered_map, DetExcParamIndx> det_map; - // // Populate the hash map (assume det_exc_param_indx is iterable) - // for (const auto& exc_info : det_exc_param_indx) { - // det_map[exc_info.det] = exc_info; // Use exc_info.det as the key - // } - - // Find corresponding DetExcParamIndx for the current determinant - // auto it = det_map.find(det_vector); - From 88fb37557dc1db0773a5a8a80010accde53ecd89 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:26:27 -0500 Subject: [PATCH 165/197] In compute_derivative: static cast iparam to long --- pyci/src/ap1rogen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index f35ff80..5cb00b3 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -453,7 +453,7 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector // If iparam is not in excitation_inds, return 0 if (it == excitation_inds.end()) {return 0.0;} - if (excitation_inds.size() == 1 && excitation_inds[0] == iparam) { + if (excitation_inds.size() == 1 && excitation_inds[0] == static_cast(iparam)) { reduced_permanent = 1.0; return reduced_permanent; } From a7c6cfa2f80ebcd1c334eca28d4d638b7271e4b8 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:28:26 -0500 Subject: [PATCH 166/197] Comment print statement --- pyci/src/ap1rogen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 5cb00b3..6f35a31 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -589,7 +589,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // std::cout << "single_permanent: " << single_permanent << std::endl; for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; + // std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; // std::cout << "nparam: " << nparam << std::endl; // std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; // std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; From b17b1c6f92314eabece706b950576e7d3717f4f8 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:30:01 -0500 Subject: [PATCH 167/197] Comment print statement --- pyci/src/ap1rogen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 6f35a31..23d60cd 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -157,7 +157,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector Date: Thu, 19 Dec 2024 20:39:38 -0500 Subject: [PATCH 168/197] Comment print statements, remove the unnecessary is_hf_det bool block --- pyci/src/nonsingletci.cpp | 369 ++++++++++---------------------------- 1 file changed, 95 insertions(+), 274 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index a5cdbdf..57f71c1 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -61,9 +61,9 @@ NonSingletCI::NonSingletCI(const long nb, const long nu, const long nd, const Ar std::vector> NonSingletCI::generate_cartesian_product( const AlignedVector>& pairs, std::size_t k) { std::vector> result; - std::cout << "Inside nonsingletci/generate_cartesian_product" << std::endl; - std::cout << "pairs.size(): " << pairs.size() << std::endl; - std::cout << "k: " << k << std::endl; + // std::cout << "Inside nonsingletci/generate_cartesian_product" << std::endl; + // std::cout << "pairs.size(): " << pairs.size() << std::endl; + // std::cout << "k: " << k << std::endl; std::size_t nocc_pairs = pairs.size(); if (k > nocc_pairs) return result; @@ -86,7 +86,6 @@ std::vector> NonSingletCI::generate_cartesian_product( } // Move the new combination into the result temp_combinations = std::move(new_result); - std::cout << "temp_combinations: "; } // Filter out combinations that are not of size k for (const auto& combination: temp_combinations) { @@ -96,7 +95,7 @@ std::vector> NonSingletCI::generate_cartesian_product( } // Debug output to ensure combinations are being generated - std::cout << "Generated " << result.size() << " combinations" << std::endl; + // std::cout << "Generated " << result.size() << " combinations" << std::endl; return result; } @@ -181,14 +180,14 @@ long NonSingletCI::calc_pindex(const long occ, const long vir) const { } void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ - std::cout << "Inside nonsingletci/add_excited_dets" << std::endl; - //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); - std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; - std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; - std::cout << "nocc_dn: " << nocc_dn << ", nvir_dn: " << nvir_dn << std::endl; - std::cout << "nbasis: " << nbasis << std::endl; - AlignedVector det(nword); + // std::cout << "Inside nonsingletci/add_excited_dets" << std::endl; + // //long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvirs_up, e); + // std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; + // std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; + // std::cout << "nocc_dn: " << nocc_dn << ", nvir_dn: " << nvir_dn << std::endl; + // std::cout << "nbasis: " << nbasis << std::endl; + AlignedVector det(nword); AlignedVector occs(nocc); AlignedVector virs(nbasis - nocc); AlignedVector occs_up, occs_dn, virs_up, virs_dn; @@ -221,16 +220,16 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ virs_up.shrink_to_fit(); virs_dn.shrink_to_fit(); - std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; - std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; - std::cout << "e: " << e << std::endl; - std::cout << "rdet: " << *rdet << std::endl; - print_vector("occs", occs); - print_vector("virs", virs); - print_vector("occs_up", occs_up); - print_vector("occs_dn", occs_dn); - print_vector("virs_up", virs_up); - print_vector("virs_dn", virs_dn); + // std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; + // std::cout << "nocc: " << nocc << ", nvir: " << nvir << std::endl; + // std::cout << "e: " << e << std::endl; + // std::cout << "rdet: " << *rdet << std::endl; + // print_vector("occs", occs); + // print_vector("virs", virs); + // print_vector("occs_up", occs_up); + // print_vector("occs_dn", occs_dn); + // print_vector("virs_up", virs_up); + // print_vector("virs_dn", virs_dn); // Create an unordered set for fast lookup of occupied down-orbitals std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); @@ -249,26 +248,17 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } } - print_pairs("occ_pairs", occ_pairs); - print_pairs("vir_pairs", vir_pairs); + // print_pairs("occ_pairs", occ_pairs); + // print_pairs("vir_pairs", vir_pairs); // Handle excitation order 0 if (e == 0) { - std::cout << "Handling excitation order 0" << std::endl; + // std::cout << "Handling excitation order 0" << std::endl; + std::memcpy(&det[0], rdet, sizeof(ulong) * nword); add_det(&det[0]); - // if (is_hf_det) { - // DetExcParamIndx container; - // container.det.resize(nword); - // std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); - // container.pair_inds.clear(); - // container.single_inds.clear(); - // ensure_struct_size(det_exc_param_indx, ndet); - // det_exc_param_indx[ndet-1] = container; - // std::cout << "Added HF det for e=0" << std::endl; - // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - // } + return ; } // Handle excitation order 1 @@ -279,58 +269,45 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ flattened_occs.push_back(pair.first); flattened_occs.push_back(pair.second); } - std::cout << "-----Handling excitation order 1-----" << std::endl; - std::cout << "Determinants of excitation order 1" << std::endl; + // std::cout << "-----Handling excitation order 1-----" << std::endl; + // std::cout << "Determinants of excitation order 1" << std::endl; + for (long occ : flattened_occs) { for (long vir : virs) { std::memcpy(&det[0], rdet, sizeof(ulong) * nword); excite_det(occ, vir, &det[0]); add_det(&det[0]); - // Structure to store determinant and indices of params - //corresponding to the pair-excitations & single-excitations - // if (is_hf_det) { - // DetExcParamIndx container; - // container.det.resize(nword); - // std::memcpy(&container.det[0], &det[0], sizeof(ulong) * nword); - // container.pair_inds.clear(); - // long sidx = calc_sindex(occ, vir); - // std::cout << "ndet: " << ndet << " S_index: " << (sidx) << std::endl; - // container.single_inds.push_back(sidx); - // std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; - // std::cout << "ndet" << ndet << std::endl; - // ensure_struct_size(det_exc_param_indx, ndet); - // det_exc_param_indx[ndet-1] = container; - // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - // } - std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; + // std::cout << "Determinant after excitation of " << occ << " " << vir << std::endl; + // for (int k = 0; k < nword; ++k) { + // std::cout << det[k] << " "; + // } + // std::cout << std::endl; } - std::cout << std::endl; + // std::cout << std::endl; } - std::cout << std::endl; + // std::cout << std::endl; return ; } // Handle excitation orders >= 2 std::size_t nocc_pairs = occ_pairs.size(); std::size_t nvir_pairs = vir_pairs.size(); - std::cout << "nocc_pairs: " << nocc_pairs << std::endl; + + // std::cout << "nocc_pairs: " << nocc_pairs << std::endl; + if (e >= 2) { // Iterate over possible (d,s) pairs: d pair excitations and s single excitations - std::cout << "--------Handling excitation order >= 2--------" << std::endl; + // std::cout << "--------Handling excitation order >= 2--------" << std::endl; for (std::size_t d = 0; d <= std::min(static_cast(e/2), nocc_pairs); ++d){ std::size_t num_singles = e - 2 * d; - std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; + // std::cout << "d: " << d << ", num_singles: " << num_singles << std::endl; // Not enough pairs for singles if (num_singles > (nocc_pairs - d)) { - std::cout << "Not enough pairs for singles" << std::endl; + // std::cout << "Not enough pairs for singles" << std::endl; continue; } @@ -341,30 +318,30 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ vpair_combinations.push_back(generate_combinations(nvir_pairs, d)); - std::cout << "Generated opair_combinations: " << std::endl; - for (const auto& opair_comb : opair_combinations[0]) { - for (const auto& idx : opair_comb) { - std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - } - } - std::cout << std::endl; + // std::cout << "Generated opair_combinations: " << std::endl; + // for (const auto& opair_comb : opair_combinations[0]) { + // for (const auto& idx : opair_comb) { + // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; + // } + // } + // std::cout << std::endl; - std::cout << "Generated vpair_combinations: " << std::endl; - for (const auto& pair_comb : vpair_combinations[0]) { - for (const auto& idx : pair_comb) { - std::cout << "(" << vir_pairs[idx].first << ", " << vir_pairs[idx].second << ") "; - } - } - std::cout << std::endl; + // std::cout << "Generated vpair_combinations: " << std::endl; + // for (const auto& pair_comb : vpair_combinations[0]) { + // for (const auto& idx : pair_comb) { + // std::cout << "(" << vir_pairs[idx].first << ", " << vir_pairs[idx].second << ") "; + // } + // } + // std::cout << std::endl; // Process pair combinations for current d for (const auto& opair_comb : opair_combinations[0]) { for (const auto& vpair_comb : vpair_combinations[0]) { - if (opair_comb.empty() || vpair_comb.empty()) { - std::cout << "Error: Empty combination detected" << std::endl; + // if (opair_comb.empty() || vpair_comb.empty()) { + // std::cout << "Error: Empty combination detected" << std::endl; // continue; - } + // } std::memcpy(&det[0], rdet, sizeof(ulong) * nword); std::vector used_virs; @@ -380,19 +357,14 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ used_virs.push_back(vir_pair.first); used_virs.push_back(vir_pair.second); - std::cout << "Determinant after pair excitation of" << std::endl; - std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; - std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - // if (is_hf_det){ - // long pidx = calc_pindex(occ_pair.first, vir_pair.first); - // std::cout << "Pair index: " << pidx << std::endl; - // det_exc.pair_inds.push_back(pidx); + // std::cout << "Determinant after pair excitation of" << std::endl; + // std::cout << "occ_pair: " << occ_pair.first << " " << occ_pair.second << std::endl; + // std::cout << "vir_pair: " << vir_pair.first << " " << vir_pair.second << std::endl; + // for (int k = 0; k < nword; ++k) { + // std::cout << det[k] << " "; // } - + // std::cout << std::endl; + } @@ -404,7 +376,7 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ remaining_occ_pairs.push_back(occ_pairs[i]); } } - print_pairs("remaining_occ_pairs", remaining_occ_pairs); + // print_pairs("remaining_occ_pairs", remaining_occ_pairs); AlignedVector remaining_virs; @@ -413,29 +385,29 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ remaining_virs.push_back(virs[i]); } } - print_vector("remaining_virs", remaining_virs); + // print_vector("remaining_virs", remaining_virs); // Process single combinations for current num_singles auto occ_combinations = generate_cartesian_product(remaining_occ_pairs, num_singles); auto vir_combinations = generate_combinations(remaining_virs.size(), num_singles); - std::cout << "Generated occ_combinations: " << std::endl; - for (const auto& occ_comb : occ_combinations) { - for (const auto& elem: occ_comb) { - std::cout << "(" << elem << ") "; - } - std::cout << std::endl; - } + // std::cout << "Generated occ_combinations: " << std::endl; + // for (const auto& occ_comb : occ_combinations) { + // for (const auto& elem: occ_comb) { + // std::cout << "(" << elem << ") "; + // } + // std::cout << std::endl; + // } - std::cout << "Generated vir_combinations: " << std::endl; - for (const auto& vir_comb : vir_combinations) { - std::cout << "("; - for (const auto& vir_idx : vir_comb) { - std::cout << remaining_virs[vir_idx] << " "; - } - std::cout << ")" << std::endl; - } + // std::cout << "Generated vir_combinations: " << std::endl; + // for (const auto& vir_comb : vir_combinations) { + // std::cout << "("; + // for (const auto& vir_idx : vir_comb) { + // std::cout << remaining_virs[vir_idx] << " "; + // } + // std::cout << ")" << std::endl; + // } for (const auto& occ_comb : occ_combinations) { @@ -449,26 +421,16 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ long occ = occ_comb[idx]; long vir = remaining_virs[vir_comb[idx]]; excite_det(occ, vir, &temp_det[0]); - std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; - // if (is_hf_det) { - // long sidx = calc_sindex(occ, vir); - // det_exc.single_inds.push_back(sidx); - // } + // std::cout << "Exciting occ: " << occ << " to vir: " << vir << std::endl; + } add_det(&temp_det[0]); // Print determinant after single excitations - std::cout << "Determinant for single combination" << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << temp_det[k] << " "; - } - std::cout << std::endl; - // if (is_hf_det) { - // det_exc.det.resize(nword); - // std::memcpy(&det_exc.det[0], &temp_det[0], sizeof(ulong) * nword); - // ensure_struct_size(det_exc_param_indx, ndet); - // det_exc_param_indx[ndet-1] = det_exc; - // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; + // std::cout << "Determinant for single combination" << std::endl; + // for (int k = 0; k < nword; ++k) { + // std::cout << temp_det[k] << " "; // } + // std::cout << std::endl; } } @@ -477,18 +439,11 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ // If num_singles == 0, directly add determinant after pair excitations add_det(&det[0]); // Print determinant after single excitations - std::cout << "Determinant for s=0" << std::endl; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - // if (is_hf_det) { - // det_exc.det.resize(nword); - // std::memcpy(&det_exc.det[0], &det[0], sizeof(ulong) * nword); - // ensure_struct_size(det_exc_param_indx, ndet); - // det_exc_param_indx[ndet-1] = det_exc; - // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - // } + // std::cout << "Determinant for s=0" << std::endl; + // for (int k = 0; k < nword; ++k) { + // std::cout << det[k] << " "; + // } + // std::cout << std::endl; } } } @@ -506,7 +461,7 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) const { // FIXME: The code is assuming nocc is even long nocc_beta = nocc/2; //std::min(nocc, nb); long nocc_alpha = nocc/2; //std::min(0L, nocc - nb); - long num_ulongs = (nb2 + Size() - 1) / Size(); + // long num_ulongs = (nb2 + Size() - 1) / Size(); // std::cout << "Inside nonsingletci/fill_hartreefock_det" << std::endl; @@ -554,137 +509,3 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re return ndet - ndet_old; } } //namespace pyci - - - -// // // Generate all combinations of d pairs -// std::vector> opair_combinations; -// std::vector pair_indices(occ_pairs.size()); -// std::iota(pair_indices.begin(), pair_indices.end(), 0); - -// do { -// std::vector combination(pair_indices.begin(), pair_indices.begin() + d); -// opair_combinations.push_back(combination); -// } while (std::next_permutation(pair_indices.begin(), pair_indices.end())); - -// // Process each combination of d pairs -// for (const auto& opair_comb: opair_combinations) { -// std::vector> used_occ_pairs; -// std::vector used_virtuals; - -// // Apply pair excitations -// std::memcpy(&det[0], rdet, sizeof(ulong) * nword); -// for (long idx : opair_comb) { -// const auto& occ_pair = occ_pairs[idx]; -// const auto& vir_pair = vir_pairs[idx]; - -// excite_det(occ_pair.first, vir_pair.first, &det[0]); -// excite_det(occ_pair.second, vir_pair.second, &det[0]); - -// used_occ_pairs.push_back(occ_pair); -// used_virtuals.push_back(vir_pair.first); -// used_virtuals.push_back(vir_pair.second); -// } - -// //Exclude used pairs and virtual orbitals -// std::vector remaining_occ_indices; -// for (std::vector>::size_type i = 0; i < occ_pairs.size(); ++i) { -// if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { -// remaining_occ_indices.push_back(static_cast(i)); -// } -// } - -// // Generate all combinations of s singles -// std::vector> single_combinations; -// std::vector single_indices(remaining_occ_indices.size()); -// std::iota(single_indices.begin(), single_indices.end(), 0); - -// do { -// std::vector combination(single_indices.begin(), single_indices.begin() + s); -// single_combinations.push_back(combination); -// } while (std::next_permutation(single_indices.begin(), single_indices.end())); - -// // Process each combination of s singles -// for (const auto& single_comb : single_combinations) { -// std::memcpy(&det[0], rdet, sizeof(ulong) * nword); - -// // Apply single excitations -// for (long idx : single_comb) { -// long occ_idx = remaining_occ_indices[idx]; -// long occ = occ_pairs[occ_idx].first; // Use the first of the remaining occ_pair -// for (long vir: virs) { -// if (std::find(used_virtuals.begin(), used_virtuals.end(), vir) != used_virtuals.end()) continue; -// excite_det(occ, vir, &det[0]); -// } -// } -// add_det(&det[0]); -// } -// } - -// for (const auto& elem : occs) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - - // std::cout << "virs: "; - // for (const auto& elem : virs) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - - - // std::cout << "occs_up: "; - // for (const auto& elem : occs_up) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - - // std::cout << "occs_dn: "; - // for (const auto& elem : occs_dn) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - - - // std::cout << "virs_up: "; - // for (const auto& elem : virs_up) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - // std::cout << "virs_dn: "; - // for (const auto& elem : virs_dn) { - // std::cout << elem << " "; - // } - // std::cout << std::endl; - - - - // std::cout << "Generated occ_combinations: " << std::endl; - // for (const auto& occ_comb : occ_combinations) { - // std::cout << "("; - // for (const auto& occ_idx : occ_comb) { - // std::cout << occ_pairs[remaining_occ_indices[occ_idx]].first << " "; - // } - // std::cout << ")" << std::endl; - // } - - // Print occ_combinations and vir_combinations for debugging - // std::cout << "Available occ_pairs for singles: "; - // for (const auto& idx : remaining_occ_indices) { - // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - // } - // std::cout << std::endl; - - - // // Determine remaining occupied indices - // std::vector remaining_occ_indices; - // for (long i = 0; i < nocc_pairs; ++i) { - // if (std::find(opair_comb.begin(), opair_comb.end(), i) == opair_comb.end()) { - // remaining_occ_indices.push_back(i); - // } - // } - // std::cout << "Remaining occ_indices: "; - // for (const auto& idx : remaining_occ_indices) { - // std::cout << "(" << occ_pairs[idx].first << ", " << occ_pairs[idx].second << ") "; - // } - // std::cout << std::endl; \ No newline at end of file From 0cea1ea7b8621b84ec9b6c5173a30d6ab1d131eb Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:40:23 -0500 Subject: [PATCH 169/197] Remove print statements --- pyci/excitation_ci.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyci/excitation_ci.py b/pyci/excitation_ci.py index ef50097..1554bf1 100644 --- a/pyci/excitation_ci.py +++ b/pyci/excitation_ci.py @@ -35,7 +35,5 @@ def add_excitations(wfn, *excitations, ref=None): Default is the Hartree-Fock determinant. """ - print("Inside excitation_ci/add_excitations") for e in excitations: - print(f"Adding {e}-excited determinants...") wfn.add_excited_dets(e, ref=ref) From e4be5230270a3f60f1e7f1aa6b36a8c7194fa5f4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:42:58 -0500 Subject: [PATCH 170/197] Remove print statements --- pyci/fanci/fanci.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index e4577f3..d621ae3 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -199,7 +199,6 @@ def __init__( # Generate determinant spaces wfn = fill_wavefunction(wfn, nproj, fill) - print("type", type(wfn)) # Compute CI matrix operator with nproj rows and len(wfn) columns if type(wfn).__name__ == "nonsingletci_wfn": ci_op = pyci.sparse_op(ham, wfn, nrow=nproj, ncol=len(wfn), symmetric=False, wfntype="nonsingletci") @@ -689,7 +688,6 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: print(f"e_max: {e_max}, len(wfn) before filling: {len(wfn)}") for nexc in range(e_max + 1): if len(wfn) >= nproj: - print("Breaking filling as len(wfn) >= nproj") break pyci.add_excitations(wfn, nexc) @@ -714,7 +712,6 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: wfn = wfn.__class__(wfn.nbasis, wfn.nocc_up, wfn.nocc_dn, wfn.to_det_array(nproj)) # Fill wfn with S space determinants - print("\nAdding S space determinants") for det in wfn.to_det_array(nproj): pyci.add_excitations(wfn, *connections, ref=det) From cbbb1229006aedf1856600b2ff6ab7906cb58f8f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:46:18 -0500 Subject: [PATCH 171/197] Remove commit statement --- pyci/src/ap1rog.cpp | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/pyci/src/ap1rog.cpp b/pyci/src/ap1rog.cpp index bed5cab..8fa1cae 100644 --- a/pyci/src/ap1rog.cpp +++ b/pyci/src/ap1rog.cpp @@ -60,9 +60,6 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) nrow = wfn_.nocc_up; ncol = wfn_.nbasis - wfn_.nocc_up; - std::cout << "nconn, nparam: " << nconn << "," << nparam << ", nrow: " << nrow << ", ncol: " << ncol << std::endl; - - ovlp.resize(nconn); d_ovlp.resize(nconn * nparam); @@ -78,33 +75,20 @@ void AP1roGObjective::init_overlap(const DOCIWfn &wfn_) ulong word, hword, pword; std::size_t h, p, nexc = 0; - std::cout << "idet: " << idet << std::endl; - std::cout << "nword: " << nword << std::endl; - for (std::size_t iword = 0; iword != nword; ++iword) { - std::cout << "rdet[" << iword << "]: " << rdet[iword] << std::endl; - std::cout << "det[iword]: " << det[iword] << std::endl; word = rdet[iword] ^ det[iword]; hword = word & rdet[iword]; pword = word & det[iword]; - std::cout << "word: " << word << ", hword: " << hword << ", pword: " << pword << std::endl; + while (hword) { h = Ctz(hword); p = Ctz(pword); hole_list[idet * wfn_.nocc_up + nexc] = h + iword * Size(); part_list[idet * wfn_.nocc_up + nexc] = p + iword * Size() - wfn_.nocc_up; - std::cout << "nexc: " << nexc << ",h: " << h << ", p: " << p << std::endl; - std::cout << "hole_list: " << hole_list[idet * wfn_.nocc_up + nexc] << ", part_list: " << part_list[idet * wfn_.nocc_up + nexc] << std::endl; - hword &= ~(1UL << h); pword &= ~(1UL << p); - ++nexc; - std::cout << "hword" << hword << std::endl; - std::cout << "pword" << pword << std::endl; - std::cout << "nexc: " << nexc << std::endl; - std::cout << "nexc_list: " << nexc_list[idet] << std::endl; - + ++nexc; } } nexc_list[idet] = nexc; @@ -132,8 +116,6 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Iterate over c = pow(2, m) submatrices (equal to (1 << m)) submatrices. */ c = 1UL << m; - std::cout << "idet" << idet << std::endl; - std::cout <<"c: " << c << ", m: " << m << std::endl; /* Loop over columns of submatrix; compute product of row sums. */ for (k = 0; k < c; ++k) { @@ -146,26 +128,18 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Add element to row sum if the row index is in the characteristic * * vector of the submatrix, which is the binary vector given by k. */ - std::cout << "k: " << k << std::endl; - std::cout << "i, j: " << i << "," << j << std::endl; - //std::cout << "1UL << j: " << 1UL << j << std::endl; std::size_t xpq = k & (1UL << j); std::cout << "k &(1UL << j): " << xpq << std::endl; if (k & (1UL << j)) { - std::cout << "hlist[i], plist[j]: " << hlist[i] << "," << plist[j] << std::endl; - std::cout << "ncol * hlist[i] + plist[j]: " << ncol * hlist[i] + plist[j] << std::endl; rowsum += x[ncol * hlist[i] + plist[j]]; - std::cout << "rowsum: " << rowsum << std::endl; } } /* Update product of row sums. */ rowsumprod *= rowsum; - std::cout << "rowsumprod: " << rowsumprod << std::endl; } /* Add term multiplied by the parity of the characteristic vector. */ - std::cout << "\n(__builtin_popcountll(k) & 1) << 1: " << (__builtin_popcountll(k) & 1) << std::endl; out += rowsumprod * (1 - ((__builtin_popcountll(k) & 1) << 1)); } From 6f21880656b1f311abc1eb894eb277339dcb2a91 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:49:57 -0500 Subject: [PATCH 172/197] Remove print statement --- pyci/fanci/fanci.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index d621ae3..43c5575 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -685,7 +685,6 @@ def fill_wavefunction(wfn: pyci.wavefunction, nproj: int, fill: str) -> None: # Fill wfn with P space determinants in excitation order until len(wfn) >= nproj; # only add Hartree-Fock det. (zero order excitation) if wfn is empty # for nexc in range(bool(len(wfn)), e_max + 1): - print(f"e_max: {e_max}, len(wfn) before filling: {len(wfn)}") for nexc in range(e_max + 1): if len(wfn) >= nproj: break From fd41e5ebf9a1b15997da7d5c7d20e9f0ebc4f0ff Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:54:10 -0500 Subject: [PATCH 173/197] Remove print statement --- pyci/src/ap1rog.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyci/src/ap1rog.cpp b/pyci/src/ap1rog.cpp index 8fa1cae..f770811 100644 --- a/pyci/src/ap1rog.cpp +++ b/pyci/src/ap1rog.cpp @@ -128,8 +128,6 @@ void AP1roGObjective::overlap(const size_t ndet, const double *x, double *y) { /* Add element to row sum if the row index is in the characteristic * * vector of the submatrix, which is the binary vector given by k. */ - std::size_t xpq = k & (1UL << j); - std::cout << "k &(1UL << j): " << xpq << std::endl; if (k & (1UL << j)) { rowsum += x[ncol * hlist[i] + plist[j]]; } From 8aa721f0f7b45febef2c064ce107ba2be5b94fce Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:55:19 -0500 Subject: [PATCH 174/197] Remove print statement --- pyci/fanci/ap1rogen.py | 43 ------------------------------------------ 1 file changed, 43 deletions(-) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index a407042..ad8162c 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -58,57 +58,20 @@ def __init__( nparam = nocc * (ham.nbasis - nocc) + (2 * nocc) * (2 * (ham.nbasis - nocc)) + 1 #less params considering we added singles as well nproj = nparam if nproj is None else nproj - print("\n nparam, nproj", nparam, nproj) if wfn is None: wfn = pyci.doci_wfn(ham.nbasis, nocc, nocc) - print("\nCreated DOCI wfn instance for AP1roGSDGeneralized_sen-o.") wfn.add_excited_dets(1) # add pair excited determinants - - print("\nCreating fci wfn") wfn = pyci.fullci_wfn(wfn) - print("wfn.nocc, wfn.nocc_up, wfn.nocc_dn: ", wfn.nocc, wfn.nocc_up, wfn.nocc_dn) - occ_array = wfn.to_occ_array() - det_array = wfn.to_det_array() - print(f"\nFor FCI {len(occ_array)} det & corresponding occ_array:") - for i, j in zip(det_array, occ_array): - print(i, j) - - print("\nCreating NonSingletCI wfn") wfn = pyci.nonsingletci_wfn(wfn) - print("wfn.nocc, wfn.nocc_up, wfn.nocc_dn: ", wfn.nocc, wfn.nocc_up, wfn.nocc_dn) - occ_array = wfn.to_occ_array() - det_array = wfn.to_det_array() - print("\nFor NonSingletCI wfn det_array: ", len(det_array), "\n", det_array) - #for det, occ in zip(det_array, occ_array): - # print(det, bin(int(det)), occ) - - ## Generate the bitstring - #bitstring = ((1 << wfn.nocc //2) - 1) << ham.nbasis | (1 << wfn.nocc//2) - 1 - ## Convert to binary string with leading zeros - #nb = ham.nbasis - #bit_str = format(bitstring, f'0{2 * nb}b') - #unocc = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '0'] - #occ = [i for i in range(len(bit_str)) if bit_str[nb-i-1] == '1'] - ## Adding non-spin-preserving alpha -> beta singles - #for i in occ: - # for a in unocc: - # exc_str = _excite_det(i, a, int(bit_str,2)) - # print("i, a, exc_str", i, a, exc_str, format(exc_str, f'0{2*nb}b')) - # wfn.add_det(np.array(exc_str, dtype=pyci.c_ulong)) - # - #det_array = wfn.to_det_array() - #print("\nFor GenCI wfn det_array after adding Gen_sen-o S:", len(det_array), "\n", det_array) elif not isinstance(wfn, pyci.nonsingletci_wfn): raise TypeError(f"Invalid `wfn` type `{type(wfn)}`; must be `pyci.nonsingletci_wfn`") - #elif wfn.nocc_up != nocc or wfn.nocc != nocc: elif wfn.nocc != nocc: raise ValueError(f"wfn.nocc does not match `nocc={nocc}` parameter") # Initialize base class - print("\nInitializing base class") FanCI.__init__(self, ham, wfn, nproj, nparam, **kwargs) # Assign reference occupations @@ -213,9 +176,3 @@ def compute_jacobian(self, x: np.ndarray) -> np.ndarray: """ return self._cext.jacobian(self._ci_op, x) - -def _excite_det(i: int, a: int, bitstring: int): - bitstring &= ~(1 << i) - bitstring |= (1 << a) - #pdb.set_trace() - return bitstring From 0f1995e53db381b6846341bb7b8f89fad6337688 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:59:02 -0500 Subject: [PATCH 175/197] Remove print statements --- pyci/src/onespinwfn.cpp | 42 ----------------------------------------- 1 file changed, 42 deletions(-) diff --git a/pyci/src/onespinwfn.cpp b/pyci/src/onespinwfn.cpp index c671640..9c9f183 100644 --- a/pyci/src/onespinwfn.cpp +++ b/pyci/src/onespinwfn.cpp @@ -219,12 +219,6 @@ void OneSpinWfn::add_all_dets(long nthread) { void OneSpinWfn::add_excited_dets(const ulong *rdet, const long e) { long i, j, k, no = binomial(nocc_up, e), nv = binomial(nvir_up, e); - std::cout << "Inside onespinwfn/add_excited_dets" << std::endl; - std::cout << "no: " << no << ", nv: " << nv << ", nword: " << nword << std::endl; - std::cout << "nocc_up: " << nocc_up << ", nvir_up: " << nvir_up << std::endl; - std::cout << "e: " << e << std::endl; - std::cout << "rdet: " << *rdet << std::endl; - AlignedVector det(nword); AlignedVector occs(nocc_up); AlignedVector virs(nvir_up); @@ -233,18 +227,6 @@ void OneSpinWfn::add_excited_dets(const ulong *rdet, const long e) { fill_occs(nword, rdet, &occs[0]); fill_virs(nword, nbasis, rdet, &virs[0]); - std::cout << "occs: "; - for (const auto& elem : occs) { - std::cout << elem << " "; - } - std::cout << std::endl; - - std::cout << "virs: "; - for (const auto& elem : virs) { - std::cout << elem << " "; - } - std::cout << std::endl; - for (k = 0; k < e; ++k) virinds[k] = k; virinds[e] = nvir_up + 1; @@ -253,35 +235,11 @@ void OneSpinWfn::add_excited_dets(const ulong *rdet, const long e) { occinds[k] = k; occinds[e] = nocc_up + 1; for (j = 0; j < no; ++j) { - std::cout << "virinds: "; - for (const auto& elem : virinds) { - std::cout << elem << " "; - } - std::cout << std::endl; - - std::cout << "occinds: "; - for (const auto& elem : occinds) { - std::cout << elem << " "; - } - std::cout << std::endl; - - // Print determinant before excite_det loop - std::cout << "Determinant before excite_det loop: "; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } - std::cout << std::endl; - std::memcpy(&det[0], rdet, sizeof(ulong) * nword); for (k = 0; k < e; ++k) { excite_det(occs[occinds[k]], virs[virinds[k]], &det[0]); } - // Print determinant after excite_det loop - std::cout << "Determinant after excite_det loop: "; - for (int k = 0; k < nword; ++k) { - std::cout << det[k] << " "; - } std::cout << std::endl; add_det(&det[0]); next_colex(&occinds[0]); From c245c60ead55ac0bb21b1b239edc0f2ac345beb1 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 20:59:45 -0500 Subject: [PATCH 176/197] Remove print statements --- pyci/src/squantop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyci/src/squantop.cpp b/pyci/src/squantop.cpp index fca0788..511274b 100644 --- a/pyci/src/squantop.cpp +++ b/pyci/src/squantop.cpp @@ -112,7 +112,7 @@ SQuantOp::SQuantOp(const std::string &filename) { h = reinterpret_cast(h_array.request().ptr); v = reinterpret_cast(v_array.request().ptr); w = reinterpret_cast(w_array.request().ptr); - std::cout << "size of h: file" << h_array.request().size << std::endl; + long n1, n2, n3; n1 = nbasis; n2 = n1 * n1; From d7c581f920e12234d51a9883edc5084dcbde5efb Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 21:01:00 -0500 Subject: [PATCH 177/197] Remove print statements --- pyci/src/fullciwfn.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pyci/src/fullciwfn.cpp b/pyci/src/fullciwfn.cpp index 2162423..494a23e 100644 --- a/pyci/src/fullciwfn.cpp +++ b/pyci/src/fullciwfn.cpp @@ -25,20 +25,14 @@ FullCIWfn::FullCIWfn(FullCIWfn &&wfn) noexcept : TwoSpinWfn(wfn) { } FullCIWfn::FullCIWfn(const DOCIWfn &wfn) : TwoSpinWfn(wfn.nbasis, wfn.nocc_up, wfn.nocc_dn) { - std::cout << "Initializing FullCIWfn from DOCIWfn" << std::endl; ndet = wfn.ndet; - std::cout << "Number of determinants: " << ndet << std::endl; dets.resize(wfn.ndet * nword2); - std::cout << "Resized dets array to: " << (wfn.ndet * nword2) << std::endl; dict.clear(); - std::cout << "Cleared dictionary" << std::endl; for (long i = 0; i < wfn.ndet; ++i) { std::memcpy(&dets[i * wfn.nword2], wfn.det_ptr(i), sizeof(ulong) * wfn.nword); std::memcpy(&dets[i * wfn.nword2 + wfn.nword], wfn.det_ptr(i), sizeof(ulong) * wfn.nword); dict[rank_det(&dets[i * wfn.nword2])] = i; - std::cout << "Processed determinant " << i << std::endl; } - std::cout << "Finished initializing FullCIWfn from DOCIWfn" << std::endl; } FullCIWfn::FullCIWfn(const std::string &filename) : TwoSpinWfn(filename) { From b5504e6a03f620cf7d3db3a10e2809e1e07313e2 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 21:05:59 -0500 Subject: [PATCH 178/197] Remove print statements --- pyci/src/twospinwfn.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pyci/src/twospinwfn.cpp b/pyci/src/twospinwfn.cpp index 7f269d2..e0fabc6 100644 --- a/pyci/src/twospinwfn.cpp +++ b/pyci/src/twospinwfn.cpp @@ -250,12 +250,9 @@ void TwoSpinWfn::add_excited_dets(const ulong *rdet, const long e_up, const long add_det(rdet); return; } - std::cout << "Inside twospin/add_excited_dets " << std::endl; - std::cout << "Calling OneSpinWfn to add_excited_dets in wfn_up " << std::endl; OneSpinWfn wfn_up(nbasis, nocc_up, nocc_up); wfn_up.add_excited_dets(&rdet[0], e_up); - std::cout << "Calling OneSpinWfn to add_excited_dets in wfn_up " << std::endl; OneSpinWfn wfn_dn(nbasis, nocc_dn, nocc_dn); wfn_dn.add_excited_dets(&rdet[nword], e_dn); AlignedVector det(nword2); @@ -330,8 +327,6 @@ long TwoSpinWfn::py_add_occs(const Array occs) { long TwoSpinWfn::py_add_excited_dets(const long exc, const pybind11::object ref) { AlignedVector v_ref; ulong *ptr; - std::cout << "Inside twospin/py_add_excited_dets " << std::endl; - std::cout << "exc: " << exc << std::endl; if (ref.is(pybind11::none())) { v_ref.resize(nword2); ptr = &v_ref[0]; @@ -345,8 +340,6 @@ long TwoSpinWfn::py_add_excited_dets(const long exc, const pybind11::object ref) long a = (exc < maxup) ? exc : maxup; long b = exc - a; while ((a >= 0) && (b <= maxdn)){ - std::cout << "Callling twospin/add_excited_dets with " << std::endl; - std::cout << "a: " << a << " b: " << b << std::endl; add_excited_dets(ptr, a--, b++); } return ndet - ndet_old; From 2d71904c439f50898ecb743d453a1e874dc4904e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 19 Dec 2024 21:11:17 -0500 Subject: [PATCH 179/197] Remove the is_hf_det bool --- pyci/include/pyci.h | 3 --- pyci/src/nonsingletci.cpp | 3 --- 2 files changed, 6 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index e01b1de..6c4df71 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -646,9 +646,6 @@ struct NonSingletCI final : public GenCIWfn { using Wfn::dets; using Wfn::dict; -private: - // bool is_hf_det; - public: NonSingletCI(const NonSingletCI &); diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 57f71c1..6bcdcb9 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -498,11 +498,8 @@ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object re v_ref.resize(nword); ptr = &v_ref[0]; fill_hartreefock_det(nbasis,nocc, ptr); - - // is_hf_det = true; } else { ptr = reinterpret_cast(ref.cast>().request().ptr); - // is_hf_det = false; } long ndet_old = ndet; add_excited_dets(ptr, exc); From 1a3bf3605d031a6a2c7b33ce9de1c413cb26c93f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 22 Dec 2024 22:49:15 -0500 Subject: [PATCH 180/197] Update the compute_derivative helper function with modified Ryser's algorithm; exclude row i and col j corresponding to iparam --- pyci/src/ap1rogen.cpp | 122 ++++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 34 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 23d60cd..286b96c 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -436,45 +436,80 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector const double* x, std::size_t iparam) { // std::cout << "\nComputing derivative" << std::endl; - double reduced_permanent = 0.0; - // std::cout << "excitation_inds: "; - // for (const auto& eid : excitation_inds) { - // std::cout << eid << " "; - // } - // std::cout << std::endl; - // std::cout << "iparam: " << iparam << std::endl; - // Check if excitation_inds is empty, first element is -1 - if (excitation_inds[0] == -1) {return 0.0;} + //--------------------------------------------------------- + // double reduced_permanent = 0.0; + // // Check if excitation_inds is empty, first element is -1 + // if (excitation_inds[0] == -1) {return 0.0;} - // check if iparam is within excitation_inds - auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); + // // check if iparam is within excitation_inds + // auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); - // If iparam is not in excitation_inds, return 0 - if (it == excitation_inds.end()) {return 0.0;} + // // If iparam is not in excitation_inds, return 0 + // if (it == excitation_inds.end()) {return 0.0;} - if (excitation_inds.size() == 1 && excitation_inds[0] == static_cast(iparam)) { - reduced_permanent = 1.0; - return reduced_permanent; - } - // Modify x such that it excludes the parameter at index iparam - std::vector modified_x(x, x + nparam); - modified_x[iparam] = 1.0; + // if (excitation_inds.size() == 1 && excitation_inds[0] == static_cast(iparam)) { + // reduced_permanent = 1.0; + // return reduced_permanent; + // } + // // Modify x such that it excludes the parameter at index iparam + // std::vector modified_x(x, x + nparam); + // modified_x[iparam] = 1.0; - // std::cout << "Modified x: "; - // for (const auto& rid : modified_x) { - // std::cout << rid << " "; - // } - // std::cout << std::endl; - permanent_calculation(excitation_inds, modified_x.data(), reduced_permanent); + // // std::cout << "Modified x: "; + // // for (const auto& rid : modified_x) { + // // std::cout << rid << " "; + // // } + // // std::cout << std::endl; + // permanent_calculation(excitation_inds, modified_x.data(), reduced_permanent); - if (std::isnan(reduced_permanent) || std::isinf(reduced_permanent)) { - std::cerr << "Error: reduced_permanent is invalid (NaN or Inf)" << std::endl; - return 0.0; + // if (std::isnan(reduced_permanent) || std::isinf(reduced_permanent)) { + // std::cerr << "Error: reduced_permanent is invalid (NaN or Inf)" << std::endl; + // return 0.0; + // } + // // std::cout << "\nreduced_permanent: " << reduced_permanent << std::endl; + // return reduced_permanent; + //--------------------------------------------------------- + std::size_t n = static_cast(std::sqrt(excitation_inds.size())); + if (n == 0) {return 0.0;} + if (n == 1) { + return (excitation_inds[0] == static_cast(iparam)) ? 1.0 : 0.0; } - // std::cout << "\nreduced_permanent: " << reduced_permanent << std::endl; - return reduced_permanent; + + double derivative = 0.0; + std::size_t subset_count = 1UL << n; // 2^n subsets + // Derive i and j from iparam + std::size_t i = iparam / n; + std::size_t j = iparam % n; + + for (std::size_t subset = 0; subset < subset_count; ++subset) { + // skip subsets where column j is not included + if ((subset & (1UL << j))) continue; + + double rowsumprod = 1.0; + + // Compute product of row sums for rows k != i + for (std::size_t k = 0; k < n; ++k) { + if (k == i) continue; + + double rowsum = 0.0; + + for (std::size_t l = 0; l < n; ++l) { + if (subset & (1UL << l)) { + rowsum += x[excitation_inds[k * n + l]]; + } + } + rowsumprod *= rowsum; + } + // Parity adjustment + int subset_parity = (__builtin_popcount(subset) % 2 == 0) ? 1 : -1; + derivative += rowsumprod * subset_parity; + } + // Final adjustment for the excluded row i + derivative *= ((n % 2 == 1) ? -1 : 1); + return derivative; + } @@ -555,6 +590,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // std::cout << "Size of s_permanent: " << s_permanent.size() << std::endl; // std::cout << "Size of p_permanent: " << p_permanent.size() << std::endl; // std::cout << "ndet: " << ndet << std::endl; + // const double epsilon = 1.0e-7; for (std::size_t idet = 0; idet != ndet; ++idet) { // Ensure we have the excitation parameters for this determinant @@ -594,8 +630,25 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; // std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; // std::cout << "size of y array: " << &y.size() << std::endl; - double dpair = 0.0; - double dsingle = 0.0; + //-----Numerical Derivative Calculation--------------------------------------- + // double pair_plus = 0.0; + // double single_plus = 0.0; + // std::vector x_perturb(x, x + nparam); + // x_perturb[iparam] += epsilon; + // permanent_calculation(exc_info.pair_inds, x_perturb.data(), pair_plus); + // permanent_calculation(exc_info.single_inds, x_perturb.data(), single_plus); + + // x_perturb[iparam] -= 2 * epsilon; + // double pair_minus = 0.0; + // double single_minus = 0.0; + // permanent_calculation(exc_info.pair_inds, x_perturb.data(), pair_minus); + // permanent_calculation(exc_info.single_inds, x_perturb.data(), single_minus); + + // double dpair = 0.0; + // double dsingle = 0.0; + // dpair = (pair_plus - pair_minus) / (2 * epsilon); + // dsingle = (single_plus - single_minus) / (2 * epsilon); + //---------------------------------------------------------------------------- // std::cout << "exc_info.single_inds: "; // for (const auto& sid : exc_info.single_inds) { // std::cout << sid << " "; @@ -606,7 +659,8 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // std::cout << pid << " "; // } // std::cout << std::endl; - + double dpair = 0.0; + double dsingle = 0.0; if (exc_info.single_inds[0] != -1) { dsingle = compute_derivative(exc_info.single_inds, x, iparam); // std::cout << "dsingle: " << dsingle << std::endl; From 94fcef26b511a25c15528f62a6c7ad9785543861 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Sun, 22 Dec 2024 22:55:04 -0500 Subject: [PATCH 181/197] correct the sign for alpha beta -> alpha beta matrix elements, correct ii index for beta -> beta element --- pyci/src/sparseop.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 8b92801..6200e71 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -592,7 +592,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // first excitation: alpha -> alpha for (j = 0; j < nvir_up; ++j) { jj = virs_up[j]; - // alpha -> alpha excitation elements excite_det(ii, jj, det_up); sign_up = phase_single_det(wfn.nword, ii, jj, rdet_up); jdet = wfn.index_det(det_up); @@ -631,7 +630,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { counter += 1; - // add the matrix element + // add the aaaa --> aaaa matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * (ham.two_mo[koffset + n1 * jj + ll] - ham.two_mo[koffset + n1 * ll + jj])); @@ -656,12 +655,14 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { // std::cout << "\nii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; // std::cout << "ndet_up: " << *det_up << std::endl; - double sign = phase_single_det(wfn.nword, kk, ll, rdet_up); + // double sign = phase_single_det(wfn.nword, kk, ll, rdet_up); + double sign = phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up); if (jj >= nbasis) jj -= nbasis; if (kk >= nbasis) kk -= nbasis; if (ll >= nbasis) ll -= nbasis; counter += 1; - append(data, sign_up * sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); + // append(data, sign_up * sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); + append(data, sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); append(indices, jdet); ll = virs_dn[l]; kk = occs_dn[k]; @@ -695,6 +696,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { + if (ii >= nbasis) ii -= nbasis; if (jj >= nbasis) jj -= nbasis; // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; @@ -710,6 +712,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; } jj = virs_dn[j]; + ii = occs_dn[i]; append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); From 0d975f92f13e4d2fb1e289a0868d7851df3d273e Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Fri, 3 Jan 2025 13:55:41 -0500 Subject: [PATCH 182/197] Add code for testing the pCCD+ spin-preserving Singles --- pyci/src/nonsingletci.cpp | 97 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index 6bcdcb9..e190db1 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -288,6 +288,27 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } // std::cout << std::endl; return ; + + + // //-----------------------pCCDSspin test----------------------- + // // std::cout << "-----Handling excitation order 1-----" << std::endl; + // for (long occ : occs_up) { + // for (long vir : virs_up) { + // std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + // excite_det(occ, vir, &det[0]); + // add_det(&det[0]); + // } + // } + + // for (long occ : occs_dn) { + // for (long vir : virs_dn) { + // std::memcpy(&det[0], rdet, sizeof(ulong) * nword); + // excite_det(occ, vir, &det[0]); + // add_det(&det[0]); + // } + // } + // return; + // //-----------------------pCCDSspin test----------------------- } // Handle excitation orders >= 2 @@ -345,7 +366,8 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ std::memcpy(&det[0], rdet, sizeof(ulong) * nword); std::vector used_virs; - DetExcParamIndx det_exc; + std::vector used_occs; + // DetExcParamIndx det_exc; for (std::size_t idx = 0; idx < d; ++idx) { const auto& occ_pair = occ_pairs[opair_comb[idx]]; @@ -354,6 +376,9 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ excite_det(occ_pair.first, vir_pair.first, &det[0]); excite_det(occ_pair.second, vir_pair.second, &det[0]); + + used_occs.push_back(occ_pair.first); + used_occs.push_back(occ_pair.second); used_virs.push_back(vir_pair.first); used_virs.push_back(vir_pair.second); @@ -434,6 +459,76 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ } } + + // //-----------------------pCCDSspin test----------------------- + // AlignedVector remaining_occs; + // AlignedVector remaining_virs; + // for (long occ : occs) { + // if (std::find(used_occs.begin(), used_occs.end(), occ) == used_occs.end()) { + // remaining_occs.push_back(occ); + // } + // } + + // for (long vir : virs) { + // if (std::find(used_virs.begin(), used_virs.end(), vir) == used_virs.end()) { + // remaining_virs.push_back(vir); + // } + // } + + // AlignedVector rem_occ_up; + // AlignedVector rem_occ_dn; + // for (long occ : remaining_occs) { + // if (occ < nbasis / 2) { + // rem_occ_up.push_back(occ); + // } else { + // rem_occ_dn.push_back(occ); + // } + // } + + // AlignedVector rem_vir_up; + // AlignedVector rem_vir_dn; + // for (long vir : remaining_virs) { + // if (vir < nbasis / 2) { + // rem_vir_up.push_back(vir); + // } else { + // rem_vir_dn.push_back(vir); + // } + // } + + // auto occ_combs = generate_combinations(rem_occ_up.size(), num_singles); + // auto vir_combs = generate_combinations(rem_vir_up.size(), num_singles); + + + // for (const auto& occ_comb : occ_combs) { + // for (const auto& vir_comb : vir_combs) { + // AlignedVector temp_det(nword); + // std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); + // for (std::size_t idx = 0; idx < num_singles; ++idx) { + // long occ = rem_occ_up[occ_comb[idx]]; + // long vir = rem_vir_up[vir_comb[idx]]; + // excite_det(occ, vir, &temp_det[0]); + // } + // add_det(&temp_det[0]); + // } + // } + + // auto occ_combs_dn = generate_combinations(rem_occ_dn.size(), num_singles); + // auto vir_combs_dn = generate_combinations(rem_vir_dn.size(), num_singles); + + // for (const auto& occ_comb : occ_combs_dn) { + // for (const auto& vir_comb : vir_combs_dn) { + // AlignedVector temp_det(nword); + // std::memcpy(&temp_det[0], det.data(), sizeof(ulong) * nword); + // for (std::size_t idx = 0; idx < num_singles; ++idx) { + // long occ = rem_occ_dn[occ_comb[idx]]; + // long vir = rem_vir_dn[vir_comb[idx]]; + // excite_det(occ, vir, &temp_det[0]); + // } + // add_det(&temp_det[0]); + // } + // } + + // //-----------------------pCCDSspin test----------------------- } else if (num_singles == 0){ // If num_singles == 0, directly add determinant after pair excitations From e9ea704b4292d7eb230f1dae985bd9090570793f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 7 Jan 2025 15:00:23 -0500 Subject: [PATCH 183/197] add check for nproj to raise valueerror --- pyci/fanci/ap1rogen.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index ad8162c..77faef6 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -59,6 +59,9 @@ def __init__( nparam = nocc * (ham.nbasis - nocc) + (2 * nocc) * (2 * (ham.nbasis - nocc)) + 1 #less params considering we added singles as well nproj = nparam if nproj is None else nproj + if nproj > nparam: + raise ValueError("nproj cannot be greater than the size of the space") + if wfn is None: wfn = pyci.doci_wfn(ham.nbasis, nocc, nocc) wfn.add_excited_dets(1) # add pair excited determinants From 2a78d90de0bc7e19d9d200915634f5defe676b88 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 7 Jan 2025 15:08:59 -0500 Subject: [PATCH 184/197] Remove all print statements, remove the commented extra options for the code --- pyci/src/ap1rogen.cpp | 306 +++++++----------------------------------- 1 file changed, 45 insertions(+), 261 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 286b96c..f8e0f72 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,14 +14,11 @@ * along with PyCI. If not, see . */ #include -#include -#include +// #include #include namespace pyci { -// See apig.cpp for reference - // Constructor with Raw Pointers // call to the base class constructor fullciwfn with the provided parameters @@ -68,7 +65,6 @@ template void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result, long nbasis) { std::vector mask(elems.size()); std::fill(mask.end() - k, mask.end() + k, true); - // std::fill(mask.begin(), mask.begin() + k, true); do { std::vector combination; for (std::size_t i = 0; i < elems.size(); ++i) { @@ -88,7 +84,6 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti std::vector> partitions; for (int p = 0; p <= std::min(e / 2 , max_opairs); ++p) { int s = e - 2 * p; - // //std::cout << "p, s: " << p << " " << s << std::endl; if (max_opairs > 0 && nvir_pairs && p) { if (e % 2 !=0) { // if e is odd partitions.emplace_back(p, s); @@ -109,22 +104,20 @@ std::vector> AP1roGeneralizedSenoObjective::generate_partiti void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& holes, const std::vector& particles, int excitation_order, std::vector& pair_inds, std::vector& single_inds, long nbasis, const NonSingletCI &wfn_) { - //std::cout << "Inside generate_excitations" << std::endl; + AlignedVector> occ_pairs, vir_pairs; AlignedVector occs_up, occs_dn, virs_up, virs_dn, temp_occs; for (int i : holes) { - // //std::cout << "i: " << i << ", nbasis: " << nbasis << std::endl; (i < nbasis ? occs_up : occs_dn).push_back(i); } for (int a : particles) { - // std::cout << "a: " << a << ", nbasis: " << nbasis << std::endl; (a < nbasis ? virs_up : virs_dn).push_back(a); } - //std::cout << "up dn set created\n"; // Create an unordered set for fast lookup of occupied down-orbitals std::unordered_set occ_dn_set(occs_dn.begin(), occs_dn.end()); std::unordered_set virs_set(particles.begin(), particles.end()); + // Generate occ_pairs and vir_pairs for (long i : occs_up) { if (occ_dn_set.find(i + nbasis) != occ_dn_set.end()) { @@ -139,42 +132,19 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector>::size_type max_pairs = occ_pairs.size(); bool nvir_pairs = false; if (max_pairs == vir_pairs.size()) { nvir_pairs = true; - // std::cout << "nvir_pairs: " << nvir_pairs << std::endl; } - // std::cout << "exci order: " << excitation_order << ", max_pairs: " << max_pairs << std::endl; auto partitions = generate_partitions(excitation_order, max_pairs, nvir_pairs); - // std::cout << "Generated partitions" << std::endl; - - // std::cout << "Partitions: " << std::endl; - // for (const auto& pair : partitions) { - // std::cout << "num_pairs: " << pair.first << ", num_singles: " << pair.second << std::endl; - // } for (const auto& pair : partitions) { const auto& num_pairs = pair.first; const auto& num_singles = pair.second; // Step 2: Generate combinations of pairs and singles - // std::cout << "Generating combinations of pairs and singles" << std::endl; - // std::cout << "num_pairs: " << num_pairs << ", num_singles: " << num_singles << std::endl; std::vector> hole_pairs, hole_singles; std::vector> part_pairs, part_singles; @@ -184,20 +154,11 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector 0) { generate_combinations(holes, 2, hole_pairs, nbasis); generate_combinations(particles, 2, part_pairs, nbasis); - // std::cout << "Generated hole_pairs" << std::endl; - - for (const auto& hpair_comb : hole_pairs) { for (const auto& ppair_comb : part_pairs){ - // std::cout << "Handling pair excitations" << std::endl; - // if (used_holes.empty() || std::none_of(hpair_comb.begin(), hpair_comb.end(), - // [&](std::size_t h) { return std::find(used_holes.begin(), used_holes.end(), h) != used_holes.end(); })) { if (!hpair_comb.empty() || !ppair_comb.empty()) { long pindx = wfn_.calc_pindex(hpair_comb[0], ppair_comb[0]); - // std::cout << "Pair index: " << pindx << std::endl; - // std::cout << "hpair_comb: " << hpair_comb[0] << " " << hpair_comb[1] << std::endl; - // std::cout << "ppair_comb: " << ppair_comb[0] << " " << ppair_comb[1] << std::endl; if (pair_inds[0] == -1) { pair_inds.clear(); } @@ -211,7 +172,6 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector 0) { - // std::cout << "Handling single excitations" << std::endl; // Filter holes and particles to exclude used ones std::vector remaining_holes, remaining_particles; @@ -223,16 +183,11 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector::quiet_NaN(); - // std::cout << "Inside init_overlap" << std::endl; - // Initialize your class-specific variables here - // init_Overlap objective for the AP1roGSDspin_sen-o - // std::cout << "wfn_.nocc_up: " << wfn_.nocc_up << "wfn_.nvir_up" << wfn_.nvir_up << std::endl; - // std::cout << "wfn_.nocc: " << wfn_.nocc << "wfn_.nvir" << wfn_.nvir << std::endl; long nocc_up = wfn_.nocc / 2; long nbasis = wfn_.nbasis / 2; - // long nvir_up = nbasis - nocc_up; nparam = nocc_up * (nbasis - nocc_up); //paired-doubles - // std::cout << "nparam (doubles): " << nparam << std::endl; nparam += wfn_.nocc * (wfn_.nbasis - wfn_.nocc); // beta singles - // std::cout << "nparam (doubles + S_alpha + S_beta): " << nparam << std::endl; - - ovlp.resize(nconn); d_ovlp.resize(nconn * nparam); det_exc_param_indx.resize(nconn); - // std::cout << "Size of d_ovlp: " << d_ovlp.size() << std::endl; std::size_t nword = (ulong)wfn_.nword; long nb = wfn_.nbasis; @@ -295,8 +225,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) wfn_.fill_hartreefock_det(nb, nocc, &rdet[0]); const ulong *det = wfn_.det_ptr(idet); ensure_struct_size(det_exc_param_indx, idet+1); - // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; - // std::cout << "\n---------> Det: " ; + bool are_same = true; for (std::size_t k = 0; k < nword; ++k) { // std::cout << det[k] << " "; @@ -318,9 +247,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) word = rdet[iword] ^ det[iword]; //str for excitation hword = word & rdet[iword]; //str for hole pword = word & det[iword]; //str for particle - // std::cout << "\nword: " << word << std::endl; - // std::cout << "hword: " << hword << std::endl; - // std::cout << "pword: " << pword << std::endl; + while(hword){ h = Ctz(hword); p = Ctz(pword); @@ -333,48 +260,22 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) hword &= ~(1UL << h); pword &= ~(1UL << p); - // std::cout << "word: " << word << std::endl; - // std::cout << "hword: " << hword << std::endl; - // std::cout << "pword: " << pword << std::endl; - // std::cout << "h: " << h << ", hole_idx: " << hole_idx << std::endl; - // std::cout << "p: " << p << ", part_idx: " << part_idx << std::endl; + ++nexc; } } - //nexc_list[idet] = nexc; - // std::cout << "nexc: " << nexc << std::endl; - // std::cout << "Ensured struct size" << std::endl; + DetExcParamIndx exc_info; exc_info.det.resize(nword); exc_info.pair_inds.resize(1); exc_info.single_inds.resize(1); exc_info.pair_inds[0] = -1; exc_info.single_inds[0] = -1; - // std::cout << "Assigned first elem as -1 to both pair_inds and single_inds" << std::endl; std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); - // std::cout << "\nCopied det" << std::endl; if (!are_same) generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); - // std::cout << "Generated excitations" << std::endl; - // std::cout << "size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; std::sort(exc_info.pair_inds.begin(), exc_info.pair_inds.end()); std::sort(exc_info.single_inds.begin(), exc_info.single_inds.end()); - // if (idet == 41) { - // std::cout << "Det: "; - // for (std::size_t k = 0; k < nword; ++k) { - // std::cout << det[k] << " "; - // } - // std::cout << std::endl; - // std::cout << "exc_info.pair_inds: "; - // for (const auto& pid : exc_info.pair_inds) { - // std::cout << pid << " "; - // } - // std::cout << std::endl; - // std::cout << "exc_info.single_inds: "; - // for (const auto& sid : exc_info.single_inds) { - // std::cout << sid << " "; - // } - // std::cout << std::endl; - // } + det_exc_param_indx[idet] = exc_info; } } @@ -386,30 +287,24 @@ bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector excitation_inds, const double* x, std::size_t iparam) { - // std::cout << "\nComputing derivative" << std::endl; - - //--------------------------------------------------------- - // double reduced_permanent = 0.0; - // // Check if excitation_inds is empty, first element is -1 - // if (excitation_inds[0] == -1) {return 0.0;} - - - // // check if iparam is within excitation_inds - // auto it = std::find(excitation_inds.begin(), excitation_inds.end(), iparam); - - // // If iparam is not in excitation_inds, return 0 - // if (it == excitation_inds.end()) {return 0.0;} - - // if (excitation_inds.size() == 1 && excitation_inds[0] == static_cast(iparam)) { - // reduced_permanent = 1.0; - // return reduced_permanent; - // } - // // Modify x such that it excludes the parameter at index iparam - // std::vector modified_x(x, x + nparam); - // modified_x[iparam] = 1.0; - - // // std::cout << "Modified x: "; - // // for (const auto& rid : modified_x) { - // // std::cout << rid << " "; - // // } - // // std::cout << std::endl; - // permanent_calculation(excitation_inds, modified_x.data(), reduced_permanent); - - // if (std::isnan(reduced_permanent) || std::isinf(reduced_permanent)) { - // std::cerr << "Error: reduced_permanent is invalid (NaN or Inf)" << std::endl; - // return 0.0; - // } - // // std::cout << "\nreduced_permanent: " << reduced_permanent << std::endl; - // return reduced_permanent; - //--------------------------------------------------------- + // Check if excitation_inds is empty or first element is -1 + if (excitation_inds.empty() || excitation_inds[0] == -1) {return 0.0;} + + // Check if iparam is within excitation_inds + auto it = std::lower_bound(excitation_inds.begin(), excitation_inds.end(), iparam); + if (it == excitation_inds.end()) {return 0.0;} + + std::size_t n = static_cast(std::sqrt(excitation_inds.size())); if (n == 0) {return 0.0;} if (n == 1) { @@ -479,13 +343,15 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector double derivative = 0.0; std::size_t subset_count = 1UL << n; // 2^n subsets - // Derive i and j from iparam - std::size_t i = iparam / n; - std::size_t j = iparam % n; + //Find the position of iparam in excitation_inds + std::size_t pos = std::distance(excitation_inds.begin(), it); + // Derive i and j from pos of iparam + std::size_t i = pos / n; + std::size_t j = pos % n; for (std::size_t subset = 0; subset < subset_count; ++subset) { // skip subsets where column j is not included - if ((subset & (1UL << j))) continue; + if (!(subset & (1UL << j))) continue; double rowsumprod = 1.0; @@ -506,8 +372,12 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector int subset_parity = (__builtin_popcount(subset) % 2 == 0) ? 1 : -1; derivative += rowsumprod * subset_parity; } - // Final adjustment for the excluded row i + // Final adjustment for the parity of the matrix derivative *= ((n % 2 == 1) ? -1 : 1); + + if (std::isnan(derivative) || std::isinf(derivative)) { + std::cerr << "Error: permanent is invalid (NaN or Inf)" << std::endl; + } return derivative; } @@ -515,26 +385,12 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { - // std::cout << "\nInside overlap" << std::endl; - // std::cout << "ndet: " << ndet << std::endl; p_permanent.resize(nconn); s_permanent.resize(nconn); - // std::cout << "Input params: "; - // for (std::size_t i = 0; i < nparam; ++i) { - // std::cout << x[i] << " "; - // } - // std::cout << std::endl; - // std::cout << "Ovlp: " ; - // for (std::size_t i = 0; i < ndet; ++i) { - // std::cout << y[i] << " "; - // } - // std::cout << std::endl; + for (std::size_t idet = 0; idet != ndet; ++idet) { - // std::cout << "Size of det_exc_param_indx: " << det_exc_param_indx.size() << std::endl; if (idet < det_exc_param_indx.size()) { - // std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; - // Access the excitation parameter indices const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; double pair_permanent = 1.0; @@ -543,37 +399,23 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d if (exc_info.pair_inds[0] != -1) { if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; - // pair_permanent = 0.0; // Default to 0 or another appropriate fallback } } if (exc_info.single_inds[0] != -1) { if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; - // single_permanent = 0.0; // Default value on error } } p_permanent[idet] = pair_permanent; s_permanent[idet] = single_permanent; - // std::cout << "exc_info.pair_inds, x[idx]: "; - // for (const auto& pid : exc_info.pair_inds) { - // std::cout << pid << ", " << x[pid] << " "; - // } - // std::cout << "\nexc_info.single_inds: "; - // for (const auto& sid : exc_info.single_inds) { - // std::cout << sid << " "; - // } - // std::cout << "\npair_permanent: " << pair_permanent << std::endl; - // std::cout << "single_permanent: " << single_permanent << std::endl; - if (y != nullptr && idet < ndet) { y[idet] = pair_permanent * single_permanent; } else { std::cerr << "y is nullptr or idet is out of bounds" << std::endl; } - // std::cout << "y[" << idet << "]: " << y[idet] << std::endl; } else { std::cout << "idet" << idet << " not found in storage" << std::endl; y[idet] = 0.0; @@ -584,107 +426,49 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d } -// void AP1roGeneralizedSenoObjective::d_overlap(const NonSingletCI &wfn_, const size_t ndet, const double *x, double *y){ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - // std::cout << "\n------>Computing d_overlap" << std::endl; - // std::cout << "Size of s_permanent: " << s_permanent.size() << std::endl; - // std::cout << "Size of p_permanent: " << p_permanent.size() << std::endl; - // std::cout << "ndet: " << ndet << std::endl; - // const double epsilon = 1.0e-7; - for (std::size_t idet = 0; idet != ndet; ++idet) { + for (std::size_t idet = 0; idet != ndet; ++idet) { // Ensure we have the excitation parameters for this determinant if (idet < det_exc_param_indx.size()) { const DetExcParamIndx exc_info = det_exc_param_indx[idet]; double pair_permanent = 1.0; double single_permanent = 1.0; if (idet < s_permanent.size() && idet < p_permanent.size()) { - // std::cout << "\n\nidet: " << idet << " found in storage" << std::endl; pair_permanent = p_permanent[idet]; single_permanent = s_permanent[idet]; } - else { - // std::cout << "\nidet: " << idet << " not found in storage" << std::endl; - if (exc_info.pair_inds[0] != -1) { - if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { - std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; - // pair_permanent = 0.0; // Default to 0 or another appropriate fallback - } - } - - if (exc_info.single_inds[0] != -1) { - if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { - std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; - // single_permanent = 0.0; // Default value on error - } - } + // else { + // if (exc_info.pair_inds[0] != -1) { + // if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { + // std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; + // } + // } + + // if (exc_info.single_inds[0] != -1) { + // if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { + // std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; + // } + // } - } - - // std::cout << "\npair_permanent: " << pair_permanent << std::endl; - // std::cout << "single_permanent: " << single_permanent << std::endl; - + // } for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - // std::cout << "computing deriv of idet: " << idet << " wrt iparam: " << iparam << std::endl; - // std::cout << "nparam: " << nparam << std::endl; - // std::cout << "Size(pair_inds): " << exc_info.pair_inds.size() << std::endl; - // std::cout << "Size(single_inds): " << exc_info.single_inds.size() << std::endl; - // std::cout << "size of y array: " << &y.size() << std::endl; - //-----Numerical Derivative Calculation--------------------------------------- - // double pair_plus = 0.0; - // double single_plus = 0.0; - // std::vector x_perturb(x, x + nparam); - // x_perturb[iparam] += epsilon; - // permanent_calculation(exc_info.pair_inds, x_perturb.data(), pair_plus); - // permanent_calculation(exc_info.single_inds, x_perturb.data(), single_plus); - - // x_perturb[iparam] -= 2 * epsilon; - // double pair_minus = 0.0; - // double single_minus = 0.0; - // permanent_calculation(exc_info.pair_inds, x_perturb.data(), pair_minus); - // permanent_calculation(exc_info.single_inds, x_perturb.data(), single_minus); - - // double dpair = 0.0; - // double dsingle = 0.0; - // dpair = (pair_plus - pair_minus) / (2 * epsilon); - // dsingle = (single_plus - single_minus) / (2 * epsilon); - //---------------------------------------------------------------------------- - // std::cout << "exc_info.single_inds: "; - // for (const auto& sid : exc_info.single_inds) { - // std::cout << sid << " "; - // } - // std::cout << std::endl; - // std::cout << "exc_info.pair_inds: "; - // for (const auto& pid : exc_info.pair_inds) { - // std::cout << pid << " "; - // } - // std::cout << std::endl; double dpair = 0.0; double dsingle = 0.0; if (exc_info.single_inds[0] != -1) { dsingle = compute_derivative(exc_info.single_inds, x, iparam); - // std::cout << "dsingle: " << dsingle << std::endl; } - // std::cout << "dsingle: " << dsingle << std::endl; if (exc_info.pair_inds[0] != -1) { dpair = compute_derivative(exc_info.pair_inds, x, iparam); - // std::cout << "dpair: " << dpair << std::endl; } - // std::cout << "dpair: " << dpair << std::endl; - - - // std::cout << "dpair: " << dpair << std::endl; - // std::cout << "dsingle: " << dsingle << "\n" ; - // std::cout << "deriv index:" << idet * nparam + iparam << std::endl; - // std::cout << "final deriv: " << dpair * single_permanent + dsingle * pair_permanent << " wrt iparam: " << iparam << std::endl; - + // std::cout << "dpair: " << dpair << ", dsingle: " << dsingle << std::endl; + std::cout << "single_permanent: " << single_permanent << ", pair_permanent: " << pair_permanent << std::endl; + std::cout << "idet: " << idet << " deriv: " << dpair * single_permanent + dsingle * pair_permanent << std::endl; y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; } } else { - // std::cout << "Determinant " << idet << " not found in det_map" << std::endl; - // Set all derivatives to zero if determinant is not found for (std::size_t iparam = 0; iparam < nparam; ++iparam) { y[ndet * iparam + idet] = 0.0; } From dcfc76299466fc51622fdc17e9ed08dd178fa7dc Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 7 Jan 2025 15:12:36 -0500 Subject: [PATCH 185/197] Add a check for nocc, raise invalid_argument if it is odd. Add description of add_excited_dets --- pyci/src/nonsingletci.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index e190db1..dcd971d 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -553,9 +553,12 @@ void NonSingletCI::add_excited_dets(const ulong *rdet, const long e){ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) const { /* GenCIWfn build using FullCIWfn initializes the OneSpinWfn with nbasis * 2, so we are calling it nb2 here*/ long nb = nb2/2; - // FIXME: The code is assuming nocc is even - long nocc_beta = nocc/2; //std::min(nocc, nb); - long nocc_alpha = nocc/2; //std::min(0L, nocc - nb); + // Ensure nocc is even + if (nocc % 2 != 0) { + throw std::invalid_argument("Number of occupied orbitals (nocc) must be even."); + } + long nocc_beta = nocc / 2; + long nocc_alpha = nocc / 2; // long num_ulongs = (nb2 + Size() - 1) / Size(); @@ -583,16 +586,28 @@ void NonSingletCI::fill_hartreefock_det(long nb2, long nocc, ulong *det) const { // std::cout << det[i] << " "; // } // std::cout << std::endl; - } + + +/** + * @brief Adds excited determinants to the current wavefunction. + * + * This function generates excited determinants based on the given excitation level + * and reference determinant. If no reference determinant is provided, it uses the + * Hartree-Fock determinant. + * + * @param exc The excitation level. + * @param ref The reference determinant as a pybind11 object. If none, Hartree-Fock determinant is used. + * @return The number of new determinants added. + */ long NonSingletCI::py_add_excited_dets(const long exc, const pybind11::object ref) { AlignedVector v_ref; ulong *ptr; if (ref.is(pybind11::none())) { v_ref.resize(nword); ptr = &v_ref[0]; - fill_hartreefock_det(nbasis,nocc, ptr); + fill_hartreefock_det(nbasis, nocc, ptr); } else { ptr = reinterpret_cast(ref.cast>().request().ptr); } From 012c169e0c2cd0dc917b1eae8ea5503c797fa77f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 9 Jan 2025 11:25:30 -0500 Subject: [PATCH 186/197] removed unused variables --- pyci/src/sparseop.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 38685c1..381786e 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -539,14 +539,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long ioffset, koffset, sign_up; long nbasis = wfn.nbasis / 2; long n1 = nbasis; - long n1 = nbasis; long n2 = n1 * n1; long n3 = n1 * n2; double val1, val2 = 0.0; const ulong *rdet_up = wfn.det_ptr(idet); - const ulong *rdet_dn = rdet_up + nbasis; - std::cout << "rdet_up: " << *rdet_up << std::endl; - ulong *det_dn = det_up + nbasis; std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); fill_occs(wfn.nword, rdet_up, occs); From 53a17e5e3b51e50ebb2592b493c2aac4d15f2ec2 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 9 Jan 2025 11:30:53 -0500 Subject: [PATCH 187/197] comment print statements --- pyci/src/ap1rogen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index f8e0f72..0e5bbd6 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -463,8 +463,8 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x dpair = compute_derivative(exc_info.pair_inds, x, iparam); } // std::cout << "dpair: " << dpair << ", dsingle: " << dsingle << std::endl; - std::cout << "single_permanent: " << single_permanent << ", pair_permanent: " << pair_permanent << std::endl; - std::cout << "idet: " << idet << " deriv: " << dpair * single_permanent + dsingle * pair_permanent << std::endl; + // std::cout << "single_permanent: " << single_permanent << ", pair_permanent: " << pair_permanent << std::endl; + // std::cout << "idet: " << idet << " deriv: " << dpair * single_permanent + dsingle * pair_permanent << std::endl; y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; } } From 485fdec71a39ac52c7fa790d9cce0c77285a228c Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 14 Jan 2025 11:54:05 -0500 Subject: [PATCH 188/197] Fix the kk index to occ_up orbitals in the second alpha --> alpha excitation block --- pyci/src/sparseop.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 381786e..0f07f6d 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -581,8 +581,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; - + val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; @@ -618,9 +617,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jj = virs_up[j]; } - // loop over spin-down occupied indices - for (k = 0; k < nocc_dn; ++k) { - kk = occs_dn[k]; + // loop over spin-up occupied indices + for (k = 0; k < nocc_up; ++k) { + kk = occs_up[k]; koffset = ioffset + n2 * kk; // second excitation: alpha -> alpha for (l = j + 1; l < nvir_up; ++l) { From 27c3df793cb6ecb3f0ae003efbc45d074152f3f7 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 14 Jan 2025 18:20:19 -0500 Subject: [PATCH 189/197] Convert spatial to spin representation of ham, called those as one_ao and two_ao; update the add_row function by using this generalized hamiltonian --- pyci/include/pyci.h | 4 +-- pyci/src/binding.cpp | 20 +++++++++++ pyci/src/sparseop.cpp | 82 ++++++++++++++----------------------------- pyci/src/squantop.cpp | 39 ++++++++++++++++++-- 4 files changed, 86 insertions(+), 59 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 6c4df71..902c7e0 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -282,8 +282,8 @@ double py_compute_enpt2(const SQuantOp &, const WfnType &, const Array, struct SQuantOp final { public: long nbasis; - double ecore, *one_mo, *two_mo, *h, *v, *w; - Array one_mo_array, two_mo_array, h_array, v_array, w_array; + double ecore, *one_mo, *two_mo, *one_ao, *two_ao, *h, *v, *w; + Array one_mo_array, two_mo_array, one_ao_array, two_ao_array, h_array, v_array, w_array; SQuantOp(void); diff --git a/pyci/src/binding.cpp b/pyci/src/binding.cpp index d0568a5..ede9c45 100644 --- a/pyci/src/binding.cpp +++ b/pyci/src/binding.cpp @@ -127,6 +127,26 @@ two_mo : numpy.ndarray )"""); +secondquant_op.def_readonly("one_ao", &SQuantOp::one_ao_array, R"""( +One-particle atomic integral array. + +Returns +------- +one_mo : numpy.ndarray + One-particle atomic integral array. + +)"""); + +secondquant_op.def_readonly("two_ao", &SQuantOp::two_ao_array, R"""( +Two-particle atomic integral array. + +Returns +------- +two_mo : numpy.ndarray + Two-particle atomic integral array. + +)"""); + secondquant_op.def_readonly("h", &SQuantOp::h_array, R"""( Seniority-zero one-particle molecular integral array. diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 0f07f6d..5943e31 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -535,12 +535,13 @@ void SparseOp::add_row(const SQuantOp &ham, const GenCIWfn &wfn, const long idet void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long idet, ulong *det_up, long *occs, long *virs) { - long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); - long ioffset, koffset, sign_up; - long nbasis = wfn.nbasis / 2; - long n1 = nbasis; + long n = wfn.nbasis / 2; + long n1 = wfn.nbasis; long n2 = n1 * n1; long n3 = n1 * n2; + + long i, j, k, l, ii, jj, kk, ll, jdet, jmin = symmetric ? idet : Max(); + long ioffset, koffset, sign_up; double val1, val2 = 0.0; const ulong *rdet_up = wfn.det_ptr(idet); std::memcpy(det_up, rdet_up, sizeof(ulong) * wfn.nword); @@ -548,15 +549,15 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long fill_occs(wfn.nword, rdet_up, occs); fill_virs(wfn.nword, wfn.nbasis, rdet_up, virs); - long nocc_up = __builtin_popcount(*det_up & ((1 << nbasis) - 1)); + long nocc_up = __builtin_popcount(*det_up & ((1 << n) - 1)); long nocc_dn = wfn.nocc - nocc_up; - long nvir_up = nbasis - nocc_up; - long nvir_dn = nbasis - nocc_dn; + long nvir_up = n - nocc_up; + long nvir_dn = n - nocc_dn; long nvir = nvir_up + nvir_dn; long *virs_up = virs; long *virs_dn = nullptr; for (long i = 0; i < nvir; ++i) { - if (virs[i] >= nbasis) { + if (virs[i] >= n) { virs_dn = &virs[i]; break; } @@ -564,7 +565,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long *occs_up = occs; long *occs_dn = nullptr; for (long i = 0; i < wfn.nocc; ++i) { - if (occs[i] >= nbasis) { + if (occs[i] >= n) { occs_dn = &occs[i]; break; } @@ -577,16 +578,15 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long ioffset = n3 * ii; // compute part of diagonal matrix element - val2 += ham.one_mo[(n1 + 1) * ii]; + val2 += ham.one_ao[(n1 + 1) * ii]; for (k = i + 1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; + val2 += ham.two_ao[koffset + n1 * ii + kk] - ham.two_ao[koffset + n1 * kk + ii]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - if (kk >= nbasis) kk -= nbasis; - val2 += ham.two_mo[ioffset + n2 * kk + n1 * ii + kk]; + val2 += ham.two_ao[ioffset + n2 * kk + n1 * ii + kk]; } // first excitation: alpha -> alpha for (j = 0; j < nvir_up; ++j) { @@ -597,24 +597,19 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - if (jj >= nbasis) jj -= nbasis; - // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; - // compute the matrix element - val1 = ham.one_mo[n1 * ii + jj]; + val1 = ham.one_ao[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + val1 += ham.two_ao[koffset + n1 * jj + kk] - ham.two_ao[koffset + n1 * kk + jj]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - if (kk >= nbasis) kk -= nbasis; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + val1 += ham.two_ao[ioffset + n2 * kk + n1 * jj + kk]; } append(data, sign_up * val1); append(indices, jdet); - jj = virs_up[j]; } // loop over spin-up occupied indices @@ -631,8 +626,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long counter += 1; // add the aaaa --> aaaa matrix element append(data, phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up) * - (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + (ham.two_ao[koffset + n1 * jj + ll] - + ham.two_ao[koffset + n1 * ll + jj])); append(indices, jdet); } excite_det(ll, kk, det_up); @@ -642,7 +637,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-down occupied indices for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { @@ -652,20 +646,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - // std::cout << "\nii, kk, jj, ll: " << ii << ", " << kk << ", " << jj << ", " << ll << std::endl; - // std::cout << "ndet_up: " << *det_up << std::endl; - // double sign = phase_single_det(wfn.nword, kk, ll, rdet_up); double sign = phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up); - if (jj >= nbasis) jj -= nbasis; - if (kk >= nbasis) kk -= nbasis; - if (ll >= nbasis) ll -= nbasis; counter += 1; - // append(data, sign_up * sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); - append(data, sign * ham.two_mo[ioffset + n2 * kk + n1 * jj + ll]); + append(data, sign * ham.two_ao[ioffset + n2 * kk + n1 * jj + ll]); append(indices, jdet); - ll = virs_dn[l]; - kk = occs_dn[k]; - jj = virs_up[j]; } excite_det(ll, kk, det_up); excite_det(ll, kk, det_up); @@ -678,15 +662,14 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // loop over spin-down occupied indices for (i = 0; i < nocc_dn; ++i) { ii = occs_dn[i]; - if (ii >= nbasis) ii -= nbasis; ioffset = n3 * ii; // compute part of diagonal matrix element - val2 += ham.one_mo[(n1 + 1) * ii]; + val2 += ham.one_ao[(n1 + 1) * ii]; for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; - if (kk >= nbasis) kk -= nbasis; + // if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; - val2 += ham.two_mo[koffset + n1 * ii + kk] - ham.two_mo[koffset + n1 * kk + ii]; + val2 += ham.two_ao[koffset + n1 * ii + kk] - ham.two_ao[koffset + n1 * kk + ii]; } ii = occs_dn[i]; @@ -697,23 +680,17 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { - if (ii >= nbasis) ii -= nbasis; - if (jj >= nbasis) jj -= nbasis; - // std::cout << "ndet_up: " << *det_up << std::endl; counter += 1; - val1 = ham.one_mo[n1 * ii + jj]; + val1 = ham.one_ao[n1 * ii + jj]; for (k = 0; k < nocc_up; ++k) { kk = occs_up[k]; - val1 += ham.two_mo[ioffset + n2 * kk + n1 * jj + kk]; + val1 += ham.two_ao[ioffset + n2 * kk + n1 * jj + kk]; } for (k = 0; k < nocc_dn; ++k) { kk = occs_dn[k]; - if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; - val1 += ham.two_mo[koffset + n1 * jj + kk] - ham.two_mo[koffset + n1 * kk + jj]; + val1 += ham.two_ao[koffset + n1 * jj + kk] - ham.two_ao[koffset + n1 * kk + jj]; } - jj = virs_dn[j]; - ii = occs_dn[i]; append(data, phase_single_det(wfn.nword, ii, jj, rdet_up) * val1); append(indices, jdet); @@ -721,7 +698,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // second excitation: beta -> beta for (k = i + 1; k < nocc_dn; ++k) { kk = occs_dn[k]; - if (kk >= nbasis) kk -= nbasis; koffset = ioffset + n2 * kk; kk = occs_dn[k]; for (l = j + 1; l < nvir_dn; ++l) { @@ -732,14 +708,10 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // check if excited determinant is in wfn if ((jdet != -1) && (jdet < jmin) && (jdet < ncol)) { double sign = phase_double_det(wfn.nword, ii, kk, jj, ll, rdet_up); - if (kk >= nbasis) kk -= nbasis; - if (ll >= nbasis) ll -= nbasis; counter += 1; - append(data, sign * (ham.two_mo[koffset + n1 * jj + ll] - - ham.two_mo[koffset + n1 * ll + jj])); + append(data, sign * (ham.two_ao[koffset + n1 * jj + ll] - + ham.two_ao[koffset + n1 * ll + jj])); append(indices, jdet); - ll = virs_dn[l]; - kk = occs_dn[k]; } excite_det(ll, kk, det_up); } diff --git a/pyci/src/squantop.cpp b/pyci/src/squantop.cpp index 511274b..48ef0ba 100644 --- a/pyci/src/squantop.cpp +++ b/pyci/src/squantop.cpp @@ -25,17 +25,21 @@ SQuantOp::SQuantOp(void) { } SQuantOp::SQuantOp(const SQuantOp &ham) - : nbasis(ham.nbasis), ecore(ham.ecore), one_mo(ham.one_mo), two_mo(ham.two_mo), h(ham.h), + : nbasis(ham.nbasis), ecore(ham.ecore), one_mo(ham.one_mo), two_mo(ham.two_mo), + one_ao(ham.one_ao), two_ao(ham.two_ao), h(ham.h), v(ham.v), w(ham.w), one_mo_array(ham.one_mo_array), two_mo_array(ham.two_mo_array), + one_ao_array(ham.one_ao_array), two_ao_array(ham.two_ao_array), h_array(ham.h_array), v_array(ham.v_array), w_array(ham.w_array) { } SQuantOp::SQuantOp(SQuantOp &&ham) noexcept : nbasis(std::exchange(ham.nbasis, 0)), ecore(std::exchange(ham.ecore, 0.0)), one_mo(std::exchange(ham.one_mo, nullptr)), two_mo(std::exchange(ham.two_mo, nullptr)), + one_ao(std::exchange(ham.one_ao, nullptr)), two_ao(std::exchange(ham.two_ao, nullptr)), h(std::exchange(ham.h, nullptr)), v(std::exchange(ham.v, nullptr)), w(std::exchange(ham.w, nullptr)), one_mo_array(std::move(ham.one_mo_array)), - two_mo_array(std::move(ham.two_mo_array)), h_array(std::move(ham.h_array)), + two_mo_array(std::move(ham.two_mo_array)), one_ao_array(std::move(ham.one_ao_array)), + two_ao_array(std::move(ham.two_ao_array)), h_array(std::move(ham.h_array)), v_array(std::move(ham.v_array)), w_array(std::move(ham.w_array)) { } @@ -158,6 +162,37 @@ SQuantOp::SQuantOp(const std::string &filename) { two_mo[i * n3 + j * n2 + i * n1 + j] * 2 - two_mo[i * n3 + j * n2 + j * n1 + i]; } } + + // Spatial to spin conversion (n * n) to (2n * 2n) + long m1 = n1 *2; + long m2 = m1 * m1; + long m3 = m1 * m2; + + one_ao_array = Array({m1, m1}); + two_ao_array = Array({m1, m1, m1, m1}); + one_ao = reinterpret_cast(one_ao_array.request().ptr); + two_ao = reinterpret_cast(two_ao_array.request().ptr); + + for (long i = 0; i < n1; ++i) { + for (long j = 0; j < n1; ++j) { + one_ao[i * m1 + j] = one_mo[i * n1 + j]; + one_ao[(i + n1) * m1 + (j + n1)] = one_mo[i * n1 + j]; + } + } + + for (long i = 0; i < n1; ++i) { + for (long j = 0; j < n1; ++j) { + for (long k = 0; k < n1; ++k) { + for (long l = 0; l < n1; ++l) { + two_ao[i * m3 + j * m2 + k * m1 + l] = two_mo[i * n1 * n1 * n1 + j * n1 * n1 + k * n1 + l]; + two_ao[(i + n1) * m3 + (j + n1) * m2 + (k + n1) * m1 + (l + n1)] = two_mo[i * n1 * n1 * n1 + j * n1 * n1 + k * n1 + l]; + two_ao[i * m3 + (j + n1) * m2 + k * m1 + (l + n1)] = two_mo[i * n1 * n1 * n1 + j * n1 * n1 + k * n1 + l]; + two_ao[(i + n1) * m3 + j * m2 + (k + n1) * m1 + l] = two_mo[i * n1 * n1 * n1 + j * n1 * n1 + k * n1 + l]; + } + } + } + } + } SQuantOp::SQuantOp(const double e, const Array mo1, const Array mo2) From 6ab3bc9d262b497b631d3a7c2bc43b1ef693e687 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Thu, 16 Jan 2025 22:31:14 -0500 Subject: [PATCH 190/197] Changed order of params by considering those corresponding to singles are listed first; now initializing a nonsingletciwfn with FullCI wfn filled with excitation order 0 - ensuring HF, 1,2,3 and 4; Introduced sign_excite and sign_swap function to calculate the sign resulting from the ordering of the annihilation and creation operators used to generate the excited configurations; set first element of overlap to 1 corresponding to HF; if excitation_inds = -1 meaning empty then set the single and double permanents to zero --- pyci/fanci/ap1rogen.py | 22 ++++-- pyci/fanci/fanci.py | 20 +++++ pyci/include/pyci.h | 12 ++- pyci/src/ap1rogen.cpp | 150 ++++++++++++++++++++++++++++++++++---- pyci/src/nonsingletci.cpp | 7 +- 5 files changed, 189 insertions(+), 22 deletions(-) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index 77faef6..bb7c1f7 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -59,13 +59,20 @@ def __init__( nparam = nocc * (ham.nbasis - nocc) + (2 * nocc) * (2 * (ham.nbasis - nocc)) + 1 #less params considering we added singles as well nproj = nparam if nproj is None else nproj - if nproj > nparam: - raise ValueError("nproj cannot be greater than the size of the space") + # if nproj > nparam: + # raise ValueError("nproj cannot be greater than the size of the space") if wfn is None: - wfn = pyci.doci_wfn(ham.nbasis, nocc, nocc) - wfn.add_excited_dets(1) # add pair excited determinants - wfn = pyci.fullci_wfn(wfn) + # wfn = pyci.doci_wfn(ham.nbasis, nocc, nocc) + # wfn.add_excited_dets(1) # add pair excited determinants + wfn = pyci.fullci_wfn(ham.nbasis, nocc, nocc) + # exc=0 ensures addint HF determinannt first + pyci.add_excitations(wfn,0,1,2,3,4) + print("Printing FCI wfn dets: ") + for sd in (wfn.to_occ_array()): + sd = np.array(sd) + print(np.concatenate((sd[0],sd[1]+ham.nbasis))) + wfn = pyci.nonsingletci_wfn(wfn) elif not isinstance(wfn, pyci.nonsingletci_wfn): @@ -76,6 +83,11 @@ def __init__( # Initialize base class FanCI.__init__(self, ham, wfn, nproj, nparam, **kwargs) + print("\n\nPrinting nonsingletci wfn dets: ") + for sd in (self._sspace): + print(sd) + # sd = np.array(sd) + # print(np.concatenate((sd[0],sd[1]+ham.nbasis))) # Assign reference occupations #ref_occs_up = np.arange(nocc_up, dtype=pyci.c_long) diff --git a/pyci/fanci/fanci.py b/pyci/fanci/fanci.py index 43c5575..1052693 100644 --- a/pyci/fanci/fanci.py +++ b/pyci/fanci/fanci.py @@ -13,6 +13,8 @@ from scipy.optimize import OptimizeResult, least_squares, root +from scipy.optimize import minimize + import pyci @@ -207,7 +209,21 @@ def __init__( # Compute arrays of occupations sspace = wfn.to_occ_array() + + # if type(wfn).__name__ == "nonsingletci_wfn": + # pspace = sspace[np.r_[0:13, 21:29, 37:45, 53:60, 66:72, 75:77, 81, 99:102, 104:108, 109:117, 126:129, 131:135, + # 136:144, 171:183, 189:195, 201:206, 209, 221:224, 225:231, 2316:239, 240:246, 261:267, + # 273:278, 282:286, 288, 300:302, 303:309, 314:316, 317:323, 337:344, 348:352, 356:359, + # 365:369, 371:375, 381:384, 388:391, 393:395, 400:403, 405:408, 413:416, 418:420, 422, + # 424:426, 427, 430]] + # # nproj = len(pspace) + # else: pspace = sspace[:nproj] + print("len(sspace), len(pspace): ", len(sspace), len(pspace)) + # dec_sspace = wfn.to_det_array() + # print("Printing sspace") + # for dec, bin in zip(dec_sspace, sspace): + # print("\n", dec, bin) # Assign attributes to instance self._nequation = nequation @@ -274,6 +290,10 @@ def optimize( elif mode == "root": opt_args = f, x0 optimizer = root + # FIXME: For BFGS to work, objective function must return a scalar value + elif mode == "bfgs": + opt_args = f, x0 + optimizer = minimize else: raise ValueError("invalid mode parameter") diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 902c7e0..0975d94 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -618,6 +618,7 @@ struct DetExcParamIndx { AlignedVector det; std::vector pair_inds; std::vector single_inds; + int sign; }; // Inline utility function for resizing DetExcParamIndx Object @@ -933,6 +934,13 @@ class AP1roGeneralizedSenoObjective : public Objective { const std::vector& , int , std::vector& , std::vector&, long, const NonSingletCI &); + // Return the signature of applying annihilators then creators to the Slater determinant. + int sign_swap(AlignedVector , long, long); + + // Return the sign of the Slater determinant after applying excitation operators. + int sign_excite(AlignedVector , const std::vector& , const std::vector& ); + + // Initializer for {d_,}overlap variables void init_overlap(const NonSingletCI &); @@ -943,10 +951,10 @@ class AP1roGeneralizedSenoObjective : public Objective { double compute_derivative(const std::vector , const double*, std::size_t); // Overlap function - virtual void overlap(const std::size_t, const double *x, double *y); + virtual void overlap(const std::size_t, const double*, double*); // Overlap gradient function - virtual void d_overlap(const size_t, const double *x, double *y); + virtual void d_overlap(const size_t, const double*, double*); }; } // namespace pyci diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 0e5bbd6..c142d8e 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -106,7 +106,7 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector& single_inds, long nbasis, const NonSingletCI &wfn_) { AlignedVector> occ_pairs, vir_pairs; - AlignedVector occs_up, occs_dn, virs_up, virs_dn, temp_occs; + AlignedVector occs_up, occs_dn, virs_up, virs_dn; // , temp_occs; for (int i : holes) { (i < nbasis ? occs_up : occs_dn).push_back(i); } @@ -118,15 +118,15 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector occ_dn_set(occs_dn.begin(), occs_dn.end()); std::unordered_set virs_set(particles.begin(), particles.end()); - // Generate occ_pairs and vir_pairs + // Generate occ_pairs for (long i : occs_up) { if (occ_dn_set.find(i + nbasis) != occ_dn_set.end()) { occ_pairs.push_back({i, i + nbasis}); - temp_occs.push_back(i); - temp_occs.push_back(i + nbasis); + // temp_occs.push_back(i); + // temp_occs.push_back(i + nbasis); } } - // std::cout << "occ_pairs created\n"; + // Generate vir_pairs for (long a : particles) { if (virs_set.find(a + nbasis) != virs_set.end()) { vir_pairs.push_back({a, a + nbasis}); @@ -159,6 +159,8 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector sd, long pos_current, long pos_future){ + // Return the signature of applying annihilators then creators to the Slater determinant. + if (pos_current < 0 || pos_future < 0) { + throw std::invalid_argument("The current and future positions must be positive integers."); + } + + // if (!((sd >> pos_current) & 1)) { + if (!((sd[pos_current / Size()] >> (pos_current % Size())) & 1)) { + throw std::invalid_argument("Given orbital is not occupied in the Slater determinant."); + } + + int num_trans = 0; + if (pos_current < pos_future) { + // Count the number of set bits between pos_current and pos + for (long i = pos_current + 1; i <= pos_future; ++i) { + if ((sd[i / Size()] >> (i % Size())) & 1) { + ++num_trans; + } + } + } else { + for (long i = pos_future; i < pos_current; ++i) { + if ((sd[i / Size()] >> (i % Size())) & 1) { + ++num_trans; + } + } + } + + // if (pos_current < pos_future) { + // // Count the number of set bits between pos_current and pos_future + // num_trans = std::bitset(sd >> (pos_current + 1)).count() - std::bitset(sd >> (pos_future + 1)).count(); + // } else { + // // Count the number of set bits between pos_future and pos_current + // num_trans = std::bitset(sd >> pos_future).count() - std::bitset(sd >> pos_current).count(); + // } + + return (num_trans % 2 == 0) ? 1 : -1; + +} + +int AP1roGeneralizedSenoObjective::sign_excite(AlignedVector sd, + const std::vector& annihilators, const std::vector& creators) { + // Return the sign of the Slater determinant after applying excitation operators. + int sign = 1; + for (std::size_t i : annihilators) { + // if (!((sd >> i) & 1)) { + if (!((sd[i / Size()] >> (i % Size())) & 1)) { + //print sd + std::cout << "Annihilator: " << i << std::endl; + for (int k = 0; k < sd.size(); ++k) { + std::cout << sd[k] << " "; + } + std::cout << std::endl; + throw std::invalid_argument("Given Slater determinant cannot be excited using the given creators and annihilators."); + } + sign *= sign_swap(sd, i, 0); + // sd = sd & ~(1UL << i); // annihilate ith orbital + sd[i / Size()] &= ~(1UL << (i % Size())); // annihilate ith orbital + } + + for (std::size_t a : creators) { + // sd = sd | (1UL << a); // create ath orbital + sd[a / Size()] |= (1UL << (a % Size())); // create ath orbital + // if (sd == 0) { + if (!((sd[a / Size()] >> (a % Size())) & 1)) { + //print sd + std::cout << "Creator: " << a << std::endl; + for (int k = 0; k < sd.size(); ++k) { + std::cout << sd[k] << " "; + } + std::cout << std::endl; + throw std::invalid_argument("Given Slater determinant cannot be excited using the given creators and annihilators."); + } + sign *= sign_swap(sd, a, 0); + } + return sign; +} + + + void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) { long nocc_up = wfn_.nocc / 2; @@ -226,6 +310,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) const ulong *det = wfn_.det_ptr(idet); ensure_struct_size(det_exc_param_indx, idet+1); + // Check if given det is the same as the reference det bool are_same = true; for (std::size_t k = 0; k < nword; ++k) { // std::cout << det[k] << " "; @@ -264,18 +349,33 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) ++nexc; } } - + // New container for the excitation information DetExcParamIndx exc_info; exc_info.det.resize(nword); exc_info.pair_inds.resize(1); exc_info.single_inds.resize(1); + + // Default values for indices exc_info.pair_inds[0] = -1; exc_info.single_inds[0] = -1; + std::memcpy(&exc_info.det[0], &det[0], sizeof(ulong) * nword); + + // Generate excitations if the given det is not the same as the reference det if (!are_same) generate_excitations(holes, particles, nexc, exc_info.pair_inds, exc_info.single_inds, nbasis, wfn_); + + // Sort the indices for single and pair excitations std::sort(exc_info.pair_inds.begin(), exc_info.pair_inds.end()); std::sort(exc_info.single_inds.begin(), exc_info.single_inds.end()); + // Store the sign of the overall excitation + int sign = 1; + if (exc_info.pair_inds[0] != -1 || exc_info.single_inds[0] != -1) { + sign = sign_excite(rdet, holes, particles); + } + exc_info.sign = sign; + + // store the excitation information det_exc_param_indx[idet] = exc_info; } } @@ -287,7 +387,8 @@ bool AP1roGeneralizedSenoObjective::permanent_calculation(const std::vector void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { p_permanent.resize(nconn); s_permanent.resize(nconn); + //print x + for (std::size_t i = 0; i < nparam; ++i) { + std::cout << x[i] << " "; + } + std::cout << "\n" << std::endl; + for (std::size_t idet = 0; idet != ndet; ++idet) { @@ -398,22 +509,32 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, d if (exc_info.pair_inds[0] != -1) { if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { - std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; + std::cerr << "Error calculating pair_permanent for idet" << idet << "\n" << std::endl; } } - + if (exc_info.single_inds[0] != -1) { if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { - std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; + std::cerr << "Error calculating single_permanent for idet " << idet << "\n" << std::endl; } } + // If given det is not allowed in the wfn, set the permanents to zero + // idet = 0 is the reference HF determinant + if (exc_info.pair_inds[0] == -1 && exc_info.single_inds[0] == -1 && idet != 0) { + pair_permanent = 0.0; + single_permanent = 0.0; + } p_permanent[idet] = pair_permanent; s_permanent[idet] = single_permanent; + if (y != nullptr && idet < ndet) { - y[idet] = pair_permanent * single_permanent; - } else { + y[idet] = exc_info.sign * pair_permanent * single_permanent; + if (idet < 225) { + std::cout << idet << " " << exc_info.det[0] << " " << y[idet] << std::endl; + } + }else { std::cerr << "y is nullptr or idet is out of bounds" << std::endl; } } else { @@ -452,6 +573,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x // } // } + for (std::size_t iparam = 0; iparam < nparam; ++iparam) { double dpair = 0.0; double dsingle = 0.0; @@ -462,8 +584,10 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x if (exc_info.pair_inds[0] != -1) { dpair = compute_derivative(exc_info.pair_inds, x, iparam); } - // std::cout << "dpair: " << dpair << ", dsingle: " << dsingle << std::endl; + // std::cout << "\nidet: " << idet << ", det: " << exc_info.det[0] << std::endl; + // std::cout << "single_inds: " << exc_info.single_inds[0] << ", pair_inds: " << exc_info.pair_inds[0] << std::endl; // std::cout << "single_permanent: " << single_permanent << ", pair_permanent: " << pair_permanent << std::endl; + // std::cout << "wrt iparam: " << iparam << ", dpair: " << dpair << ", dsingle: " << dsingle << std::endl; // std::cout << "idet: " << idet << " deriv: " << dpair * single_permanent + dsingle * pair_permanent << std::endl; y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; } diff --git a/pyci/src/nonsingletci.cpp b/pyci/src/nonsingletci.cpp index dcd971d..8bf6841 100644 --- a/pyci/src/nonsingletci.cpp +++ b/pyci/src/nonsingletci.cpp @@ -157,7 +157,9 @@ long NonSingletCI::calc_sindex(const long occ, const long vir) const { // std::cout << "o: " << o << ", v: " << v << std::endl; // std::cout << "nocc: " << nocc << ", nb: " << nb << std::endl; - long idx = nocc / 2 * (nbasis - nocc) / 2 + o * (nbasis - nocc) + v; + // long idx = nocc / 2 * (nbasis - nocc) / 2 + o * (nbasis - nocc) + v; //considering doubles are listed first + + long idx = o * (nbasis - nocc) + v; // considering singles are listed first // std::cout << "idx: " << idx << std::endl; return idx; } @@ -175,7 +177,8 @@ long NonSingletCI::calc_pindex(const long occ, const long vir) const { } else { o = occ; } - long idx = (nbasis / 2 - nocc / 2) * o + v; + // long idx = (nbasis / 2 - nocc / 2) * o + v; //considering doubles are listed first + long idx = (nbasis - nocc) * nocc + (nbasis / 2 - nocc / 2) * o + v; //considering singles are listed first return idx; } From 8b42198376a1eba6109f26e2a00607b44dae3ab7 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 12 Feb 2025 18:19:46 -0500 Subject: [PATCH 191/197] added fanpy approach to calculate overlap --- pyci/src/ap1rogen.cpp | 1880 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 1741 insertions(+), 139 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index c142d8e..d666aca 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -14,8 +14,14 @@ * along with PyCI. If not, see . */ #include -// #include +#include #include +#include +#include +#include +#include +#include +#include namespace pyci { @@ -29,9 +35,18 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_ const std::size_t n_paramcons_, const long *idx_paramcons_, const double *val_paramcons_) -: Objective::Objective(op_, wfn_, n_detcons_, idx_detcons_, val_detcons_, n_paramcons_, idx_paramcons_, val_paramcons_) +: Objective::Objective(op_, wfn_, n_detcons_, idx_detcons_, val_detcons_, n_paramcons_, idx_paramcons_, val_paramcons_), wfn_(wfn_) { - init_overlap(wfn_); + // init_overlap(wfn_); + ranks = {1, 2}; + set_attributes_from_wfn(wfn_); + exops = assign_exops(); //wfn_.nbasis, wfn_.nocc, wfn_.nword); + // assign_and_sort_exops(ranks, wfn_.nbasis); + nparam = nocc / 2 * (nbasis/2 - nocc / 2); //paired-doubles + nparam += nocc * (nbasis - nocc); // alpha, beta singles + + ovlp.resize(nconn); + d_ovlp.resize(nconn * nparam); } // call to initizlize the overlap related data @@ -41,14 +56,23 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const SparseOp &op_ const pybind11::object val_detcons_, const pybind11::object idx_paramcons_, const pybind11::object val_paramcons_) -: Objective::Objective(op_, wfn_, idx_detcons_, val_detcons_, idx_paramcons_, val_paramcons_) +: Objective::Objective(op_, wfn_, idx_detcons_, val_detcons_, idx_paramcons_, val_paramcons_), wfn_(wfn_) { - init_overlap(wfn_); + // init_overlap(wfn_); + ranks = {1, 2}; + set_attributes_from_wfn(wfn_); + exops = assign_exops(); //wfn_.nbasis, wfn_.nocc, wfn_.nword); + // assign_and_sort_exops(ranks, wfn_.nbasis); + nparam = nocc / 2 * (nbasis/2 - nocc / 2); //paired-doubles + nparam += nocc * (nbasis - nocc); // alpha, beta singles + + ovlp.resize(nconn); + d_ovlp.resize(nconn * nparam); } // Copy Constructor // obj is the constant reference to another object to be copied AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGeneralizedSenoObjective &obj) -: Objective::Objective(obj), det_exc_param_indx(obj.det_exc_param_indx), nexc_list(obj.nexc_list) +: Objective::Objective(obj), exops(obj.exops), ind_exops(obj.ind_exops), ranks(obj.ranks), det_exc_param_indx(obj.det_exc_param_indx), nexc_list(obj.nexc_list), wfn_(obj.wfn_) { return; } @@ -56,11 +80,1450 @@ AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(const AP1roGenerali // Move constructor // obj is the rvalue reference to another object to be moved AP1roGeneralizedSenoObjective::AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&obj) noexcept -: Objective::Objective(obj), det_exc_param_indx(obj.det_exc_param_indx), nexc_list(std::move(obj.nexc_list)) +: Objective::Objective(obj), exops(std::move(obj.exops)), ind_exops(std::move(obj.ind_exops)), ranks(std::move(obj.ranks)), det_exc_param_indx(obj.det_exc_param_indx), nexc_list(std::move(obj.nexc_list)), wfn_(obj.wfn_) { return; } +// Function to set attributes from wfn +void AP1roGeneralizedSenoObjective::set_attributes_from_wfn(const NonSingletCI & wfn) { + nbasis = wfn.nbasis; + nocc = wfn.nocc; + ndet = wfn.ndet; + nword = wfn.nword; + + // std::cout << "nbasis: " << nbasis << ", nocc: " << nocc << ", ndet: " << ndet << ", nword: " << nword << std::endl; + // // Print the types of the attributes + // std::cout << "Type of wfn.nbasis: " << typeid(decltype(wfn.nbasis)).name() << std::endl; + // std::cout << "Type of wfn.nocc: " << typeid(decltype(wfn.nocc)).name() << std::endl; + // std::cout << "Type of wfn.ndet: " << typeid(decltype(wfn.ndet)).name() << std::endl; + // std::cout << "Type of wfn.nword: " << typeid(decltype(wfn.nword)).name() << std::endl; +} + +std::unordered_map, int, AP1roGeneralizedSenoObjective::HashVector, + AP1roGeneralizedSenoObjective::VectorEqual> AP1roGeneralizedSenoObjective::assign_exops(){ + //const long nbasis, const long nocc, const long nword){ + + int counter = 0; + // std::cout << "nocc: " << nocc << ", nbasis: " << nbasis << std::endl; + // Occupied indices of HF reference det + AlignedVector rdet(nword); + wfn_.fill_hartreefock_det(nbasis, nocc, &rdet[0]); + AlignedVector ex_from(nocc); + fill_occs(nword, rdet.data(), &ex_from[0]); + + AlignedVector ex_to; + for (std::size_t i = 0; i < nbasis; ++i) { + if (std::find(ex_from.begin(), ex_from.end(), i) == ex_from.end()) { + ex_to.push_back(i); + } + } + + // std::cout << "****Ex_from: "; + // for (long i : ex_from) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + // std::cout << "****Ex_to: "; + // for (long i : ex_to) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + + // Generate Single excitations: non-spin-preserving + for (size_t i = 0; i < ex_from.size(); ++i) { + long occ_alpha = ex_from[i]; + for (long vir : ex_to) { + std::vector exop = {occ_alpha, vir}; + exops[exop] = counter++; + } + } + + long nspatial = nbasis / 2; + + // Generate paired double excitations + for (size_t i = 0; i < ex_from.size() / 2; ++i) { + long occ_alpha = ex_from[i]; + for (size_t a = 0; a < ex_to.size() / 2; ++a) { + long vir_alpha = ex_to[a]; + std::vector exop = {occ_alpha, occ_alpha + nspatial, vir_alpha, vir_alpha + nspatial}; + exops[exop] = counter++; + } + } + + // std::cout << "****Exops: "; + // for (const auto& exop : exops) { + // std::cout << "{ "; + // for (long i : exop.first) { + // std::cout << i << " "; + // } + // std::cout << "} : " << exop.second << std::endl; + // } + + + // Create a vector of keys from the exops map + for (const auto& pair : exops) { + ind_exops.push_back(pair.first); + } + + // Sort the vector of keys based on the values in the exops map + std::sort(ind_exops.begin(), ind_exops.end(), [this](const std::vector& a, const std::vector& b) { + return exops[a] < exops[b]; + }); + + return exops; +} + + + + + +// Helper function to print the result +void AP1roGeneralizedSenoObjective::printPartitions(const std::vector& partitions) { + for (const auto& partition : partitions) { + std::cout << "{ "; + for (int coin : partition) { + std::cout << coin << " "; + } + std::cout << "}\n"; + } +} + +// Recursive function to find all partitions +std::vector AP1roGeneralizedSenoObjective::findPartitions(const std::vector& coins, int numCoinTypes, int total, Cache& cache) { + // std::cout << "\nCoins.size(): " << coins.size() << std::endl; + // std::cout << "numCoinTypes: " << numCoinTypes << std::endl; + // std::cout << "total: " << total << std::endl; + + if (total == 0) { + return {{}}; + } + + if (total < 0 || numCoinTypes <= 0) { + return {}; + } + + CacheKey key = {numCoinTypes, total}; + if (cache.find(key) != cache.end()) { + return cache[key]; + } + + std::vector result; + + // Include the last coin + for (auto& partition : findPartitions(coins, numCoinTypes, total - coins[numCoinTypes - 1], cache)) { + partition.push_back(coins[numCoinTypes - 1]); + result.push_back(partition); + } + + // Exclude the last coin + auto excludeLast = findPartitions(coins, numCoinTypes - 1, total, cache); + result.insert(result.end(), excludeLast.begin(), excludeLast.end()); + + cache[key] = result; + // std::cout << "Cache size: " << cache.size() << std::endl; + // std::cout << "Key: " << key.first << " " << key.second << std::endl; + // std::cout << "Result size: " << result.size() << std::endl; + return result; +} + +// Main function to handle the partitions +std::vector AP1roGeneralizedSenoObjective::intPartitionRecursive(const std::vector& coins, int numCoinTypes, int total) { + // std::cout << "IntPartitionRecur: \nCoins: "; + // for (int coin : coins) { + // std::cout << coin << " "; + // } + // std::cout << std::endl; + + Cache cache; + auto result = findPartitions(coins, numCoinTypes, total, cache); + + // Sort each partition to ensure consistency + for (auto& partition : result) { + std::sort(partition.begin(), partition.end()); + } + + // Remove duplicates (optional if input guarantees no duplicates) + std::sort(result.begin(), result.end()); + result.erase(std::unique(result.begin(), result.end()), result.end()); + + // std::cout << "Number of partitions: " << result.size() << std::endl; + // std::cout << "Partitions: "; + // printPartitions(result); + + return result; +} + + + +void AP1roGeneralizedSenoObjective::generateCombinations(const std::vector collection, std::vector::size_type bin_size, int start, + std::vector& current_comb, std::vector>& results) { + if (current_comb.size() == bin_size) { + results.push_back(current_comb); + return; + } + + for (std::vector::size_type i = start; i < collection.size(); ++i) { + current_comb.push_back(collection[i]); + generateCombinations(collection, bin_size, i + 1, current_comb, results); + current_comb.pop_back(); + } +} + + +// Function to generate unordered partitions +void AP1roGeneralizedSenoObjective::get_unordered_partition(std::vector& collection, std::vector>& bin_size_num, + std::vector>& current_partition, int index, + std::vector>>& results) { + + if (index == 0) { + results.push_back(current_partition); + return; + } + + int last = collection[index-1]; + // std::cout << "Last element from collection: " << last << std::endl; + + std::vector>> prev_partitions; + get_unordered_partition(collection, bin_size_num, current_partition, index - 1, prev_partitions); + + for (const auto& prev_partition : prev_partitions) { + // std::cout << "Previous partition: "; + // print_current_partition(prev_partition); + + int ind_bin = -1; + int ind_size = 0; + int ind_bin_size = -1; + + while (ind_size < static_cast(bin_size_num.size())) { + ind_bin += 1; + ind_bin_size += 1; + + if (ind_bin_size == bin_size_num[ind_size].second) { + ind_size += 1; + ind_bin_size = 0; + if (ind_size == static_cast(bin_size_num.size())) { + break; + } + } + + std::vector subset = prev_partition[ind_bin]; + // std::cout << "Selected subset: "; + // for (int num : subset) std::cout << num << " "; + // std::cout << std::endl; + + if (subset.empty()) { + std::vector> new_partition = prev_partition; + new_partition[ind_bin].push_back(last); + results.push_back(new_partition); + + if (bin_size_num[ind_size].second > 1) { + ind_bin += bin_size_num[ind_size].second - ind_bin_size - 1; + ind_size += 1; + ind_bin_size = -1; + } + continue; + } + + if (!(subset.back() < last)) { + // std::cout << "Skipping because " << subset.back() << " is not less than " << last << std::endl; + continue; + } + + if (!(static_cast(subset.size()) < bin_size_num[ind_size].first)) { + // std::cout << "Skipping because subset length " << subset.size() << " exceeds limit " << bin_size_num[ind_size].first << std::endl; + continue; + } + + std::vector> new_partition = prev_partition; + new_partition[ind_bin].push_back(last); + results.push_back(new_partition); + } + } +} + + +std::vector>> AP1roGeneralizedSenoObjective::generate_unordered_partitions(std::vector collection, + std::vector> bin_size_num) { + // std::cout << "Entering in generate unordered partition\n" ; + std::vector>> results; + + // Compute total number of bins + int total_bins = 0; + for (auto& bin : bin_size_num) total_bins += bin.second; + // std::cout << "Total bins: " << total_bins << std::endl; + + std::vector> current_partition(total_bins); // Initialize correct number of bins + std::sort(collection.begin(), collection.end()); // Ensure input order + get_unordered_partition(collection, bin_size_num, current_partition, collection.size(), results); + + return results; +} + + + +// Grouping By Size +std::unordered_map>> AP1roGeneralizedSenoObjective::group_by_size( + const std::vector>& partitions) { + // std::cout << "\nInside group_by_size\n"; + std::unordered_map>> grouped_exops; + for (const auto& part : partitions) { + // std::cout << "Part size: " << part.size() << std::endl; + grouped_exops[part.size()].push_back(part); + } + // print_grouped_exops(grouped_exops); + // std::cout << "groups by size: " ; + // for (const auto& group : grouped_exops) { + // std::cout << "Group size: " << group.first << std::endl; + // for (const auto& part : group.second) { + // std::cout << "{ "; + // for (int i : part) { + // std::cout << i << " "; + // } + // std::cout << "}\n"; + // } + // } + + return grouped_exops; +} + +// // Generating Permutations +// template +// std::vector> AP1roGeneralizedSenoObjective::generate_perms( +// const std::vector& elements, +// std::vector& current, +// std::vector& used) { +// std::vector> result; +// if (current.size() == elements.size()) { +// result.push_back(current); +// return result; +// } +// for (size_t i = 0; i < elements.size(); ++i) { +// if (used[i]) continue; +// used[i] = true; +// current.push_back(elements[i]); +// auto perms = generate_perms(elements, current, used); +// result.insert(result.end(), perms.begin(), perms.end()); +// current.pop_back(); +// used[i] = false; +// } + +// return result; +// } + +// Helper function to generate permutations +template +std::vector> AP1roGeneralizedSenoObjective::generate_perms(const std::vector & vec) { + std::vector> perms; + std::vector temp = vec; + do { + perms.push_back(temp); + } while (std::next_permutation(temp.begin(), temp.end())); + + // std::cout << "Permutations: "; + // for (const auto& perm : perms) { + // std::cout << "{ "; + // for (T i : perm) { + // std::cout << i << " "; + // } + // std::cout << "}\n"; + // } + + return perms; +} + +// Combining Paired Permutations +// combine annihilation and creation operators of the same size +// std::vector, std::vector>> +std::vector, std::vector>> AP1roGeneralizedSenoObjective::combine_pairs( + const std::vector>& annhs, + const std::vector>& creas) { + std::vector, std::vector>> combined_perms; + for (const auto& annh : annhs) { + for (const auto& crea : creas) { + combined_perms.emplace_back(annh, crea); + } + } + return combined_perms; +} + + +// Computes the sign of a permutation +int AP1roGeneralizedSenoObjective::sign_perm(std::vector jumbled_set, const std::vector ordered_set, bool is_decreasing = false) { + if (is_decreasing) { + std::reverse(jumbled_set.begin(), jumbled_set.end()); + } + + // Determine the ordered set if not provided + std::vector sorted_set = ordered_set.empty() ? jumbled_set : ordered_set; + + // Ensure the ordered set is strictly increasing + if (!std::is_sorted(sorted_set.begin(), sorted_set.end())) { + throw std::invalid_argument("ordered_set must be strictly increasing."); + } + + int sign = 1; + + // Count transpositions needed to sort + for (size_t i = 0; i < sorted_set.size(); ++i) { + for (size_t j = 0; j < jumbled_set.size(); ++j) { + if (jumbled_set[j] > sorted_set[i]) { + sign *= -1; + } else if (jumbled_set[j] == sorted_set[i]) { + break; + } + } + } + + return sign; +} + +// Helper function to determine the smallest integer type to hold indices +template +T AP1roGeneralizedSenoObjective::choose_dtype(size_t nparams) { + size_t two_power = static_cast(std::ceil(std::log2(nparams))); + if (two_power <= 8) { + return uint8_t(); + } else if (two_power <= 16) { + return uint16_t(); + } else if (two_power <= 32) { + return uint32_t(); + } else if (two_power <= 64) { + return uint64_t(); + } else { + throw std::runtime_error("Can only support up to 2**63 number of parameters"); + } +} + +// Helper function to generate the Cartesian product of vectors +template +std::vector, std::vector>>> AP1roGeneralizedSenoObjective::cartesian_product(const std::vector>, std::vector>>>& v) { + std::vector, std::vector>>> s = {{}}; + for (const auto& u : v) { + std::vector, std::vector>>> r; + for (const auto& x : s) { + for (const auto& y1 : u.first) { + for (const auto& y2 : u.second) { + r.push_back(x); + r.back().emplace_back(y1, y2); + } + } + } + s = std::move(r); + } + return s; +} + +// Explicit instantiation of the cartesian_product template for the required type +// template std::vector, std::vector>>> cartesian_product(const std::vector>, std::vector>>>&); + +// std::vector> AP1roGeneralizedSenoObjective::cartesian_product(const std::vector>& v) { +// std::vector> result; +// if (v.empty()) return result; + +// // Initialize result with the first vector +// result.push_back({}); +// for (const auto& vec : v) { +// std::vector> temp; +// for (const auto& res : result) { +// for (const auto& elem : vec) { +// temp.push_back(res); +// temp.back().push_back(elem); +// } +// } +// result = std::move(temp); +// } +// return result; +// } + +// Ensure the template function is instantiated for the required types + +// template std::vector, std::vector>>> AP1roGeneralizedSenoObjective::cartesian_product(const std::vector, std::vector>>>&); + +// template class cartesian_product, std::vector>>; + + +// Function to generate all possible excitation operators +void AP1roGeneralizedSenoObjective::generate_possible_exops( + const std::vector& a_inds, const std::vector& c_inds) +{ + // std::cout << "\nGenerating possible excitation operators...\n"; + + // const std::unordered_set>& valid_exops; + std::pair, std::vector> key = std::make_pair(a_inds, c_inds); + // std::unordered_map>, std::size_t> inds_multi; + std::unordered_map>> inds_multi; + + // Step 1: Get partitoins of a_inds size + int exrank = a_inds.size(); + int nranks = ranks.size(); + auto partitions = intPartitionRecursive(ranks, nranks, exrank); + + for (const auto& partition : partitions) { + // std::cout << "Partition: "; + // for (int size : partition) { + // std::cout << size << " "; + // } + // std::cout << "\n"; + // Step 2: Convert partition into bin size and count format + std::unordered_map reduced_partition; + for (int size : partition) { + reduced_partition[size]++; + } + + //bin_size_num = exc_op_rank, counter of the number of that excitation operator + std::vector> bin_size_num; + // for (const auto& [bin_size, count] : reduced_partition) { + for (const auto& bins : reduced_partition) { + const auto& bin_size = bins.first; + const auto& count = bins.second; + bin_size_num.emplace_back(bin_size, count); + // std::cout << "Bin size: " << bin_size << " Count: " << count << "\n"; + } + + // Step 3: Generate all unordered partitions of a_inds and c_inds + // convert a_inds from size_t to int + std::vector a_inds_int(a_inds.begin(), a_inds.end()); + std::vector c_inds_int(c_inds.begin(), c_inds.end()); + auto annhs_partitions = generate_unordered_partitions(a_inds_int, bin_size_num); + auto creas_partitions = generate_unordered_partitions(c_inds_int, bin_size_num); + + // std::cout << "annhs_partitions:\n"; + // for (const auto& annhs : annhs_partitions) { + // std::cout << "{ "; + // for (const auto& annh : annhs) { + // std::cout << "{ "; + // for (int i : annh) { + // std::cout << i << " "; + // } + // std::cout << "} "; + // } + // std::cout << "}\n"; + // } + // std::cout << "creas_partitions:\n"; + // for (const auto& creas : creas_partitions) { + // std::cout << "{ "; + // for (const auto& crea : creas) { + // std::cout << "{ "; + // for (int i : crea) { + // std::cout << i << " "; + // } + // std::cout << "} "; + // } + // std::cout << "}\n"; + // } + + + for (const auto& annhs : annhs_partitions) { + // auto annhs_grouped = group_by_size(annhs); + std::unordered_map>> annhs_grouped; + for (const auto& annh : annhs) { + annhs_grouped[annh.size()].push_back(annh); + } + + // std::cout << "annh_grouped:\n"; + // for (const auto& pair : annhs_grouped) { + // std::cout << pair.first << ": "; + // for (const auto& vec : pair.second) { + // std::cout << "{ "; + // for (int i : vec) { + // std::cout << i << " "; + // } + // std::cout << "} "; + // } + // std::cout << std::endl; + // } + + for (const auto& creas: creas_partitions) { + // auto creas_grouped = group_by_size(creas); + std::unordered_map>> creas_grouped; + for (const auto& crea : creas) { + creas_grouped[crea.size()].push_back(crea); + } + + // std::cout << "creas_grouped:\n"; + // for (const auto& pair : creas_grouped) { + // std::cout << pair.first << ": "; + // for (const auto& vec : pair.second) { + // std::cout << "{ "; + // for (int i : vec) { + // std::cout << i << " "; + // } + // std::cout << "} "; + // } + // std::cout << std::endl; + // } + + // Step 3: Generate permutations for each group + std::unordered_map>>> creas_perms; + // // -------------------------------------------------------------------- + // for (const auto& pair : creas_grouped) { + // std::cout << "Generating perms:\n"; + // std::cout << pair.second.size() << std::endl; + // if (pair.first == 1 && pair.second.size() > 1) { + // // Permute all bins together + // std::vector all_bins; + // for (const auto& vec : pair.second) { + // all_bins.insert(all_bins.end(), vec.begin(), vec.end()); + // } + // auto perms = generate_perms(all_bins); + // for (const auto& perm : perms) { + // std::vector> split_perm; + // for (size_t i = 0; i < perm.size(); i ++) { + // split_perm.push_back(std::vector(perm.begin() + i, perm.begin() + i + pair.first)); + // } + // creas_perms[pair.first].insert(creas_perms[pair.first].end(), split_perm.begin(), split_perm.end()); + // } + // } else { + // const auto& group = pair.second; + // std::vector>> perms; + // if (group.size() > 1) { + // // Generate permutations of the vectors in the group + // std::vector> group_copy = group; + // do { + // perms.push_back(group_copy); + // } while (std::next_permutation(group_copy.begin(), group_copy.end())); + // } else { + // perms.push_back(group); + // } + // creas_perms[pair.first] = perms; + // // for (const auto& vec : pair.second){ + // // std::cout << "vec: "; + // // for (int i : vec) { + // // std::cout << i << " "; + // // } + // // std::cout << std::endl; + // // creas_perms[pair.first] = generate_perms(vec); + // // } + // } + + // } + // // -------------------------------------------------------------------- + // const auto& size = size_group.first; + // const auto& group = size_group.second; + // std::vector> perms; + // for (const auto& crea: group) { + // std::vector temp; + // std::vector used(crea.size(), false); + // std::cout << "genreate_perms\n"; + // auto current_perms = generate_perms(crea, temp, used); + // perms.insert(perms.end(), current_perms.begin(), current_perms.end()); + // } + // creas_perms[size] = perms; + // std::cout << "creas_perms:\n"; + // for (const auto& perm : perms) { + // std::cout << "{ "; + // for (int i : perm) { + // std::cout << i << " "; + // } + // std::cout << "}\n"; + // } + // } + + for (const auto& pair : creas_grouped) { + int size = pair.first; + const auto& group = pair.second; + std::vector>> perms; + + // Generate permutations of the vectors in group + std::vector> group_copy = group; + do { + perms.push_back(group_copy); + } while (std::next_permutation(group_copy.begin(), group_copy.end())); + creas_perms[size] = perms; + } + + // Print creas_perms for debugging + // std::cout << "creas_perms:\n"; + // for (const auto& pair : creas_perms) { + // std::cout << pair.first << ": "; + // for (const auto& vecs : pair.second) { + // std::cout << "{ "; + // for (const auto& vec : vecs) { + // std::cout << "{ "; + // for (int i : vec) { + // std::cout << i << " "; + // } + // std::cout << "} "; + // } + // std::cout << "} "; + // } + // std::cout << std::endl; + // } + + // Combine permutations of each annihilation and creation pair (of same size) + // std::vector, std::vector>>> exc_perms; + std::vector>, std::vector>>> exc_perms; + for (const auto& size_num : bin_size_num) { + int size = size_num.first; + // if (annhs_grouped.find(size) != annhs_grouped.end() && creas_perms.find(size) != creas_perms.end()) { + // if (size == 1 && size_num.second > 1) { + // /// Special case: handle permutations of entire group + // std::size_t nperms = creas_perms[size].size() / creas_grouped[size].size(); + // std::cout << "nperms: " << nperms << std::endl; + // for (std::size_t i = 0; i < creas_perms[size].size(); i += nperms) { + // std::vector> split_crea; + // for (std::size_t j = 0; j < nperms ; ++j) { + // split_crea.push_back(creas_perms[size][i + j]); + // } + // exc_perms.push_back(std::make_pair(annhs_grouped[size], split_crea)); + // } + + // } else { + // exc_perms.push_back(std::make_pair(annhs_grouped[size], creas_perms[size])); + // } + // } + if (annhs_grouped.find(size) != annhs_grouped.end() && creas_perms.find(size) != creas_perms.end()) { + for (const auto& crea_perm : creas_perms[size]){ + exc_perms.push_back(std::make_pair(annhs_grouped[size], crea_perm)); + } + } + } + // auto annh_group = annhs_grouped[size]; + // auto crea_perm = creas_perms[size]; + // std::cout << "Printing crea_perm\n"; + // for (const auto& crea : crea_perm) { + // std::cout << "{ "; + // for (int i : crea) { + // std::cout << i << " "; + // } + // std::cout << "}\n"; + // } + // std::vector, std::vector>> combined; + // for (const auto& annh : annh_group) { + // for (const auto& crea : crea_perm) { + + // std::cout << "Annihilation: "; + // for (int i : annh) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + // std::cout << "Creation: "; + // for (int i : crea) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + // combined.emplace_back(std::make_pair(annh, crea)); + + // combined.push_back(std::make_pair(annh, crea)); + // std::cout << "Combined: {"; + // for (const auto& elem : combined.back().first) { + // std::cout << elem << " "; + // } + // std::cout << "-->"; + // for (const auto& elem : combined.back().second) { + // std::cout << elem << " "; + // } + // std::cout << "}" << std::endl; + // } + // } + // exc_perms.push_back(combined); + + // } + + // Print exc_perms + // std::cout << "\nexc_perms: "; + // for (const auto& pair : exc_perms) { + // for (const auto& annh : pair.first) { + // std::cout << "{ "; + // for (int i : annh) { + // std::cout << i << " "; + // } + // } + // std::cout << "} -> { "; + // for (const auto& crea : pair.second) { + // for (int i : crea) { + // std::cout << i << " "; + // } + // std::cout << "} "; + // } + // std::cout << std::endl; + // } + + + // for (const auto& excs : cartesian_product(exc_perms)) { + for (const auto& excs : exc_perms) { + // std::cout << "***Cartesian product***\n"; + std::vector> combs; + // std::vector, std::vector>> combs; + bool is_continue = false; + // for (std::size_t i = 0; i < excs.first.size(); ++i) { + // // auto [annh, crea] = exc; + auto annhs = excs.first; + auto creas = excs.second; + + // std::cout << "Annihilation: "; + // for (const auto& vec : annhs) { + // std::cout << "{ "; + // for (int elem : vec) { + // std::cout << elem << " "; + // } + // std::cout << "} "; + // } + // std::cout << std::endl; + // std::cout << "Creation: "; + // for (const auto& vec : creas) { + // std::cout << "{ "; + // for (int elem : vec) { + // std::cout << elem << " "; + // } + // std::cout << "} "; + // } + // std::cout << std::endl; + //(annh); + // op.insert(op.end(), crea.begin(), crea.end()); + // op.reserve(annh.size() + crea.size()); // Reserve space for efficiency + + // std::vector op; + // for (int a : annh) { + // std::cout << "a: " << a << std::endl; + // op.push_back(static_cast(a)); // Convert each element to long + // } + // for (int c : crea) { + // std::cout << "c: " << c << std::endl; + // op.push_back(static_cast(c)); // Convert each element to long + // } + for (std::size_t j = 0; j < annhs.size(); ++j) { + std::vector annh(annhs[j].begin(), annhs[j].end()); // Convert each element to long + std::vector crea(creas[j].begin(), creas[j].end()); // Convert each element to long + std::vector op(annh.begin(), annh.end()); + op.insert(op.end(), crea.begin(), crea.end()); + // std::cout << "op: "; + // for (long elem : op) { + // std::cout << elem << " "; + // } + // std::cout << std::endl; + + // std::cout << "Size of exops: " << exops.size() << std::endl; + + // std::csout<< "searching for op in exops\n"; + // if (exops.find(op) != exops.end()) { + // std::cout << "op found in exops\n"; + // } + // else if (exops.find(op) == exops.end()) { + // std::cout << "op not found in exops\n"; + // is_continue = false; + // break; + // } + // try { + // combs.push_back(op); + // std::cout << "Successfully pushed op to combs" << std::endl; + // } catch (const std::exception& e) { + // std::cerr << "Exception caught during push_back: " << e.what() << std::endl; + // } catch (...) { + // std::cerr << "Unknown exception caught during push_back" << std::endl; + // } + + if (std::find_if(exops.begin(), exops.end(), [&op](const auto& pair) { + return pair.first == op; + }) == exops.end()) { + // std::cout << "op not found in exops\n"; + is_continue = true; + break; + } + combs.push_back(op); + + // } + + } + if (is_continue) break; + // if (is_continue) continue; + + int num_hops = 0, prev_hurdles = 0; + //std::cout << "combs size: " << combs.size() << std::endl; + + std::vector jumbled_a_inds, jumbled_c_inds; + for (const auto& exop : combs) { + size_t num_inds = exop.size() / 2; + num_hops += prev_hurdles * num_inds; + prev_hurdles += num_inds; + + //std::cout << "num_hops: " << num_hops << ", prev_hurdles: " << prev_hurdles << std::endl; + + jumbled_a_inds.insert(jumbled_a_inds.end(), exop.begin(), exop.begin() + num_inds); + jumbled_c_inds.insert(jumbled_c_inds.end(), exop.begin() + num_inds, exop.end()); + } + + int sign = (num_hops % 2 == 0) ? 1 : -1; + + + + sign *= sign_perm(jumbled_a_inds, a_inds, false); + sign *= sign_perm(jumbled_c_inds, c_inds, false); + + std::vector inds; + for (const auto& exop : combs) { + inds.push_back(exops[exop]); + } + inds.push_back(sign); + //std::cout << "Sign: " << sign << std::endl; + + + //std::cout << "Inds: "; + // for (int i : inds) { + // std::cout << i << " "; + // if (i > 10000) { + // std::cout << "i > 10000\n"; + // } + // } + // std::cout << std::endl; + + if (inds_multi.find(inds.size() - 1) == inds_multi.end()) { + //std::cout << "Inds_multi not found\n"; + inds_multi[static_cast(inds.size() - 1)] = {}; + } + inds_multi[static_cast(inds.size() - 1)].push_back(inds); + } + } + + } + } + //std::cout << "addign inds_multi exop_combs: "; + // exop_combs[key].push_back(inds_multi); + try { + exop_combs[key] = inds_multi; + //std::cout << "Successfully assigned inds_multi to exop_combs" << std::endl; + } catch (const std::exception& e) { + std::cerr << "Exception caught during exop_combs assignment: " << e.what() << std::endl; + } catch (...) { + std::cerr << "Unknown exception caught during exop_combs assignment" << std::endl; + } + + // std::cout << "exop_combs done"; + // Print the contents of exop_combs + // std::cout << "Contents of exop_combs:" << std::endl; + // for (const auto& pair : exop_combs) { + // std::cout << "\n{"; + // for (const auto& elem : pair.first.first) { + // std::cout << elem << ", "; + // } + // for (const auto& elem : pair.first.second) { + // std::cout << elem << ", "; + // } + // std::cout << "} : "; + // for (const auto& vec : pair.second) { + // std::cout << "{"; + // const auto& rank = vec.first; + // const auto& inds = vec.second; + // std::cout << rank << ":" ; + // for (const auto& ind : inds) { + // std::cout << "{"; + // for (int i : ind) { + // std::cout << i << " "; + // } + // std::cout << "}"; + // } + // std::cout << "}, "; + // } + // std::cout << std::endl; + // } + + + + // Determine dtype + // uint64_t dtype = choose_dtype(nparam); + +// // Prepare reshaped and finalized inds_multi +// for (auto& [rank, inds] : inds_multi) { +// // Reshape to (-1, rank + 1) and store in uint64_t format +// size_t row_size = rank + 1; +// size_t nrows = inds.size() / row_size; +// std::vector reshaped_inds; +// std::pair, std::vector> key = std::make_pair(a_inds, c_inds); + +// for (size_t i = 0; i < nrows; ++i) { +// uint64_t packed_row = 0; +// for (size_t j = 0; j < row_size; ++j) { +// packed_row = (packed_row << 16) | static_cast(inds[i * row_size + j][0]); +// } +// reshaped_inds.push_back(packed_row); +// } +// // Save reshaped indices in the exop_combs structure +// exop_combs[key][rank] = reshaped_inds; +// } +} + + +// std::variant> AP1roGeneralizedSenoObjective::product_amplitudes_multi( +double AP1roGeneralizedSenoObjective::product_amplitudes_multi( + const std::unordered_map>>& inds_multi, + bool deriv, const double* x){ + // std::cout << "deriv: " << deriv << std::endl; + double output = 0.0; + if (deriv) { + throw std::invalid_argument("Derivative computation is not supported."); + } else { + // for (const auto& [exc_order, inds_sign] : inds_multi) { + // std::cout << "In product_amplitudes_multi\n"; + // std::cout << "inds_multi size: " << inds_multi.size() << std::endl; + + for (const auto& exc_inds : inds_multi) { + // std::cout << "Processing exc_inds\n"; + + std::size_t exc_order = exc_inds.first; + const std::vector> inds_sign = exc_inds.second; + + // std::cout << "Exc_order: " << exc_order << std::endl; + // std::cout << "inds_sign size: " << inds_sign.size() << std::endl; + + // for (const auto& row : inds_sign) { + // std::cout << "Row: "; + // for (int i : row) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + // } + + std::vector> indices; + std::vector signs; + for (const auto& row : inds_sign) { + + // std::cout << "Row: "; + // for (int i : row) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + + if (row.empty()){ + std::cerr << "Error: row in empty\n"; + } + + + + std::vector ind(row.begin(), row.end() - 1); + indices.push_back(ind); + + // std::cout << "Indices: "; + // for (int i : ind) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + + int sign = row.back(); + signs.push_back (sign > 1 ? -1 : sign); + } + + for (size_t i = 0; i < indices.size(); ++i) { + double product = 1.0; + for (const auto& idx : indices[i]) { + // std::cout << "x[idx]: " << x[idx] << std::endl; + product *= x[idx]; + } + output += product * signs[i]; + } + } + + } + return output; + + // // Derivative computation + // std::vector output(nparam, 0.0); + // for (const auto& [exc_order, inds_sign] : inds_multi) { + // std::vector> indices; + // std::vector signs; + // for (const auto& row : inds_sign) { + // std::vector ind(row.begin(), row.end() - 1); + // indices.push_back(ind); + // int sign = row.back(); + // signs.push_back(sign > 1 ? -1 : sign); + // } + + // std::unordered_set unique_inds; + // for (const auto& row : indices) { + // unique_inds.insert(row.begin(), row.end()); + // } + + // for (const auto& ind : unique_inds) { + // std::vector bool_inds; + // for (const auto& row : indices) { + // bool_inds.push_back(std::find(row.begin(), row.end(), ind) != row.end()); + // } + + // std::vector row_inds; + // for (const auto& bi : bool_inds) { + // row_inds.push_back(bi); + // } + + // std::vector> selected_params; + // for (const auto& row : indices) { + // std::vector temp; + // for (const auto& idx : row) { + // temp.push_back(x[idx]); + // } + // selected_params.push_back(temp); + // } + + // std::vector old_params; + // for (size_t i = 0; i < selected_params.size(); ++i) { + // if (bool_inds[i]) { + // old_params.push_back(selected_params[i][ind]); + // selected_params[i][ind] = 1.0; + // } + // } + + // for (size_t i = 0; i < selected_params.size(); ++i) { + // if (row_inds[i]) { + // double prod = 1.0; + // for (const auto& val : selected_params[i]) { + // prod *= val; + // } + // output[ind] += prod * signs[i]; + // } + // } + + // for (size_t i = 0; i < selected_params.size(); ++i) { + // if (bool_inds[i]) { + // selected_params[i][ind] = old_params[i]; + // } + // } + // } + // } + // return output; +} + +int AP1roGeneralizedSenoObjective::sign_swap(AlignedVector sd, long pos_current, long pos_future){ + // Return the signature of applying annihilators then creators to the Slater determinant. + if (pos_current < 0 || pos_future < 0) { + throw std::invalid_argument("The current and future positions must be positive integers."); + } + + // if (!((sd >> pos_current) & 1)) { + if (!((sd[pos_current / Size()] >> (pos_current % Size())) & 1)) { + throw std::invalid_argument("Given orbital is not occupied in the Slater determinant."); + } + + int num_trans = 0; + if (pos_current < pos_future) { + // Count the number of set bits between pos_current and pos + for (long i = pos_current + 1; i <= pos_future; ++i) { + if ((sd[i / Size()] >> (i % Size())) & 1) { + ++num_trans; + } + } + } else { + for (long i = pos_future; i < pos_current; ++i) { + if ((sd[i / Size()] >> (i % Size())) & 1) { + ++num_trans; + } + } + } + return (num_trans % 2 == 0) ? 1 : -1; + +} + +int AP1roGeneralizedSenoObjective::sign_excite(AlignedVector sd, + const std::vector& annihilators, const std::vector& creators) { + // Return the sign of the Slater determinant after applying excitation operators. + int sign = 1; + for (std::size_t i : annihilators) { + // if (!((sd >> i) & 1)) { + if (!((sd[i / Size()] >> (i % Size())) & 1)) { + //print sd + std::cout << "Annihilator: " << i << std::endl; + for (std::size_t k = 0; k < sd.size(); ++k) { + std::cout << sd[k] << " "; + } + std::cout << std::endl; + throw std::invalid_argument("Given Slater determinant cannot be excited using the given creators and annihilators."); + } + sign *= sign_swap(sd, i, 0); + // sd = sd & ~(1UL << i); // annihilate ith orbital + sd[i / Size()] &= ~(1UL << (i % Size())); // annihilate ith orbital + } + + for (std::size_t a : creators) { + // sd = sd | (1UL << a); // create ath orbital + sd[a / Size()] |= (1UL << (a % Size())); // create ath orbital + // if (sd == 0) { + if (!((sd[a / Size()] >> (a % Size())) & 1)) { + //print sd + std::cout << "Creator: " << a << std::endl; + for (std::size_t k = 0; k < sd.size(); ++k) { + std::cout << sd[k] << " "; + } + std::cout << std::endl; + throw std::invalid_argument("Given Slater determinant cannot be excited using the given creators and annihilators."); + } + sign *= sign_swap(sd, a, 0); + } + return sign; +} + + +void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double* x, double* y) +{ + std::cout << "-------Computing Overlap\n nbasis: " << nbasis << ", ndet: " << ndet << "\n" ; + // long nocc_up = nocc / 2; + // long nb = nbasis / 2; + + // // nparam = nocc_up * (nb - nocc_up); //paired-doubles + // // nparam += nocc * (nbasis - nocc); // alpha, beta singles + + // // ovlp.resize(nconn); + // // d_ovlp.resize(nconn * nparam); + std::cout << "nconn: " << nconn << ", nparam: " << nparam << "\n"; + + AlignedVector rdet(nword); + wfn_.fill_hartreefock_det(nbasis, nocc, &rdet[0]); + std::cout << "rdet: " ; + for (std::size_t k = 0; k < nword; k++) { + std::cout << rdet[k]; } + std::cout << std::endl; + + if (y == nullptr) { + std::cerr << "Error: y is a null pointer" << std::endl; + // return; + } + + for (std::size_t idet = 0; idet != ndet; ++idet) { + // std::cout << "\n-----Processing idet = " << idet << "\n"; + y[idet] = 0.0; + // std::cout << "Accessing det_ptr" << std::endl; + + if (idet >= static_cast(wfn_.ndet)) { + std::cerr << "Error: idet (" << idet << ") is out of bounds (ndet: " << wfn_.ndet << ")" << std::endl; + continue; + } + + const ulong *det = wfn_.det_ptr(idet); + if (det == nullptr) { + std::cerr << "Error: det_ptr returned nullptr for idet = " << idet << std::endl; + // continue; + } + + // std::cout << "det: " ; + for (std::size_t k = 0; k < nword; k++) { + std::cout << det[k]; } + std::cout << ",,"; + + // Check if given det is the same as the reference det + bool are_same = true; + for (std::size_t k = 0; k < nword; ++k) { + // std::cout << det[k] << " "; + if (rdet[k] != det[k]) { + are_same = false; + break; + } + } + // std::cout << "are_same: " << are_same << std::endl; + + ulong word, hword, pword; + std::size_t h, p, nexc = 0; + + std::vector holes; + std::vector particles; + + // Collect holes and particles + for (std::size_t iword = 0; iword != nword; ++iword) + { + word = rdet[iword] ^ det[iword]; //str for excitation + hword = word & rdet[iword]; //str for hole + pword = word & det[iword]; //str for particle + + while(hword){ + h = Ctz(hword); + p = Ctz(pword); + + std::size_t hole_idx = h + iword * Size(); + std::size_t part_idx = p + iword * Size(); // - nocc_up; + + holes.push_back(hole_idx); + particles.push_back(part_idx); + + hword &= ~(1UL << h); + pword &= ~(1UL << p); + + ++nexc; + } + } + + // Sen-o processing + // Check if annhiliation and creation operators are in the exop_combinations + std::pair, std::vector> key = std::make_pair(holes, particles); + // std::cout << "key: " << key.first.size() << " " << key.second.size() << std::endl; + if (!are_same){ + // std::cout << "holes: "; + // for (std::size_t i : holes) { + // std::cout << i << " ";} + // std::cout << std::endl; + + if (exop_combs.find(key) == exop_combs.end()) { + + // std::cout << "particles: "; + // for (std::size_t i : particles) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + + std::vector holes_int(holes.begin(), holes.end()); + std::vector particles_int(particles.begin(), particles.end()); + generate_possible_exops(holes_int, particles_int); + // std::cout << "\nGenerated possible exops\n"; + + std::unordered_map>> inds_multi = exop_combs[key]; + + // std::cout <<"inds_multi size: " << inds_multi.size() << std::endl; + // std::cout << "**Inds_multi: "; + // for (const auto& rank_inds: inds_multi) { + // const auto& rank = rank_inds.first; + // const std::vector> inds = rank_inds.second; + // std::cout << rank << ":" << std::endl; + // for (const auto& ind : inds) { + // std::cout << "{"; + // for (int i : ind) { + // std::cout << i << " "; + // } + // std::cout << "}\n"; + // } + // } + + + // Occupied indices of HF reference det + AlignedVector occs(nocc); + fill_occs(nword, rdet.data(), &occs[0]); + + // Processing sen-o + for (auto& pair : inds_multi){ + auto& exc_order = pair.first; + auto& inds_sign_ = pair.second; + + // std::cout << "exc_order: " << exc_order << std::endl; + // std::cout << "inds_sign_ size: " << inds_sign_.size() << std::endl; + + // last element of inds_sign is the sign of the excitation + // auto& sign_ = inds_sign_.back(); + + // std::cout << "Params: "; + // for (int i = 0; i < nparam; i++) { + // std::cout << x[i] << " "; + // } + + std::vector> selected_rows; + // for (auto it = inds_sign_.begin(); it != inds_sign_.end() - 1; ++it) { + // const auto& row = *it; + for (const auto& row : inds_sign_) { + // std::cout << "Processing Row: "; + // for (int i : row) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + + std::unordered_set trash; + bool skip_row = false; + + // for (const auto& exop_indx : row) { + for (auto it = row.begin(); it != row.end() - 1; ++it) { + const auto& exop_indx = *it; + + // Check if exop_indx is a valid index + if (exop_indx < 0 || static_cast(exop_indx) >= ind_exops.size()) { + std::cout << "ind_exops.size(): " << ind_exops.size() << std::endl; + std::cerr << "Error: exop_indx " << exop_indx << " is out of bounds" << std::endl; + continue; + } + const auto& exop = ind_exops[exop_indx]; + + // std::cout << "exop_indx: " << exop_indx << std::endl; + // std::cout << "exop: "; + // for (long i : exop) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + + if (exop.size() == 2) { + // std::cout << "exop size: 2\n"; + if (trash.find(exop[0]) != trash.end()) { + skip_row = true; + break; + } + if (exop[0] < static_cast(nbasis / 2)) { + if (std::find(occs.begin(), occs.end(), exop[0] + nbasis / 2) == occs.end()) { + skip_row = true; + break; + } else { + trash.insert(exop[0]); + trash.insert(exop[0] + nbasis / 2); + } + } else { + if (std::find(occs.begin(), occs.end(), exop[0] - nbasis / 2) == occs.end()) { + skip_row = true; + break; + } else { + trash.insert(exop[0]); + trash.insert(exop[0] - nbasis / 2); + } + } + } else { + // std::cout << "exop size: != 2\n"; + for (size_t j = 0; j < exop.size() / 2; ++j) { + if (trash.find(exop[j]) != trash.end()) { + skip_row = true; + break; + } else { + trash.insert(exop[j]); + } + } + if (skip_row) break; + } + } + if (!skip_row) { + selected_rows.push_back(row); + } + } + inds_multi[exc_order] = selected_rows; + + } + + // std::cout << "Inds_multi: "; + // for (const auto& rank_inds: inds_multi) { + // const auto& rank = rank_inds.first; + // const std::vector> inds = rank_inds.second; + // std::cout << rank << ":" << std::endl; + // for (const auto& ind : inds) { + // std::cout << "{"; + // for (int i : ind) { + // std::cout << i << " "; + // } + // std::cout << "}\n"; + // } + // } + + + double amplitudes = 0.0; + amplitudes = product_amplitudes_multi(inds_multi, false, x); + // double amplitudes = std::get(amplitudes_variant); + int sign = sign_excite(rdet, holes, particles); + y[idet] = sign * amplitudes; + + // std::cout << "Amplitudes: " ; + std::cout << amplitudes << ",," << sign << std::endl; + // std::cout << "Sign: " <<; + + } else{ + std::unordered_map>> inds_multi = exop_combs[key]; + auto amplitudes = product_amplitudes_multi(inds_multi, false, x); + int sign = sign_excite(rdet, holes, particles); + std::cout << amplitudes << ",," << sign << std::endl; + y[idet] = sign * amplitudes; + } + + } else if (are_same) { + y[idet] = 1.0; + } else { + y[idet] = 0.0; + } + + + } + +} + + + + + + +//--------------------------------------------------------------------------------------------------------------------------------------------------- template void AP1roGeneralizedSenoObjective::generate_combinations(const std::vector& elems, int k, std::vector>& result, long nbasis) { std::vector mask(elems.size()); @@ -208,82 +1671,6 @@ void AP1roGeneralizedSenoObjective::generate_excitations(const std::vector sd, long pos_current, long pos_future){ - // Return the signature of applying annihilators then creators to the Slater determinant. - if (pos_current < 0 || pos_future < 0) { - throw std::invalid_argument("The current and future positions must be positive integers."); - } - - // if (!((sd >> pos_current) & 1)) { - if (!((sd[pos_current / Size()] >> (pos_current % Size())) & 1)) { - throw std::invalid_argument("Given orbital is not occupied in the Slater determinant."); - } - - int num_trans = 0; - if (pos_current < pos_future) { - // Count the number of set bits between pos_current and pos - for (long i = pos_current + 1; i <= pos_future; ++i) { - if ((sd[i / Size()] >> (i % Size())) & 1) { - ++num_trans; - } - } - } else { - for (long i = pos_future; i < pos_current; ++i) { - if ((sd[i / Size()] >> (i % Size())) & 1) { - ++num_trans; - } - } - } - - // if (pos_current < pos_future) { - // // Count the number of set bits between pos_current and pos_future - // num_trans = std::bitset(sd >> (pos_current + 1)).count() - std::bitset(sd >> (pos_future + 1)).count(); - // } else { - // // Count the number of set bits between pos_future and pos_current - // num_trans = std::bitset(sd >> pos_future).count() - std::bitset(sd >> pos_current).count(); - // } - - return (num_trans % 2 == 0) ? 1 : -1; - -} - -int AP1roGeneralizedSenoObjective::sign_excite(AlignedVector sd, - const std::vector& annihilators, const std::vector& creators) { - // Return the sign of the Slater determinant after applying excitation operators. - int sign = 1; - for (std::size_t i : annihilators) { - // if (!((sd >> i) & 1)) { - if (!((sd[i / Size()] >> (i % Size())) & 1)) { - //print sd - std::cout << "Annihilator: " << i << std::endl; - for (int k = 0; k < sd.size(); ++k) { - std::cout << sd[k] << " "; - } - std::cout << std::endl; - throw std::invalid_argument("Given Slater determinant cannot be excited using the given creators and annihilators."); - } - sign *= sign_swap(sd, i, 0); - // sd = sd & ~(1UL << i); // annihilate ith orbital - sd[i / Size()] &= ~(1UL << (i % Size())); // annihilate ith orbital - } - - for (std::size_t a : creators) { - // sd = sd | (1UL << a); // create ath orbital - sd[a / Size()] |= (1UL << (a % Size())); // create ath orbital - // if (sd == 0) { - if (!((sd[a / Size()] >> (a % Size())) & 1)) { - //print sd - std::cout << "Creator: " << a << std::endl; - for (int k = 0; k < sd.size(); ++k) { - std::cout << sd[k] << " "; - } - std::cout << std::endl; - throw std::invalid_argument("Given Slater determinant cannot be excited using the given creators and annihilators."); - } - sign *= sign_swap(sd, a, 0); - } - return sign; -} @@ -295,11 +1682,11 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) nparam = nocc_up * (nbasis - nocc_up); //paired-doubles nparam += wfn_.nocc * (wfn_.nbasis - wfn_.nocc); // beta singles - ovlp.resize(nconn); - d_ovlp.resize(nconn * nparam); + // ovlp.resize(nconn); + // d_ovlp.resize(nconn * nparam); det_exc_param_indx.resize(nconn); - std::size_t nword = (ulong)wfn_.nword; + // std::size_t nword = (ulong)wfn_.nword; long nb = wfn_.nbasis; long nocc = wfn_.nocc; @@ -327,7 +1714,7 @@ void AP1roGeneralizedSenoObjective::init_overlap(const NonSingletCI &wfn_) std::vector particles; // Collect holes and particles - for (std::size_t iword = 0; iword != nword; ++iword) + for (std::size_t iword = 0; iword != nword; ++iword) { word = rdet[iword] ^ det[iword]; //str for excitation hword = word & rdet[iword]; //str for hole @@ -489,62 +1876,62 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector -void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { - p_permanent.resize(nconn); - s_permanent.resize(nconn); - //print x - for (std::size_t i = 0; i < nparam; ++i) { - std::cout << x[i] << " "; - } - std::cout << "\n" << std::endl; +// void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { +// p_permanent.resize(nconn); +// s_permanent.resize(nconn); +// //print x +// for (std::size_t i = 0; i < nparam; ++i) { +// std::cout << x[i] << " "; +// } +// std::cout << "\n" << std::endl; - for (std::size_t idet = 0; idet != ndet; ++idet) { +// for (std::size_t idet = 0; idet != ndet; ++idet) { - if (idet < det_exc_param_indx.size()) { - // Access the excitation parameter indices - const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; - double pair_permanent = 1.0; - double single_permanent = 1.0; - - if (exc_info.pair_inds[0] != -1) { - if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { - std::cerr << "Error calculating pair_permanent for idet" << idet << "\n" << std::endl; - } - } +// if (idet < det_exc_param_indx.size()) { +// // Access the excitation parameter indices +// const DetExcParamIndx& exc_info = det_exc_param_indx[idet]; +// double pair_permanent = 1.0; +// double single_permanent = 1.0; + +// if (exc_info.pair_inds[0] != -1) { +// if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { +// std::cerr << "Error calculating pair_permanent for idet" << idet << "\n" << std::endl; +// } +// } - if (exc_info.single_inds[0] != -1) { - if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { - std::cerr << "Error calculating single_permanent for idet " << idet << "\n" << std::endl; - } - } - // If given det is not allowed in the wfn, set the permanents to zero - // idet = 0 is the reference HF determinant - if (exc_info.pair_inds[0] == -1 && exc_info.single_inds[0] == -1 && idet != 0) { - pair_permanent = 0.0; - single_permanent = 0.0; - } - - p_permanent[idet] = pair_permanent; - s_permanent[idet] = single_permanent; - - - if (y != nullptr && idet < ndet) { - y[idet] = exc_info.sign * pair_permanent * single_permanent; - if (idet < 225) { - std::cout << idet << " " << exc_info.det[0] << " " << y[idet] << std::endl; - } - }else { - std::cerr << "y is nullptr or idet is out of bounds" << std::endl; - } - } else { - std::cout << "idet" << idet << " not found in storage" << std::endl; - y[idet] = 0.0; - s_permanent[idet] = 0.0; - p_permanent[idet] = 0.0; - } - } -} +// if (exc_info.single_inds[0] != -1) { +// if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { +// std::cerr << "Error calculating single_permanent for idet " << idet << "\n" << std::endl; +// } +// } +// // If given det is not allowed in the wfn, set the permanents to zero +// // idet = 0 is the reference HF determinant +// if (exc_info.pair_inds[0] == -1 && exc_info.single_inds[0] == -1 && idet != 0) { +// pair_permanent = 0.0; +// single_permanent = 0.0; +// } + +// p_permanent[idet] = pair_permanent; +// s_permanent[idet] = single_permanent; + + +// if (y != nullptr && idet < ndet) { +// y[idet] = exc_info.sign * pair_permanent * single_permanent; +// if (idet < 225) { +// std::cout << idet << " " << exc_info.det[0] << " " << y[idet] << " " << exc_info.sign << std::endl; +// } +// }else { +// std::cerr << "y is nullptr or idet is out of bounds" << std::endl; +// } +// } else { +// std::cout << "idet" << idet << " not found in storage" << std::endl; +// y[idet] = 0.0; +// s_permanent[idet] = 0.0; +// p_permanent[idet] = 0.0; +// } +// } +// } void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ @@ -602,3 +1989,218 @@ void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x } // namespace pyci + + +// std::vector> AP1roGeneralizedSenoObjective::int_partition_dp(const std::vector& coins, std::size_t total){ +// // Coin change problem +// std::vector>> dp(total +1); + +// for (std::size_t coin : coins) { +// for (std::size_t i = coin; i <= total; ++i) { +// for (const auto& partition : dp[i - coin]) { +// auto new_partition = partition; +// new_partition.push back(coin); +// dp[i].push_back(new_partition); +// } +// } +// } +// return dp[total]; +// } + + +// // Assign excitation operators +// std::unordered_map, int> AP1roGeneralizedSenoObjective::assign_exops( +// const std::vector& ranks, +// int nspin){ +// // const std::vector>* indices) { + +// std::unordered_map, int> exops; +// int counter = 0; +// std::cout << "****Ranks: "; +// for (int rank : ranks) { +// std::cout << rank << " "; +// } +// std::cout << std::endl; +// std::cout << "****nspin: " << nspin << std::endl; + + // if (indices == nullptr) { + // // Generate all possible excitation operators consistent with the ranks + // for (int rank : ranks) { + // std::vector> ann_combs; + // std::vector temp; + // generateCombinations(std::vector(nspin), rank, 0, temp, ann_combs); + + // for (const auto& annhs : ann_combs) { + // std::vector remaining; + // for (int i = 0; i < nspin; ++i) { + // if (std::find(annhs.begin(), annhs.end(), i) == annhs.end()) { + // remaining.push_back(i); + // } + // } + // std::vector> crea_combs; + // generateCombinations(remaining, rank, 0, temp, crea_combs); + + // for (const auto& crea : crea_combs) { + // std::vector exop(annhs); + // exop.insert(exop.end(), crea.begin(), crea.end()); + // exops[exop] = counter++; + // } + // } + // } + + // } else { + // // Validate the indices + // if (indices->size() != 2) { + // throw std::invalid_argument("`indices` must have exactly 2 elements."); + // } + + // for (const auto& inds : *indices) { + // if (!std::all_of(inds.begin(), inds.end(), [](int i) { return i >= 0 ; })) { + // throw std::invalid_argument("All `indices` must be non-negative integers."); + // } + // } + + // std::vector ex_from = indices->at(0); + // std::vector ex_to = indices->at(1); + + // // Remove duplicates and sort + // std::sort(ex_from.begin(), ex_from.end()); + // ex_from.erase(std::unique(ex_from.begin(), ex_from.end()), ex_from.end()); + // std::sort(ex_to.begin(), ex_to.end()); + // ex_to.erase(std::unique(ex_to.begin(), ex_to.end()), ex_to.end()); + + // // Generate excitaion operators based on `indices` + // for (int rank : ranks) { + // std::vector> ann_combs; + // std::vector temp; + // generateCombinations(ex_from, rank, 0, temp, ann_combs); + + // for (const auto& annh: ann_combs) { + // std::vector> crea_combs; + // generateCombinations(ex_to, rank, 0, temp, crea_combs); + + // for (const auto& crea : crea_combs) { + // std::vector op(annh); + // op.insert(op.end(), crea.begin(), crea.end()); + // exops[op] = counter++; + // } + // } + // } + // } +// for (int rank : ranks) { +// std::vector> ann_combs; +// std::vector temp; +// generateCombinations(std::vector(nspin), rank, 0, temp, ann_combs); + +// for (const auto& annhs : ann_combs) { +// std::vector remaining; +// for (int i = 0; i < nspin; ++i) { +// if (std::find(annhs.begin(), annhs.end(), i) == annhs.end()) { +// remaining.push_back(i); +// } +// } +// std::vector> crea_combs; +// generateCombinations(remaining, rank, 0, temp, crea_combs); + +// for (const auto& crea : crea_combs) { +// std::vector exop(annhs); +// exop.insert(exop.end(), crea.begin(), crea.end()); +// exops[exop] = counter++; +// } +// } +// } +// std::cout << "****Exops: "; +// for (const auto& exop : exops) { +// std::cout << "{ "; +// for (int i : exop.first) { +// std::cout << i << " "; +// } +// std::cout << "} :"; +// std::cout << exop.second << " "; +// std::cout << std::endl; +// } +// return exops; + +// } + +// // Function to assign exops and sort keys +// void AP1roGeneralizedSenoObjective::assign_and_sort_exops(const std::vector& ranks, +// int nspin){ //, const std::vector>* indices) { +// std::cout << "Assigning and sorting excitation operators...\n"; +// exops = assign_exops(ranks, nspin); //, indices); +// std::cout << "Assigned " << exops.size() << " excitation operators.\n"; +// ind_exops.clear(); +// for (const auto& pair : exops) { +// ind_exops.push_back(pair.first); +// } +// std::sort(ind_exops.begin(), ind_exops.end(), [this](const std::vector& a, const std::vector& b) { +// return exops[a] < exops[b]; +// }); +// std::cout << "Sorted excitation operators.\n"; +// std::cout << "Exops: "; +// for (const auto& exop : ind_exops) { +// std::cout << "{ "; +// for (int i : exop) { +// std::cout << i << " "; +// } +// std::cout << "} "; +// } +// } + + + +// generate unordered partition + // // Flatten the bin_config + // std::vector> bin_config; + // // for (const auto& [bin_size, bin_count] : bin_size_num) { + // for (const auto& bins : bin_size_num) { + // const auto& bin_size = bins.first; + // const auto& bin_count = bins.second; + // for (int i = 0; i < bin_count; ++i) { + // bin_config.emplace_back(bin_size, 1); + // } + // } + // std::vector>> results; + // std::vector> current_partition; + // helper_generate_partitions(collection, bin_config, 0, current_partition, results); + + +// void AP1roGeneralizedSenoObjective::helper_generate_partitions( +// const std::vector collection, +// std::vector>& bin_config, +// std::vector>::size_type bin_idx, +// std::vector>& current_partition, +// std::vector>>& results) { +// if (bin_idx == bin_config.size()) { +// results.push_back(current_partition); +// return; +// } + +// int bin_size = bin_config[bin_idx].first; +// // int bin_count = bin_config[bin_idx].second; + +// // Generate all combinations for the current bin size +// std::vector> all_combs; +// std::vector current_comb; +// generateCombinations(collection, bin_size, 0, current_comb, all_combs); + +// // Duplicate combinations +// std::set> unique_combs(all_combs.begin(), all_combs.end()); + +// for (const auto& bin : unique_combs) { +// // Enforce bin ordering; First element of the current bin +// // must be >= the first element of the previous bin (if any) +// if (!current_partition.empty() && current_partition.back()[0] > bin[0]) { +// continue; +// } + +// std::vector remaining_elements(collection.begin(), collection.end()); +// for (int elem : bin) { +// remaining_elements.erase(std::remove(remaining_elements.begin(), remaining_elements.end(), elem), remaining_elements.end()); +// } + +// current_partition.push_back(bin); +// helper_generate_partitions(remaining_elements, bin_config, bin_idx + 1, current_partition, results); +// current_partition.pop_back(); +// } +// } \ No newline at end of file From 5fed888f35d62d40e3b0231cd2f633fe0560b7f5 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Mon, 17 Feb 2025 21:59:15 -0500 Subject: [PATCH 192/197] Added deriv function for implementation approach same as fanpy --- pyci/src/ap1rogen.cpp | 317 +++++++++++++++++++++++++++++++++++------- 1 file changed, 266 insertions(+), 51 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index d666aca..488e522 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -1060,7 +1060,7 @@ double AP1roGeneralizedSenoObjective::product_amplitudes_multi( for (const auto& exc_inds : inds_multi) { // std::cout << "Processing exc_inds\n"; - std::size_t exc_order = exc_inds.first; + // std::size_t exc_order = exc_inds.first; const std::vector> inds_sign = exc_inds.second; // std::cout << "Exc_order: " << exc_order << std::endl; @@ -1181,6 +1181,71 @@ double AP1roGeneralizedSenoObjective::product_amplitudes_multi( // return output; } +std::vector AP1roGeneralizedSenoObjective::product_ampli_multi_deriv( + const std::unordered_map>>& indices_multi, + bool deriv, const double* params){ + std::vector output(nparam, 0.0); + if (!deriv) { + throw std::invalid_argument("Deriv must be enabled for this function."); + } + + for (const auto& indices_sign : indices_multi) { + const auto& indices = indices_sign.second; + std::vector signs(indices.size()); + std::transform(indices.begin(), indices.end(), signs.begin(), [](const std::vector& row) { + return row.back() > 1 ? -1 : row.back(); + }); + + std::set unique_indices; + for (const auto& row : indices) { + unique_indices.insert(row.begin(), row.end() - 1); + } + + for (int ind : unique_indices) { + std::vector bool_indices(indices.size()); + std::transform(indices.begin(), indices.end(), bool_indices.begin(), [ind](const std::vector& row) { + return std::find(row.begin(), row.end() - 1, ind) != row.end() - 1; + }); + + std::vector row_inds(indices.size()); + std::transform(bool_indices.begin(), bool_indices.end(), row_inds.begin(), [](bool b) { return b; }); + + std::vector> selected_params(indices.size()); + for (std::size_t i = 0; i < indices.size(); ++i) { + selected_params[i].resize(indices[i].size() - 1); + for (std::size_t j = 0; j < indices[i].size() - 1; ++j) { + selected_params[i][j] = params[indices[i][j]]; + } + } + + std::vector old_params(selected_params.size()); + for (std::size_t i = 0; i < selected_params.size(); ++i) { + if (bool_indices[i]) { + old_params[i] = selected_params[i][0]; + selected_params[i][0] = 1.0; + } + } + + for (std::size_t i = 0; i < row_inds.size(); ++i) { + if (row_inds[i]) { + double prod = 1.0; + for (std::size_t j = 0; j < selected_params[i].size(); ++j) { + prod *= selected_params[i][j]; + } + output[ind] += prod * signs[i]; + } + } + + for (std::size_t i = 0; i < selected_params.size(); ++i) { + if (bool_indices[i]) { + selected_params[i][0] = old_params[i]; + } + } + } + } + return output; +} + int AP1roGeneralizedSenoObjective::sign_swap(AlignedVector sd, long pos_current, long pos_future){ // Return the signature of applying annihilators then creators to the Slater determinant. if (pos_current < 0 || pos_future < 0) { @@ -1275,6 +1340,8 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double* x, d // return; } + det_ac_inds.resize(nconn); + for (std::size_t idet = 0; idet != ndet; ++idet) { // std::cout << "\n-----Processing idet = " << idet << "\n"; y[idet] = 0.0; @@ -1313,6 +1380,20 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double* x, d std::vector holes; std::vector particles; + // Container to save annhiliation and creation indices, and sign + DetExcParamIndx ac_info; + ac_info.det.resize(nword); + ac_info.pair_inds.resize(1); // for annhilation indices + ac_info.single_inds.resize(1); // for creation indices + + // Default values for indices + ac_info.pair_inds[0] = -1; + ac_info.single_inds[0] = -1; + ac_info.sign = 1; + + // Storing current det + std::memcpy(&ac_info.det[0], &det[0], sizeof(ulong) * nword); + // Collect holes and particles for (std::size_t iword = 0; iword != nword; ++iword) { @@ -1337,6 +1418,7 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double* x, d } } + // Sen-o processing // Check if annhiliation and creation operators are in the exop_combinations std::pair, std::vector> key = std::make_pair(holes, particles); @@ -1493,24 +1575,46 @@ void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double* x, d amplitudes = product_amplitudes_multi(inds_multi, false, x); // double amplitudes = std::get(amplitudes_variant); int sign = sign_excite(rdet, holes, particles); + ac_info.sign = sign; y[idet] = sign * amplitudes; // std::cout << "Amplitudes: " ; std::cout << amplitudes << ",," << sign << std::endl; // std::cout << "Sign: " <<; - + + + } else{ std::unordered_map>> inds_multi = exop_combs[key]; auto amplitudes = product_amplitudes_multi(inds_multi, false, x); int sign = sign_excite(rdet, holes, particles); + ac_info.sign = sign; std::cout << amplitudes << ",," << sign << std::endl; y[idet] = sign * amplitudes; } + // Store the annihilation and creation indices and sign + if (holes.size() > 0 && particles.size() > 0) { + // std::cout << "Storing annihilation and creation indices\n"; + std::vector holes_long(holes.begin(), holes.end()); + std::vector particles_long(particles.begin(), particles.end()); + ac_info.pair_inds.clear(); + ac_info.single_inds.clear(); + ac_info.pair_inds = holes_long; + ac_info.single_inds = particles_long; + + // Ensure det_ac_inds has enough space + ensure_struct_size(det_ac_inds, idet+1); + det_ac_inds[idet] = ac_info; + // std::cout << "storing done\n"; + } + } else if (are_same) { y[idet] = 1.0; + det_ac_inds[idet] = ac_info; } else { y[idet] = 0.0; + det_ac_inds[idet] = ac_info; } @@ -1874,6 +1978,117 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector } +void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, double* y) { + std::cout << "-------Computing Derivative\n nbasis: " << nbasis << ", ndet: " << ndet << "\n" ; + for (std::size_t idet = 0; idet< ndet; idet++) { + // Ensure we have annhiliation and creation indices for this determinant + if (idet < det_ac_inds.size()) { + std::cout << "Processing idet: " << idet << std::endl; + const DetExcParamIndx ac_info = det_ac_inds[idet]; + + std::cout << "pair_inds: "; + for (long i : ac_info.pair_inds) { + std::cout << i << " "; + } + std::cout << std::endl; + std::cout << "single_inds: "; + for (long i : ac_info.single_inds) { + std::cout << i << " "; + } + std::cout << std::endl; + + // if reference determinant, set the derivative to zero + if (ac_info.pair_inds[0] == -1 && ac_info.single_inds[0] == -1) { + std::cout << "Reference determinant\n"; + for (std::size_t iparam = 0; iparam < nparam; ++iparam) { + y[idet * nparam + iparam] = 0.0; + } + continue; + } else { + // std::vector a_inds = ac_info.pair_inds; //annihilation indices + // std::vector c_inds = ac_info.single_inds; //creation indices + // std::vector combined_inds = a_inds; + std::vector a_inds(ac_info.pair_inds.begin(), ac_info.pair_inds.end()); + std::vector c_inds(ac_info.single_inds.begin(), ac_info.single_inds.end()); + std::pair, std::vector> key = std::make_pair(a_inds, c_inds); + + // combined_inds.insert(combined_inds.end(), c_inds.begin(), c_inds.end()); + if (exop_combs.find(key) == exop_combs.end()) { + generate_possible_exops(a_inds, c_inds); + } + + auto& inds_multi = exop_combs[key]; + AlignedVector det = ac_info.det; + const int sign = ac_info.sign; + std::vector occs(nocc); + fill_occs(nword, det.data(), &occs[0]); + + for (auto& exc_order : inds_multi) { + auto& indices_sign = exc_order.second; + std::vector> selected_rows; + + std::cout << "exc_order: " << exc_order.first << std::endl; + + for (std::size_t row_ind = 0; row_ind < indices_sign.size(); ++row_ind) { + const auto& row = indices_sign[row_ind]; + std::set trash; + bool skip_row = false; + + for (const auto& exop_index : row) { + const auto& exop = ind_exops[exop_index]; + if (exop.size() == 2) { + if (trash.find(exop[0]) != trash.end()) { + skip_row = true; + break; + } + if (exop[0] < static_cast(nbasis / 2)) { + if (std::find(occs.begin(), occs.end(), exop[0] + static_cast(nbasis / 2)) == occs.end()) { + skip_row = true; + break; + } else { + trash.insert(exop[0]); + trash.insert(exop[0] + static_cast(nbasis / 2)); + } + } else { + if (std::find(occs.begin(), occs.end(), exop[0] - static_cast(nbasis / 2)) == occs.end()) { + skip_row = true; + break; + } else { + trash.insert(exop[0]); + trash.insert(exop[0] - static_cast(nbasis / 2)); + } + } + } else { + for (std::size_t j = 0; j < exop.size() / 2; ++j) { + if (trash.find(exop[j]) != trash.end()) { + skip_row = true; + break; + } else { + trash.insert(exop[j]); + } + } + if (skip_row) break; + } + } + if (!skip_row) { + selected_rows.push_back(row); + } + } + indices_sign = selected_rows; + inds_multi[exc_order.first] = indices_sign; + } + std::vector damplitudes = product_ampli_multi_deriv(inds_multi, true, x); + for (std::size_t iparam = 0; iparam < nparam; ++iparam) { + y[idet * nparam + iparam] = sign * damplitudes[iparam]; + } + + + + } + } + } +} + // void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { @@ -1934,63 +2149,63 @@ double AP1roGeneralizedSenoObjective::compute_derivative(const std::vector // } -void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - - for (std::size_t idet = 0; idet != ndet; ++idet) { - // Ensure we have the excitation parameters for this determinant - if (idet < det_exc_param_indx.size()) { - const DetExcParamIndx exc_info = det_exc_param_indx[idet]; - double pair_permanent = 1.0; - double single_permanent = 1.0; - if (idet < s_permanent.size() && idet < p_permanent.size()) { - pair_permanent = p_permanent[idet]; - single_permanent = s_permanent[idet]; - } - // else { - // if (exc_info.pair_inds[0] != -1) { - // if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { - // std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; - // } - // } +// void AP1roGeneralizedSenoObjective::d_overlap(const size_t ndet, const double *x, double *y){ - // if (exc_info.single_inds[0] != -1) { - // if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { - // std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; - // } - // } +// for (std::size_t idet = 0; idet != ndet; ++idet) { +// // Ensure we have the excitation parameters for this determinant +// if (idet < det_exc_param_indx.size()) { +// const DetExcParamIndx exc_info = det_exc_param_indx[idet]; +// double pair_permanent = 1.0; +// double single_permanent = 1.0; +// if (idet < s_permanent.size() && idet < p_permanent.size()) { +// pair_permanent = p_permanent[idet]; +// single_permanent = s_permanent[idet]; +// } +// // else { +// // if (exc_info.pair_inds[0] != -1) { +// // if (!permanent_calculation(exc_info.pair_inds, x, pair_permanent)) { +// // std::cerr << "Error calculating pair_permanent for idet" << idet << std::endl; +// // } +// // } + +// // if (exc_info.single_inds[0] != -1) { +// // if (!permanent_calculation(exc_info.single_inds, x, single_permanent)) { +// // std::cerr << "Error calculating single_permanent for idet " << idet << std::endl; +// // } +// // } - // } +// // } - for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - double dpair = 0.0; - double dsingle = 0.0; - if (exc_info.single_inds[0] != -1) { - dsingle = compute_derivative(exc_info.single_inds, x, iparam); - } +// for (std::size_t iparam = 0; iparam < nparam; ++iparam) { +// double dpair = 0.0; +// double dsingle = 0.0; +// if (exc_info.single_inds[0] != -1) { +// dsingle = compute_derivative(exc_info.single_inds, x, iparam); +// } - if (exc_info.pair_inds[0] != -1) { - dpair = compute_derivative(exc_info.pair_inds, x, iparam); - } - // std::cout << "\nidet: " << idet << ", det: " << exc_info.det[0] << std::endl; - // std::cout << "single_inds: " << exc_info.single_inds[0] << ", pair_inds: " << exc_info.pair_inds[0] << std::endl; - // std::cout << "single_permanent: " << single_permanent << ", pair_permanent: " << pair_permanent << std::endl; - // std::cout << "wrt iparam: " << iparam << ", dpair: " << dpair << ", dsingle: " << dsingle << std::endl; - // std::cout << "idet: " << idet << " deriv: " << dpair * single_permanent + dsingle * pair_permanent << std::endl; - y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; - } - } - else { - for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - y[ndet * iparam + idet] = 0.0; - } - } - } -} +// if (exc_info.pair_inds[0] != -1) { +// dpair = compute_derivative(exc_info.pair_inds, x, iparam); +// } +// // std::cout << "\nidet: " << idet << ", det: " << exc_info.det[0] << std::endl; +// // std::cout << "single_inds: " << exc_info.single_inds[0] << ", pair_inds: " << exc_info.pair_inds[0] << std::endl; +// // std::cout << "single_permanent: " << single_permanent << ", pair_permanent: " << pair_permanent << std::endl; +// // std::cout << "wrt iparam: " << iparam << ", dpair: " << dpair << ", dsingle: " << dsingle << std::endl; +// // std::cout << "idet: " << idet << " deriv: " << dpair * single_permanent + dsingle * pair_permanent << std::endl; +// y[ndet * iparam + idet] = dpair * single_permanent + dsingle * pair_permanent; +// } +// } +// else { +// for (std::size_t iparam = 0; iparam < nparam; ++iparam) { +// y[ndet * iparam + idet] = 0.0; +// } +// } +// } +// } } // namespace pyci - +//---------------------------ROUGH WORK-------------------------------------------- // std::vector> AP1roGeneralizedSenoObjective::int_partition_dp(const std::vector& coins, std::size_t total){ // // Coin change problem // std::vector>> dp(total +1); From 99f668c6a5e6643ee8b4809cbf8f07b16b04b3a1 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Tue, 18 Feb 2025 21:03:43 -0500 Subject: [PATCH 193/197] update add row function for NonSingletCI --- pyci/src/sparseop.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pyci/src/sparseop.cpp b/pyci/src/sparseop.cpp index 5943e31..6b0a24a 100644 --- a/pyci/src/sparseop.cpp +++ b/pyci/src/sparseop.cpp @@ -535,8 +535,10 @@ void SparseOp::add_row(const SQuantOp &ham, const GenCIWfn &wfn, const long idet void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long idet, ulong *det_up, long *occs, long *virs) { - long n = wfn.nbasis / 2; - long n1 = wfn.nbasis; + long n = wfn.nbasis / 2; // nspatial + long n1 = wfn.nbasis; // nspin + + // std::cout << "n: " << n << ", n1: " << n1 << std::endl; long n2 = n1 * n1; long n3 = n1 * n2; @@ -554,6 +556,9 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long long nvir_up = n - nocc_up; long nvir_dn = n - nocc_dn; long nvir = nvir_up + nvir_dn; + + // std::cout << "nocc_up: " << nocc_up << ", nocc_dn: " << nocc_dn << ", nvir_up: " << nvir_up << ", nvir_dn: " << nvir_dn << std::endl; + long *virs_up = virs; long *virs_dn = nullptr; for (long i = 0; i < nvir; ++i) { @@ -613,7 +618,7 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long } // loop over spin-up occupied indices - for (k = 0; k < nocc_up; ++k) { + for (k = i+1; k < nocc_up; ++k) { kk = occs_up[k]; koffset = ioffset + n2 * kk; // second excitation: alpha -> alpha @@ -641,7 +646,6 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long // second excitation: beta -> beta for (l = 0; l < nvir_dn; ++l) { ll = virs_dn[l]; - kk = occs_dn[k]; excite_det(kk, ll, det_up); jdet = wfn.index_det(det_up); // check if the excited determinant is in wfn @@ -652,10 +656,8 @@ void SparseOp::add_row(const SQuantOp &ham, const NonSingletCI &wfn, const long append(indices, jdet); } excite_det(ll, kk, det_up); - excite_det(ll, kk, det_up); } - } - + } excite_det(jj, ii, det_up); } } From afc6c4786eaa8ee48c072695add9e3062913e65a Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 19 Feb 2025 19:59:31 -0500 Subject: [PATCH 194/197] Clean up the commented extra optional codes --- pyci/src/ap1rogen.cpp | 310 +++++++++--------------------------------- 1 file changed, 64 insertions(+), 246 deletions(-) diff --git a/pyci/src/ap1rogen.cpp b/pyci/src/ap1rogen.cpp index 488e522..45037f2 100644 --- a/pyci/src/ap1rogen.cpp +++ b/pyci/src/ap1rogen.cpp @@ -1983,33 +1983,24 @@ void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, for (std::size_t idet = 0; idet< ndet; idet++) { // Ensure we have annhiliation and creation indices for this determinant if (idet < det_ac_inds.size()) { - std::cout << "Processing idet: " << idet << std::endl; + std::cout << "\n**Processing idet: " << idet ; const DetExcParamIndx ac_info = det_ac_inds[idet]; - - std::cout << "pair_inds: "; - for (long i : ac_info.pair_inds) { - std::cout << i << " "; - } - std::cout << std::endl; - std::cout << "single_inds: "; - for (long i : ac_info.single_inds) { - std::cout << i << " "; - } + + std::cout << " " ; + for (std::size_t k = 0; k < nword; k++) { + std::cout << ac_info.det[k]; } std::cout << std::endl; // if reference determinant, set the derivative to zero if (ac_info.pair_inds[0] == -1 && ac_info.single_inds[0] == -1) { - std::cout << "Reference determinant\n"; + std::cout << "Processing reference determinant\n"; for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - y[idet * nparam + iparam] = 0.0; + y[ndet * iparam + idet] = 0.0; } continue; } else { - // std::vector a_inds = ac_info.pair_inds; //annihilation indices - // std::vector c_inds = ac_info.single_inds; //creation indices - // std::vector combined_inds = a_inds; - std::vector a_inds(ac_info.pair_inds.begin(), ac_info.pair_inds.end()); - std::vector c_inds(ac_info.single_inds.begin(), ac_info.single_inds.end()); + std::vector a_inds(ac_info.pair_inds.begin(), ac_info.pair_inds.end()); //annihilation indices + std::vector c_inds(ac_info.single_inds.begin(), ac_info.single_inds.end()); //creation indices std::pair, std::vector> key = std::make_pair(a_inds, c_inds); // combined_inds.insert(combined_inds.end(), c_inds.begin(), c_inds.end()); @@ -2023,37 +2014,65 @@ void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, std::vector occs(nocc); fill_occs(nword, det.data(), &occs[0]); - for (auto& exc_order : inds_multi) { - auto& indices_sign = exc_order.second; + for (auto& pair : inds_multi) { + auto& indices_sign = pair.second; std::vector> selected_rows; - std::cout << "exc_order: " << exc_order.first << std::endl; + // std::cout << "exc_order: " << pair.first << std::endl; - for (std::size_t row_ind = 0; row_ind < indices_sign.size(); ++row_ind) { - const auto& row = indices_sign[row_ind]; - std::set trash; + for (const auto& row : indices_sign) { + std::cout << "Row: "; + std::cout << "["; + for (int i : row) { + std::cout << i << " "; + } + std::cout << "]" << std::endl; + + std::unordered_set trash; bool skip_row = false; + + // for (const auto& exop_indx : row) { + for (auto it = row.begin(); it != row.end() - 1; ++it) { + const auto& exop_index = *it; - for (const auto& exop_index : row) { + // Check if exop_indx is a valid index + if (exop_index < 0 || static_cast(exop_index) >= ind_exops.size()) { + std::cout << "ind_exops.size(): " << ind_exops.size() << std::endl; + std::cerr << "Error: exop_index " << exop_index << " is out of bounds" << std::endl; + continue; + } const auto& exop = ind_exops[exop_index]; + + // std::cout << "exop_index: " << exop_index << std::endl; + // std::cout << "exop: "; + // for (long i : exop) { + // std::cout << i << " "; + // } + // std::cout << std::endl; + if (exop.size() == 2) { if (trash.find(exop[0]) != trash.end()) { + // std::cout << "exop[0] already in trash\n"; skip_row = true; break; } if (exop[0] < static_cast(nbasis / 2)) { if (std::find(occs.begin(), occs.end(), exop[0] + static_cast(nbasis / 2)) == occs.end()) { skip_row = true; + // std::cout << "exop[0] + nbasis / 2 not in occs\n"; break; } else { + // std::cout << "exop[0] + nbasis / 2 in occs\n"; trash.insert(exop[0]); trash.insert(exop[0] + static_cast(nbasis / 2)); } } else { if (std::find(occs.begin(), occs.end(), exop[0] - static_cast(nbasis / 2)) == occs.end()) { skip_row = true; + // std::cout << "exop[0] - nbasis / 2 not in occs\n"; break; } else { + // std::cout << "exop[0] - nbasis / 2 in occ\n"; trash.insert(exop[0]); trash.insert(exop[0] - static_cast(nbasis / 2)); } @@ -2061,6 +2080,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, } else { for (std::size_t j = 0; j < exop.size() / 2; ++j) { if (trash.find(exop[j]) != trash.end()) { + std::cout << "exop[j] already in trash\n"; skip_row = true; break; } else { @@ -2074,15 +2094,27 @@ void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, selected_rows.push_back(row); } } + + std::cout << "Selected: "; + for (const auto& row : selected_rows) { + std::cout << "["; + for (int i : row) { + std::cout << i << " "; + } + std::cout << "]" << std::endl; + } + std::cout << std::endl; + indices_sign = selected_rows; - inds_multi[exc_order.first] = indices_sign; + inds_multi[pair.first] = indices_sign; } std::vector damplitudes = product_ampli_multi_deriv(inds_multi, true, x); for (std::size_t iparam = 0; iparam < nparam; ++iparam) { - y[idet * nparam + iparam] = sign * damplitudes[iparam]; - } - - + y[ndet * iparam + idet] = sign * damplitudes[iparam]; + if (damplitudes[iparam] != 0.0) { + std::cout << "iparam: " << iparam << ", dampli: " << damplitudes[iparam] << ", sign: " << sign << std::endl; + } + } } } @@ -2090,7 +2122,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, } - +//-------------------------------------FIRST APPROACH BEGIN------------------------------------------------------------------------- // void AP1roGeneralizedSenoObjective::overlap(std::size_t ndet, const double *x, double *y) { // p_permanent.resize(nconn); // s_permanent.resize(nconn); @@ -2201,221 +2233,7 @@ void AP1roGeneralizedSenoObjective::d_overlap(std::size_t ndet, const double* x, // } // } // } +//-------------------------------------FIRST APPROACH END------------------------------------------------------------------------- } // namespace pyci - -//---------------------------ROUGH WORK-------------------------------------------- -// std::vector> AP1roGeneralizedSenoObjective::int_partition_dp(const std::vector& coins, std::size_t total){ -// // Coin change problem -// std::vector>> dp(total +1); - -// for (std::size_t coin : coins) { -// for (std::size_t i = coin; i <= total; ++i) { -// for (const auto& partition : dp[i - coin]) { -// auto new_partition = partition; -// new_partition.push back(coin); -// dp[i].push_back(new_partition); -// } -// } -// } -// return dp[total]; -// } - - -// // Assign excitation operators -// std::unordered_map, int> AP1roGeneralizedSenoObjective::assign_exops( -// const std::vector& ranks, -// int nspin){ -// // const std::vector>* indices) { - -// std::unordered_map, int> exops; -// int counter = 0; -// std::cout << "****Ranks: "; -// for (int rank : ranks) { -// std::cout << rank << " "; -// } -// std::cout << std::endl; -// std::cout << "****nspin: " << nspin << std::endl; - - // if (indices == nullptr) { - // // Generate all possible excitation operators consistent with the ranks - // for (int rank : ranks) { - // std::vector> ann_combs; - // std::vector temp; - // generateCombinations(std::vector(nspin), rank, 0, temp, ann_combs); - - // for (const auto& annhs : ann_combs) { - // std::vector remaining; - // for (int i = 0; i < nspin; ++i) { - // if (std::find(annhs.begin(), annhs.end(), i) == annhs.end()) { - // remaining.push_back(i); - // } - // } - // std::vector> crea_combs; - // generateCombinations(remaining, rank, 0, temp, crea_combs); - - // for (const auto& crea : crea_combs) { - // std::vector exop(annhs); - // exop.insert(exop.end(), crea.begin(), crea.end()); - // exops[exop] = counter++; - // } - // } - // } - - // } else { - // // Validate the indices - // if (indices->size() != 2) { - // throw std::invalid_argument("`indices` must have exactly 2 elements."); - // } - - // for (const auto& inds : *indices) { - // if (!std::all_of(inds.begin(), inds.end(), [](int i) { return i >= 0 ; })) { - // throw std::invalid_argument("All `indices` must be non-negative integers."); - // } - // } - - // std::vector ex_from = indices->at(0); - // std::vector ex_to = indices->at(1); - - // // Remove duplicates and sort - // std::sort(ex_from.begin(), ex_from.end()); - // ex_from.erase(std::unique(ex_from.begin(), ex_from.end()), ex_from.end()); - // std::sort(ex_to.begin(), ex_to.end()); - // ex_to.erase(std::unique(ex_to.begin(), ex_to.end()), ex_to.end()); - - // // Generate excitaion operators based on `indices` - // for (int rank : ranks) { - // std::vector> ann_combs; - // std::vector temp; - // generateCombinations(ex_from, rank, 0, temp, ann_combs); - - // for (const auto& annh: ann_combs) { - // std::vector> crea_combs; - // generateCombinations(ex_to, rank, 0, temp, crea_combs); - - // for (const auto& crea : crea_combs) { - // std::vector op(annh); - // op.insert(op.end(), crea.begin(), crea.end()); - // exops[op] = counter++; - // } - // } - // } - // } -// for (int rank : ranks) { -// std::vector> ann_combs; -// std::vector temp; -// generateCombinations(std::vector(nspin), rank, 0, temp, ann_combs); - -// for (const auto& annhs : ann_combs) { -// std::vector remaining; -// for (int i = 0; i < nspin; ++i) { -// if (std::find(annhs.begin(), annhs.end(), i) == annhs.end()) { -// remaining.push_back(i); -// } -// } -// std::vector> crea_combs; -// generateCombinations(remaining, rank, 0, temp, crea_combs); - -// for (const auto& crea : crea_combs) { -// std::vector exop(annhs); -// exop.insert(exop.end(), crea.begin(), crea.end()); -// exops[exop] = counter++; -// } -// } -// } -// std::cout << "****Exops: "; -// for (const auto& exop : exops) { -// std::cout << "{ "; -// for (int i : exop.first) { -// std::cout << i << " "; -// } -// std::cout << "} :"; -// std::cout << exop.second << " "; -// std::cout << std::endl; -// } -// return exops; - -// } - -// // Function to assign exops and sort keys -// void AP1roGeneralizedSenoObjective::assign_and_sort_exops(const std::vector& ranks, -// int nspin){ //, const std::vector>* indices) { -// std::cout << "Assigning and sorting excitation operators...\n"; -// exops = assign_exops(ranks, nspin); //, indices); -// std::cout << "Assigned " << exops.size() << " excitation operators.\n"; -// ind_exops.clear(); -// for (const auto& pair : exops) { -// ind_exops.push_back(pair.first); -// } -// std::sort(ind_exops.begin(), ind_exops.end(), [this](const std::vector& a, const std::vector& b) { -// return exops[a] < exops[b]; -// }); -// std::cout << "Sorted excitation operators.\n"; -// std::cout << "Exops: "; -// for (const auto& exop : ind_exops) { -// std::cout << "{ "; -// for (int i : exop) { -// std::cout << i << " "; -// } -// std::cout << "} "; -// } -// } - - - -// generate unordered partition - // // Flatten the bin_config - // std::vector> bin_config; - // // for (const auto& [bin_size, bin_count] : bin_size_num) { - // for (const auto& bins : bin_size_num) { - // const auto& bin_size = bins.first; - // const auto& bin_count = bins.second; - // for (int i = 0; i < bin_count; ++i) { - // bin_config.emplace_back(bin_size, 1); - // } - // } - // std::vector>> results; - // std::vector> current_partition; - // helper_generate_partitions(collection, bin_config, 0, current_partition, results); - - -// void AP1roGeneralizedSenoObjective::helper_generate_partitions( -// const std::vector collection, -// std::vector>& bin_config, -// std::vector>::size_type bin_idx, -// std::vector>& current_partition, -// std::vector>>& results) { -// if (bin_idx == bin_config.size()) { -// results.push_back(current_partition); -// return; -// } - -// int bin_size = bin_config[bin_idx].first; -// // int bin_count = bin_config[bin_idx].second; - -// // Generate all combinations for the current bin size -// std::vector> all_combs; -// std::vector current_comb; -// generateCombinations(collection, bin_size, 0, current_comb, all_combs); - -// // Duplicate combinations -// std::set> unique_combs(all_combs.begin(), all_combs.end()); - -// for (const auto& bin : unique_combs) { -// // Enforce bin ordering; First element of the current bin -// // must be >= the first element of the previous bin (if any) -// if (!current_partition.empty() && current_partition.back()[0] > bin[0]) { -// continue; -// } - -// std::vector remaining_elements(collection.begin(), collection.end()); -// for (int elem : bin) { -// remaining_elements.erase(std::remove(remaining_elements.begin(), remaining_elements.end(), elem), remaining_elements.end()); -// } - -// current_partition.push_back(bin); -// helper_generate_partitions(remaining_elements, bin_config, bin_idx + 1, current_partition, results); -// current_partition.pop_back(); -// } -// } \ No newline at end of file From 7e7cc71b3595594be2c0a58690f1361bc1bbc7b4 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 19 Feb 2025 20:06:06 -0500 Subject: [PATCH 195/197] Firstll configurations based on exc using FullCI base class --- pyci/fanci/ap1rogen.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyci/fanci/ap1rogen.py b/pyci/fanci/ap1rogen.py index bb7c1f7..c1c8bdb 100644 --- a/pyci/fanci/ap1rogen.py +++ b/pyci/fanci/ap1rogen.py @@ -67,11 +67,11 @@ def __init__( # wfn.add_excited_dets(1) # add pair excited determinants wfn = pyci.fullci_wfn(ham.nbasis, nocc, nocc) # exc=0 ensures addint HF determinannt first - pyci.add_excitations(wfn,0,1,2,3,4) + pyci.add_excitations(wfn,1,2,3,4) print("Printing FCI wfn dets: ") - for sd in (wfn.to_occ_array()): + for i, sd in enumerate(wfn.to_occ_array()): sd = np.array(sd) - print(np.concatenate((sd[0],sd[1]+ham.nbasis))) + print(wfn.to_det_array()[i],np.concatenate((sd[0],sd[1]+ham.nbasis))) wfn = pyci.nonsingletci_wfn(wfn) @@ -83,11 +83,13 @@ def __init__( # Initialize base class FanCI.__init__(self, ham, wfn, nproj, nparam, **kwargs) + print("Nonsingletci nbasis: ",wfn.nbasis) print("\n\nPrinting nonsingletci wfn dets: ") for sd in (self._sspace): print(sd) # sd = np.array(sd) # print(np.concatenate((sd[0],sd[1]+ham.nbasis))) + print("Done printing\n\n") # Assign reference occupations #ref_occs_up = np.arange(nocc_up, dtype=pyci.c_long) From b46ac618d1c1a7139075ffb0e49ab312b4ee5526 Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 19 Feb 2025 20:09:02 -0500 Subject: [PATCH 196/197] change nword2 to nword to fix the update issue in GenCI base class --- pyci/src/genciwfn.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/pyci/src/genciwfn.cpp b/pyci/src/genciwfn.cpp index 182210b..4f92ecd 100644 --- a/pyci/src/genciwfn.cpp +++ b/pyci/src/genciwfn.cpp @@ -26,20 +26,55 @@ GenCIWfn::GenCIWfn(GenCIWfn &&wfn) noexcept : OneSpinWfn(wfn) { GenCIWfn::GenCIWfn(const DOCIWfn &wfn) : GenCIWfn(FullCIWfn(wfn)) { } +// GenCIWfn::GenCIWfn(const FullCIWfn &wfn) : OneSpinWfn(wfn.nbasis * 2, wfn.nocc, 0) { GenCIWfn::GenCIWfn(const FullCIWfn &wfn) : OneSpinWfn(wfn.nbasis * 2, wfn.nocc, 0) { ndet = wfn.ndet; - dets.resize(wfn.ndet * wfn.nword2); + dets.resize(wfn.ndet * wfn.nword); AlignedVector occs(wfn.nocc); + std::cout << "Inside GenCIWfn constructor" << std::endl; + std::cout << "wfn.nbasis: " << wfn.nbasis << ", wfn.nocc: " << wfn.nocc << std::endl; + std::cout << "wfn.nocc: " << wfn.nocc << ", wfn.nocc_up, _dn: " << wfn.nocc_up << ", " << wfn.nocc_dn << std::endl; + std::cout << "wfn.ndet: " << wfn.ndet << std::endl; long *occs_up = &occs[0], *occs_dn = &occs[wfn.nocc_up]; long j, k = 0; - for (long i = 0; i < wfn.ndet; ++i) { + + std::cout << "occs: " ; + for (int i = 0; i < wfn.nocc; i++) { + std::cout << occs[i] << " "; + } + std::cout << std::endl; + + for (long i = 0; i < wfn.ndet; i += 1) { fill_occs(wfn.nword, wfn.det_ptr(i), occs_up); - fill_occs(wfn.nword, wfn.det_ptr(i), occs_dn); + fill_occs(wfn.nword, wfn.det_ptr(i) + wfn.nword, occs_dn); + + std::cout << "\nwfn.det_ptr(" << i << "): " << wfn.det_ptr(i)[0] << " " << wfn.det_ptr(i)[1] << std::endl; + std::cout << "occs_up: " ; + for (int l = 0; l < wfn.nocc_up; l++) { + std::cout << occs_up[l] << " "; + } + std::cout << std::endl; + std::cout << "occs_dn: " ; + for (int l = 0; l < wfn.nocc_dn; l++) { + std::cout << occs_dn[l] << " "; + } + std::cout << std::endl; + for (j = 0; j < wfn.nocc_dn; ++j) occs_dn[j] += wfn.nbasis; + + std::cout << "updated occs_dn: "; + for(int l = 0; l < wfn.nocc_dn; l++) { + std::cout << occs_dn[l] << " "; + } + std::cout << std::endl; + + fill_det(wfn.nocc, occs_up, &dets[k]); dict[rank_det(&dets[k])] = i; - k += wfn.nword; + std::cout << "det[" << k << "]: " << dets[k] << std::endl; + k += wfn.nword; + } } From 048deeafc3479819617591804bf058cd5620599f Mon Sep 17 00:00:00 2001 From: "Pratiksha B. Gaikwad" Date: Wed, 19 Feb 2025 20:09:59 -0500 Subject: [PATCH 197/197] update function declarations --- pyci/include/pyci.h | 166 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 161 insertions(+), 5 deletions(-) diff --git a/pyci/include/pyci.h b/pyci/include/pyci.h index 0975d94..982482b 100644 --- a/pyci/include/pyci.h +++ b/pyci/include/pyci.h @@ -28,6 +28,7 @@ #include #include #include +#include #define EIGEN_DEFAULT_DENSE_INDEX_TYPE long #include @@ -69,6 +70,30 @@ #define PYCI_CHUNKSIZE_MIN 1024 #endif +// Specialize std::hash for std::vector +namespace std { + template <> + struct hash> { + int operator()(const std::vector& vec) const { + int seed = vec.size(); + for (auto& i : vec) { + seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } + return seed; + } + }; + + template <> + struct hash, std::vector>> { + int operator()(const std::pair, std::vector>& p) const { + int seed = hash>()(p.first); + seed ^= hash>()(p.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } + }; +} + + namespace pyci { /* Integer types, popcnt and ctz functions. */ @@ -895,17 +920,88 @@ class AP1roGeneralizedSenoObjective : public Objective { using Objective::ovlp; // Overlap vector using Objective::d_ovlp; // Overlap gradient matrix + using Partition = std::vector; // Type alias for a partition + using CacheKey = std::pair; // Key type for cache + // Custom hash function for CacheKey + struct CacheKeyHash { + std::size_t operator()(const CacheKey& key) const { + return std::hash()(key.first) ^ (std::hash()(key.second) << 1); + } + }; + // Define the cache type + using Cache = std::unordered_map, CacheKeyHash>; + + + std::size_t nbasis; + std::size_t nocc; + std::size_t ndet; + std::size_t nword; + + + struct HashVector { + long operator()(const std::vector& v) const { + long hash = 0; + for (long i : v) { + hash ^= std::hash()(i) + 0x9e3779b9 + (hash << 6) + (hash >> 2); + } + return hash; + } + }; + + // Custom equality function for std::vector + struct VectorEqual { + bool operator()(const std::vector& v1, const std::vector& v2) const { + return v1 == v2; + } + }; + + - // double default_value; + // std::unordered_map, int> exops; + std::unordered_map, int, HashVector, VectorEqual> exops; + std::vector> ind_exops; + std::vector ranks; std::vector det_exc_param_indx; // Det and excitation details + std::vector det_ac_inds; // Det, annhilation and creation indices, sign std::vector nexc_list; + const NonSingletCI& wfn_; // Member variable to store the wavefunction + + + + // struct pair_hash { + // template + // std::size_t operator()(const std::pair& p) const { + // auto hash1 = std::hash{}(p.first); + // auto hash2 = std::hash{}(p.second); + // return hash1 ^ (hash2 << 1); // Combine the two hash values + // } + // }; + // Custom hash function for std::vector + struct vector_hash { + std::size_t operator()(const std::vector& v) const { + std::size_t hash = 0; + for (auto& i : v) { + hash ^= std::hash{}(i) + 0x9e3779b9 + (hash << 6) + (hash >> 2); + } + return hash; + } + }; + // Custom hash function for std::pair, std::vector> + struct pair_hash { + std::size_t operator()(const std::pair, std::vector>& p) const { + auto hash1 = vector_hash{}(p.first); + auto hash2 = vector_hash{}(p.second); + return hash1 ^ (hash2 << 1); // Combine the two hash values + } + }; + + + + std::unordered_map, std::vector>, std::unordered_map>>, pair_hash> exop_combs; + std::vector s_permanent; std::vector p_permanent; -public: - // Keep in mind the {DOCI,FullCI,GenCI}Wfn class names in - // the arguments below depend on the template specialization - // C++ constructor AP1roGeneralizedSenoObjective(const SparseOp &, const NonSingletCI &, const std::size_t = 0UL, const long * = nullptr, const double * = nullptr, @@ -922,6 +1018,9 @@ class AP1roGeneralizedSenoObjective : public Objective { // C++ move constructor AP1roGeneralizedSenoObjective(AP1roGeneralizedSenoObjective &&) noexcept; + // Function to set attributes from wfn + void set_attributes_from_wfn(const NonSingletCI & ); + // Generate combinations of pairs and singles template void generate_combinations(const std::vector&, int , std::vector>&, long ); @@ -934,6 +1033,17 @@ class AP1roGeneralizedSenoObjective : public Objective { const std::vector& , int , std::vector& , std::vector&, long, const NonSingletCI &); + + // std::variant> + double product_amplitudes_multi( + const std::unordered_map>>&, + bool, const double*); + + + std::vector product_ampli_multi_deriv( + const std::unordered_map>>& , + bool , const double* ); + // Return the signature of applying annihilators then creators to the Slater determinant. int sign_swap(AlignedVector , long, long); @@ -955,6 +1065,52 @@ class AP1roGeneralizedSenoObjective : public Objective { // Overlap gradient function virtual void d_overlap(const size_t, const double*, double*); + + // New methods + void printPartitions(const std::vector&); + + std::vector findPartitions(const std::vector&, int, int, Cache&); + + std::vector intPartitionRecursive(const std::vector&, int, int); + + // template + void generateCombinations(const std::vector, std::vector::size_type, int, std::vector&, std::vector>&); + + // std::unordered_map, int> assign_exops(const std::vector&, int); //, const std::vector>*); + std::unordered_map, int, HashVector, VectorEqual> assign_exops(); //const long, const long, const long); + + void assign_and_sort_exops(const std::vector& , int); //, const std::vector>* ); + + // void helper_generate_partitions(const std::vector, std::vector>&, std::vector>::size_type, std::vector>&, std::vector>>&); + void get_unordered_partition(std::vector&, std::vector>& , + std::vector>& , int , + std::vector>>& ); + + std::vector>> generate_unordered_partitions(std::vector, std::vector>); + + std::unordered_map>> group_by_size(const std::vector>&); + + template + std::vector> generate_perms(const std::vector & vec) ; + // std::vector> generate_perms(const std::vector&, std::vector&, std::vector&); + + std::vector, std::vector>> combine_pairs(const std::vector>&, const std::vector>&); + + int sign_perm(std::vector, const std::vector, bool); + + template + T choose_dtype(size_t); + + template + std::vector, std::vector>>> cartesian_product(const std::vector>, std::vector>>>& ); + // std::vector> cartesian_product(const std::vector>& ); + + void generate_possible_exops(const std::vector&, const std::vector&); + //, std::vector&, std::unordered_map, std::vector>, std::vector>&);//std::vector>&); + + }; } // namespace pyci + +