28 #ifndef MPQC_INTERFACES_PURIFICATION_HPP
29 #define MPQC_INTERFACES_PURIFICATION_HPP
31 #include <mpqc/math/matrix.hpp>
32 #include <tiledarray.h>
36 namespace purification {
38 using TArray2 = TA::Array<double, 2>;
41 std::size_t multiplies;
47 std::array<double ,2> BoundsTA(
const TArray2 &F){
54 double min = 10, max = -10;
58 std::array<double, 2> Bounds(
const Matrix &F){
61 for(
auto i = 0; i < n; ++i){
63 for(
auto j = 0; j < n; ++j){
64 row_sum += (j != i) ? -std::abs(F(i,j)) : F(i,i);
66 min = (row_sum < min) ? row_sum : min;
70 for(
auto i = 0; i < n; ++i){
72 for(
auto j = 0; j < n; ++j){
73 row_sum += (j != i) ? std::abs(F(i,j)) : F(i,i);
75 max = (row_sum > max) ? row_sum : max;
81 performance tr_pure(
const TArray2 &F, TArray2 &D, std::size_t occ){
89 Matrix I = Eigen::MatrixXd::Identity(F.rows(), F.cols());
91 D = (E[0] * I - F)/(E[0] - E[1]);
95 data.adds++; data.multiplies++;
97 while((IDD).lpNorm<Eigen::Infinity>() > 1e-6){
100 int gamma = (occ - D.trace() > 0) ? 1 : -1;
105 D = 0.5 *
Matrix(D + D.transpose());
107 data.adds++; data.multiplies++;
114 Matrix I = Eigen::MatrixXd::Identity(D.rows(), D.cols());
115 return Matrix(D * D * D * (4 * I - 3 * D));
119 Matrix I = Eigen::MatrixXd::Identity(D.rows(), D.cols());
120 return Matrix( D * D * (I - D) * (I - D));
123 performance fourth_order_pure(
const Matrix &F,
Matrix &D, std::size_t occ){
131 Matrix I = Eigen::MatrixXd::Identity(F.rows(), F.cols());
133 D = (E[0] * I - F)/(E[0] - E[1]);
139 while((D - D2).lpNorm<Eigen::Infinity>() > 1e-9){
144 data.adds++; data.multiplies++;
146 double gamma = (double(occ) -
Matrix(D3 * (4 * I - 3 * D)).trace())/
147 (
Matrix(D2 * ID * ID).trace());
148 data.adds += 1; data.multiplies += 3; data.traces += 2;
157 D = D3 * (4 * I - 3 * D) + gamma * (D2 * ID * ID);
158 data.adds += 4; data.multiplies += 3;
167 performance canonical_pure(
const Matrix &F,
Matrix &D, std::size_t occ){
176 Matrix I = Eigen::MatrixXd::Identity(n, n);
177 double mu = F.trace()/n;
179 double lambda = std::min(
double(occ)/(E[0]-mu),
180 double(n-occ)/(mu - E[1]));
181 D = (lambda/double(n)) * (mu * I - F) + double(occ)/double(n) * I;
187 while((D - D2).lpNorm<Eigen::Infinity>() > 1e-6
194 double c = (
Matrix(D2 - D3).trace())/
196 data.adds += 2; data.traces +=2;
198 D = (1.0/c) * ((1 + c) * D2 - D3);
201 D = 1.0/(1.0 - c) * ((1 - 2*c) * D + (1 + c)*D2 - D3);