Commit f9738392 authored by Dmitry I. Lyakh's avatar Dmitry I. Lyakh
Browse files

Added systematic MC-VQE ground state tests


Signed-off-by: default avatarDmitry I. Lyakh <quant4me@gmail.com>
parent decc1bb0
/** ExaTN:: Variational optimizer of a closed symmetric tensor network expansion functional
REVISION: 2021/09/17
REVISION: 2021/09/25
Copyright (C) 2018-2021 Dmitry I. Lyakh (Liakh)
Copyright (C) 2018-2021 Oak Ridge National Laboratory (UT-Battelle) **/
......@@ -226,12 +226,12 @@ bool TensorNetworkOptimizer::optimize(const ProcessGroup & process_group)
if(TensorNetworkOptimizer::debug > 1) std::cout << " Operator expectation value w.r.t. " << environment.tensor->getName()
<< " = " << std::scientific << expect_val << std::endl;
//Update the expectation value in the gradient expansion:
if(TensorNetworkOptimizer::debug > 1){
if(TensorNetworkOptimizer::debug > 2){
std::cout << " Old gradient expansion coefficients:\n";
environment.gradient_expansion.printCoefficients();
}
scale_metrics(environment.gradient_expansion,environment.expect_value,expect_val);
if(TensorNetworkOptimizer::debug > 1){
if(TensorNetworkOptimizer::debug > 2){
std::cout << " New gradient expansion coefficients:\n";
environment.gradient_expansion.printCoefficients();
}
......@@ -268,12 +268,12 @@ bool TensorNetworkOptimizer::optimize(const ProcessGroup & process_group)
if(micro_iteration == (micro_iterations_ - 1)) converged = false;
}
//Compute the optimal step size:
if(TensorNetworkOptimizer::debug > 1){
if(TensorNetworkOptimizer::debug > 2){
std::cout << " Old hessian expansion coefficients:\n";
environment.hessian_expansion.printCoefficients();
}
scale_metrics(environment.hessian_expansion,environment.expect_value,expect_val);
if(TensorNetworkOptimizer::debug > 1){
if(TensorNetworkOptimizer::debug > 2){
std::cout << " New hessian expansion coefficients:\n";
environment.hessian_expansion.printCoefficients();
}
......
......@@ -18,7 +18,7 @@
#include "errors.hpp"
//Test activation:
#define EXATN_TEST0
/*#define EXATN_TEST0
#define EXATN_TEST1
#define EXATN_TEST2
#define EXATN_TEST3
......@@ -44,9 +44,10 @@
#define EXATN_TEST23
#define EXATN_TEST24
#define EXATN_TEST25
//#define EXATN_TEST26 //requires input file from source
#define EXATN_TEST27
#define EXATN_TEST28
#define EXATN_TEST26*/
//#define EXATN_TEST27 //requires input file from source
#define EXATN_TEST28 //requires input file from source
//#define EXATN_TEST30
#ifdef EXATN_TEST0
......@@ -2853,6 +2854,148 @@ TEST(NumServerTester, OptimizerHubbard) {
#endif
#ifdef EXATN_TEST26
TEST(NumServerTester, ExaTNGenVisitor) {
using exatn::TensorShape;
using exatn::TensorSignature;
using exatn::Tensor;
using exatn::TensorComposite;
using exatn::TensorNetwork;
using exatn::TensorExpansion;
using exatn::TensorOperator;
using exatn::TensorElementType;
const auto TENS_ELEM_TYPE = TensorElementType::COMPLEX64;
//Test configuration:
const int num_sites = 16, max_bond_dim = std::min(static_cast<int>(std::pow(2,num_sites/2)),1);
const int max_layers = (num_sites - 1); //1 less CNOT gates
bool EVALUATE_FULL_TENSOR = false;
//exatn::resetLoggingLevel(2,2); //debug
bool success = true;
//Define the initial qubit state vector:
std::vector<std::complex<double>> qzero {
{1.0,0.0}, {0.0,0.0}
};
//Create a shallow quantum circuit:
// Create and initialize qubit tensors:
for(unsigned int i = 0; i < num_sites; ++i){
success = exatn::createTensor("Q"+std::to_string(i),TENS_ELEM_TYPE,TensorShape{2}); assert(success);
}
for(unsigned int i = 0; i < num_sites; ++i){
success = exatn::initTensorData("Q"+std::to_string(i),qzero); assert(success);
}
// Create and initalize 1-body gates:
success = exatn::createTensor("H",TENS_ELEM_TYPE,TensorShape{2,2}); assert(success);
success = exatn::initTensorData("H",exatn::quantum::getGateData(exatn::quantum::Gate::gate_H)); assert(success);
// Create and initialize 2-body gates:
success = exatn::createTensor("CNOT",TENS_ELEM_TYPE,TensorShape{2,2,2,2}); assert(success);
success = exatn::initTensorData("CNOT",exatn::quantum::getGateData(exatn::quantum::Gate::gate_CX)); assert(success);
// Append qubit tensors, 1-body and 2-body gates to a tensor network:
auto circuit_net = exatn::makeSharedTensorNetwork("Circuit");
for(unsigned int i = 0; i < num_sites; ++i){
success = circuit_net->appendTensor(i+1,exatn::getTensor("Q"+std::to_string(i)),{}); assert(success);
}
for(unsigned int i = 0; i < 1; ++i){
success = circuit_net->appendTensorGate(exatn::getTensor("H"),{i});
}
for(unsigned int i = 1; i < std::min(max_layers+1,num_sites); ++i){
success = circuit_net->appendTensorGate(exatn::getTensor("CNOT"),{i,i-1}); assert(success);
}
auto circuit = exatn::makeSharedTensorExpansion("Circuit",circuit_net,std::complex<double>{1.0,0.0});
success = exatn::balanceNormalizeNorm2Sync(*circuit,1.0,1.0,false); assert(success);
//circuit->printIt(); //debug
//Evaluate the quantum circuit:
if(EVALUATE_FULL_TENSOR){
success = exatn::evaluateSync(*circuit_net); assert(success);
}
//Create tensor network ansatz:
auto mps_builder = exatn::getTensorNetworkBuilder("MPS");
success = mps_builder->setParameter("max_bond_dim",max_bond_dim); assert(success);
auto ansatz_tensor = exatn::makeSharedTensor("AnsatzTensor",std::vector<int>(num_sites,2));
auto ansatz_net = exatn::makeSharedTensorNetwork("Ansatz",ansatz_tensor,*mps_builder);
ansatz_net->markOptimizableTensors([](const Tensor & tensor){return true;});
auto ansatz = exatn::makeSharedTensorExpansion("Ansatz",ansatz_net,std::complex<double>{1.0,0.0});
for(auto tens_conn = ansatz_net->begin(); tens_conn != ansatz_net->end(); ++tens_conn){
if(tens_conn->first != 0){ //input tensors only
success = exatn::createTensor(tens_conn->second.getTensor(),TENS_ELEM_TYPE); assert(success);
success = exatn::initTensorRnd(tens_conn->second.getName()); assert(success);
}
}
success = exatn::balanceNormalizeNorm2Sync(*ansatz,1.0,1.0,true); assert(success);
//ansatz->printIt(); //debug
//Create the full tensor ansatz:
auto ansatz_full_tensor = exatn::makeSharedTensor("AnsatzFullTensor",std::vector<int>(num_sites,2));
auto ansatz_full_net = exatn::makeSharedTensorNetwork("AnsatzFull");
success = ansatz_full_net->appendTensor(1,ansatz_full_tensor,{}); assert(success);
ansatz_full_net->markOptimizableAllTensors();
auto ansatz_full = exatn::makeSharedTensorExpansion("AnsatzFull",ansatz_full_net,std::complex<double>{1.0,0.0});
//ansatz_full->printIt(); //debug
if(EVALUATE_FULL_TENSOR){
success = exatn::createTensor(ansatz_full_tensor,TENS_ELEM_TYPE); assert(success);
success = exatn::initTensorRnd(ansatz_full_tensor->getName()); assert(success);
success = exatn::balanceNormalizeNorm2Sync(*ansatz_full,1.0,1.0,true); assert(success);
}
//Reconstruct the quantum circuit by a given tensor network ansatz:
std::cout << "Reconstructing the quantum circuit by a given tensor network ansatz:" << std::endl;
ansatz->conjugate();
exatn::TensorNetworkReconstructor::resetDebugLevel(1); //debug
exatn::TensorNetworkReconstructor reconstructor(circuit,ansatz,1e-5);
reconstructor.resetLearningRate(1.0);
success = exatn::sync(); assert(success);
double residual_norm, fidelity;
bool reconstructed = reconstructor.reconstruct(&residual_norm,&fidelity);
success = exatn::sync(); assert(success);
if(reconstructed){
std::cout << "Reconstruction succeeded: Residual norm = " << residual_norm
<< "; Fidelity = " << fidelity << std::endl;
/*for(auto tens = ansatz_net->cbegin(); tens != ansatz_net->cend(); ++tens){
if(tens->first != 0) exatn::printTensor(tens->second.getName()); //debug
}*/
if(EVALUATE_FULL_TENSOR){
const auto & tensor0_name = ansatz_full_tensor->getName();
const auto & tensor1_name = circuit_net->getTensor(0)->getName();
success = exatn::initTensorSync(tensor0_name,0.0); assert(success);
success = exatn::evaluateSync(*ansatz,ansatz_full_tensor); assert(success);
success = exatn::normalizeNorm2Sync(tensor0_name); assert(success);
success = exatn::normalizeNorm2Sync(tensor1_name); assert(success);
std::string addition;
success = exatn::generate_addition_pattern(ansatz_full_tensor->getRank(),addition,false,tensor0_name,tensor1_name); assert(success);
success = exatn::addTensors(addition,-1.0); assert(success);
double norm2 = 0.0;
success = exatn::computeNorm2Sync(tensor0_name,norm2);
std::cout << "2-norm of the tensor-difference = " << norm2 << std::endl;
//std::cout << "Full circuit tensor (reference):" << std::endl; //debug
//exatn::printTensor(tensor1_name); //debug
}
}else{
std::cout << "Reconstruction failed!" << std::endl; //assert(false);
}
ansatz->conjugate();
//Destroy tensors:
if(EVALUATE_FULL_TENSOR){
success = exatn::destroyTensor(ansatz_full_tensor->getName()); assert(success);
success = exatn::destroyTensor(ansatz_tensor->getName()); assert(success);
}
success = exatn::destroyTensors(*ansatz_net); assert(success);
success = exatn::destroyTensors(*circuit_net); assert(success);
//Synchronize:
success = exatn::sync(); assert(success);
exatn::resetLoggingLevel(0,0);
//Grab a beer!
}
#endif
#ifdef EXATN_TEST27
TEST(NumServerTester, HubbardHamiltonian) {
using exatn::TensorShape;
using exatn::TensorSignature;
......@@ -2968,8 +3111,8 @@ TEST(NumServerTester, HubbardHamiltonian) {
}
#endif
#ifdef EXATN_TEST27
TEST(NumServerTester, ExaTNGenVisitor) {
#ifdef EXATN_TEST28
TEST(NumServerTester, MCVQEHamiltonian) {
using exatn::TensorShape;
using exatn::TensorSignature;
using exatn::Tensor;
......@@ -2981,53 +3124,19 @@ TEST(NumServerTester, ExaTNGenVisitor) {
const auto TENS_ELEM_TYPE = TensorElementType::COMPLEX64;
//Test configuration:
const int num_sites = 16, max_bond_dim = std::min(static_cast<int>(std::pow(2,num_sites/2)),1);
const int max_layers = (num_sites - 1); //1 less CNOT gates
bool EVALUATE_FULL_TENSOR = false;
//exatn::resetLoggingLevel(2,2); //debug
bool success = true;
//Define the initial qubit state vector:
std::vector<std::complex<double>> qzero {
{1.0,0.0}, {0.0,0.0}
};
const int num_sites = 8;
const int bond_dim_lim = 4;
const int max_bond_dim = std::min(static_cast<int>(std::pow(2,num_sites/2)),bond_dim_lim);
//Create a shallow quantum circuit:
// Create and initialize qubit tensors:
for(unsigned int i = 0; i < num_sites; ++i){
success = exatn::createTensor("Q"+std::to_string(i),TENS_ELEM_TYPE,TensorShape{2}); assert(success);
}
for(unsigned int i = 0; i < num_sites; ++i){
success = exatn::initTensorData("Q"+std::to_string(i),qzero); assert(success);
}
// Create and initalize 1-body gates:
success = exatn::createTensor("H",TENS_ELEM_TYPE,TensorShape{2,2}); assert(success);
success = exatn::initTensorData("H",exatn::quantum::getGateData(exatn::quantum::Gate::gate_H)); assert(success);
// Create and initialize 2-body gates:
success = exatn::createTensor("CNOT",TENS_ELEM_TYPE,TensorShape{2,2,2,2}); assert(success);
success = exatn::initTensorData("CNOT",exatn::quantum::getGateData(exatn::quantum::Gate::gate_CX)); assert(success);
// Append qubit tensors, 1-body and 2-body gates to a tensor network:
auto circuit_net = exatn::makeSharedTensorNetwork("Circuit");
for(unsigned int i = 0; i < num_sites; ++i){
success = circuit_net->appendTensor(i+1,exatn::getTensor("Q"+std::to_string(i)),{}); assert(success);
}
for(unsigned int i = 0; i < 1; ++i){
success = circuit_net->appendTensorGate(exatn::getTensor("H"),{i});
}
for(unsigned int i = 1; i < std::min(max_layers+1,num_sites); ++i){
success = circuit_net->appendTensorGate(exatn::getTensor("CNOT"),{i,i-1}); assert(success);
}
auto circuit = exatn::makeSharedTensorExpansion("Circuit",circuit_net,std::complex<double>{1.0,0.0});
success = exatn::balanceNormalizeNorm2Sync(*circuit,1.0,1.0,false); assert(success);
//circuit->printIt(); //debug
//Evaluate the quantum circuit:
if(EVALUATE_FULL_TENSOR){
success = exatn::evaluateSync(*circuit_net); assert(success);
}
//Read the Hamiltonian in spin representation:
auto hamiltonian_operator = exatn::quantum::readSpinHamiltonian("MCVQEHam",
"mcvqe_"+std::to_string(num_sites)+"q.qcw.txt",TENS_ELEM_TYPE,"QCWare");
success = hamiltonian_operator->deleteComponent(0); assert(success); //remove SCF part
hamiltonian_operator->printIt();
//Create tensor network ansatz:
auto mps_builder = exatn::getTensorNetworkBuilder("MPS");
......@@ -3036,72 +3145,30 @@ TEST(NumServerTester, ExaTNGenVisitor) {
auto ansatz_net = exatn::makeSharedTensorNetwork("Ansatz",ansatz_tensor,*mps_builder);
ansatz_net->markOptimizableTensors([](const Tensor & tensor){return true;});
auto ansatz = exatn::makeSharedTensorExpansion("Ansatz",ansatz_net,std::complex<double>{1.0,0.0});
for(auto tens_conn = ansatz_net->begin(); tens_conn != ansatz_net->end(); ++tens_conn){
if(tens_conn->first != 0){ //input tensors only
success = exatn::createTensor(tens_conn->second.getTensor(),TENS_ELEM_TYPE); assert(success);
success = exatn::initTensorRnd(tens_conn->second.getName()); assert(success);
}
}
success = exatn::balanceNormalizeNorm2Sync(*ansatz,1.0,1.0,true); assert(success);
//ansatz->printIt(); //debug
//Create the full tensor ansatz:
auto ansatz_full_tensor = exatn::makeSharedTensor("AnsatzFullTensor",std::vector<int>(num_sites,2));
auto ansatz_full_net = exatn::makeSharedTensorNetwork("AnsatzFull");
success = ansatz_full_net->appendTensor(1,ansatz_full_tensor,{}); assert(success);
ansatz_full_net->markOptimizableAllTensors();
auto ansatz_full = exatn::makeSharedTensorExpansion("AnsatzFull",ansatz_full_net,std::complex<double>{1.0,0.0});
//ansatz_full->printIt(); //debug
if(EVALUATE_FULL_TENSOR){
success = exatn::createTensor(ansatz_full_tensor,TENS_ELEM_TYPE); assert(success);
success = exatn::initTensorRnd(ansatz_full_tensor->getName()); assert(success);
success = exatn::balanceNormalizeNorm2Sync(*ansatz_full,1.0,1.0,true); assert(success);
}
//Allocate/initialize tensors in the tensor network ansatz:
success = exatn::createTensorsSync(*ansatz_net,TENS_ELEM_TYPE); assert(success);
success = exatn::initTensorsRndSync(*ansatz_net); assert(success);
//success = exatn::balanceNormalizeNorm2Sync(*ansatz,1.0,1.0,true); assert(success);
//Reconstruct the quantum circuit by a given tensor network ansatz:
std::cout << "Reconstructing the quantum circuit by a given tensor network ansatz:" << std::endl;
ansatz->conjugate();
exatn::TensorNetworkReconstructor::resetDebugLevel(1); //debug
exatn::TensorNetworkReconstructor reconstructor(circuit,ansatz,1e-5);
reconstructor.resetLearningRate(1.0);
success = exatn::sync(); assert(success);
double residual_norm, fidelity;
bool reconstructed = reconstructor.reconstruct(&residual_norm,&fidelity);
success = exatn::sync(); assert(success);
if(reconstructed){
std::cout << "Reconstruction succeeded: Residual norm = " << residual_norm
<< "; Fidelity = " << fidelity << std::endl;
/*for(auto tens = ansatz_net->cbegin(); tens != ansatz_net->cend(); ++tens){
if(tens->first != 0) exatn::printTensor(tens->second.getName()); //debug
}*/
if(EVALUATE_FULL_TENSOR){
const auto & tensor0_name = ansatz_full_tensor->getName();
const auto & tensor1_name = circuit_net->getTensor(0)->getName();
success = exatn::initTensorSync(tensor0_name,0.0); assert(success);
success = exatn::evaluateSync(*ansatz,ansatz_full_tensor); assert(success);
success = exatn::normalizeNorm2Sync(tensor0_name); assert(success);
success = exatn::normalizeNorm2Sync(tensor1_name); assert(success);
std::string addition;
success = exatn::generate_addition_pattern(ansatz_full_tensor->getRank(),addition,false,tensor0_name,tensor1_name); assert(success);
success = exatn::addTensors(addition,-1.0); assert(success);
double norm2 = 0.0;
success = exatn::computeNorm2Sync(tensor0_name,norm2);
std::cout << "2-norm of the tensor-difference = " << norm2 << std::endl;
//std::cout << "Full circuit tensor (reference):" << std::endl; //debug
//exatn::printTensor(tensor1_name); //debug
//Perform ground state optimization on a tensor network manifold:
{
std::cout << "Ground state optimization on a tensor network manifold:" << std::endl;
exatn::TensorNetworkOptimizer::resetDebugLevel(1);
exatn::TensorNetworkOptimizer optimizer(hamiltonian_operator,ansatz,5e-4);
//optimizer.resetMicroIterations(1);
bool converged = optimizer.optimize();
success = exatn::sync(); assert(success);
if(converged){
std::cout << "Optimization succeeded!" << std::endl;
}else{
std::cout << "Optimization failed!" << std::endl; assert(false);
}
}else{
std::cout << "Reconstruction failed!" << std::endl; //assert(false);
}
ansatz->conjugate();
//Destroy tensors:
if(EVALUATE_FULL_TENSOR){
success = exatn::destroyTensor(ansatz_full_tensor->getName()); assert(success);
success = exatn::destroyTensor(ansatz_tensor->getName()); assert(success);
}
success = exatn::destroyTensors(*ansatz_net); assert(success);
success = exatn::destroyTensors(*circuit_net); assert(success);
success = exatn::destroyTensorsSync(*ansatz_net); assert(success);
//Synchronize:
success = exatn::sync(); assert(success);
......@@ -3110,7 +3177,7 @@ TEST(NumServerTester, ExaTNGenVisitor) {
}
#endif
#ifdef EXATN_TEST28
#ifdef EXATN_TEST30
TEST(NumServerTester, TensorComposite) {
using exatn::TensorShape;
using exatn::TensorSignature;
......
-21459.924482148097*I
+0.013958292661992958*X0
+0.017780394781136848*X0*X1
-0.006896704529177866*X0*Z1
-0.03376113630025557*Z0
+0.011474775121306156*Z0*X1
-0.004444563032874407*Z0*Z1
+0.009522097764876093*X1
-0.008640686174448204*X1*X2
-0.00641012019143096*X1*Z2
-0.042308599255825224*Z1
+0.0033005482717231548*Z1*X2
+0.0024514303165071353*Z1*Z2
-0.006583545256676178*X2
-0.007287160094179741*X2*X3
+0.004086379532445629*X2*Z3
-0.04957343856301523*Z2
-0.005120355594249221*Z2*X3
+0.00289351687114843*Z2*Z3
-0.006327031384126287*X3
-0.01840086316143409*X3*X4
-0.012367083572855955*X3*Z4
-0.03839552410604509*Z3
+0.010913763352627169*Z3*X4
+0.007334390217786867*Z3*Z4
+0.009699304994889446*X4
-0.004742884975867185*X4*X5
-0.0011410992924187104*X4*Z5
-0.03672437524536075*Z4
-0.0028540627220499703*Z4*X5
-0.0006758931704842083*Z4*Z5
-0.008546718038275256*X5
+0.0012774322501627943*X5*X6
-0.0006862884757300228*X5*Z6
-0.040029787841621825*Z5
+0.0004181198916071052*Z5*X6
-0.0002418324220780885*Z5*Z6
-0.004220761908087866*X6
-0.007850802949685699*X6*X7
-0.004536735382497114*X6*Z7
-0.041302161404488*Z6
+0.005221816809904007*Z6*X7
+0.003023554049679674*Z6*Z7
+0.005276029874809775*X7
+0.003908746500200684*X7*X8
+0.002296023695924425*X7*Z8
-0.03970158623823018*Z7
+0.002172368884806159*Z7*X8
+0.0012504359603084801*Z7*Z8
+0.0177160364898953*X8
+0.017780394781136848*X8*X9
-0.006896704529177866*X8*Z9
-0.031331984502371416*Z8
+0.011474775121306156*Z8*X9
-0.004444563032874407*Z8*Z9
+0.009522097764876093*X9
-0.008640686174448204*X9*X10
-0.00641012019143096*X9*Z10
-0.042308599255825224*Z9
+0.0033005482717231548*Z9*X10
+0.0024514303165071353*Z9*Z10
-0.006583545256676178*X10
-0.007287160094179741*X10*X11
+0.004086379532445629*X10*Z11
-0.04957343856301523*Z10
-0.005120355594249221*Z10*X11
+0.00289351687114843*Z10*Z11
-0.006327031384126281*X11
-0.018400863161434074*X11*X12
-0.012367083572855944*X11*Z12
-0.0383955241060451*Z11
+0.01091376335262716*Z11*X12
+0.007334390217786859*Z11*Z12
+0.009699304994889427*X12
-0.004742884975867166*X12*X13
-0.0011410992924187095*X12*Z13
-0.03672437524536075*Z12
-0.0028540627220499546*Z12*X13
-0.0006758931704842049*Z12*Z13
-0.00854671803827525*X13
+0.0012774322501627909*X13*X14
-0.0006862884757300207*X13*Z14
-0.04002978784162181*Z13
+0.00041811989160710434*Z13*X14
-0.00024183242207808828*Z13*Z14
-0.004220761908087874*X14
-0.007850802949685707*X14*X15
-0.004536735382497122*X14*Z15
-0.041302161404488*Z14
+0.005221816809904011*Z14*X15
+0.0030235540496796774*Z14*Z15
+0.002362932929837013*X15
-0.04139809785433139*Z15
-32189.885728186207*I
+0.013958292661992958*X0
+0.017780394781136848*X0*X1
-0.006896704529177866*X0*Z1
-0.03376113630025557*Z0
+0.011474775121306156*Z0*X1
-0.004444563032874407*Z0*Z1
+0.009522097764876093*X1
-0.008640686174448204*X1*X2
-0.00641012019143096*X1*Z2
-0.042308599255825224*Z1
+0.0033005482717231548*Z1*X2
+0.0024514303165071353*Z1*Z2
-0.006583545256676178*X2
-0.007287160094179741*X2*X3
+0.004086379532445629*X2*Z3
-0.04957343856301523*Z2
-0.005120355594249221*Z2*X3
+0.00289351687114843*Z2*Z3
-0.006327031384126287*X3
-0.01840086316143409*X3*X4
-0.012367083572855955*X3*Z4
-0.03839552410604509*Z3
+0.010913763352627169*Z3*X4
+0.007334390217786867*Z3*Z4
+0.009699304994889446*X4
-0.004742884975867185*X4*X5
-0.0011410992924187104*X4*Z5
-0.03672437524536075*Z4
-0.0028540627220499703*Z4*X5
-0.0006758931704842083*Z4*Z5
-0.008546718038275256*X5
+0.0012774322501627943*X5*X6
-0.0006862884757300228*X5*Z6
-0.040029787841621825*Z5
+0.0004181198916071052*Z5*X6
-0.0002418324220780885*Z5*Z6
-0.004220761908087866*X6
-0.007850802949685699*X6*X7
-0.004536735382497114*X6*Z7
-0.041302161404488*Z6
+0.005221816809904007*Z6*X7
+0.003023554049679674*Z6*Z7
+0.005276029874809775*X7
+0.003908746500200684*X7*X8
+0.002296023695924425*X7*Z8
-0.03970158623823018*Z7
+0.002172368884806159*Z7*X8
+0.0012504359603084801*Z7*Z8
+0.0177160364898953*X8
+0.017780394781136848*X8*X9
-0.006896704529177866*X8*Z9
-0.031331984502371416*Z8
+0.011474775121306156*Z8*X9
-0.004444563032874407*Z8*Z9
+0.009522097764876093*X9
-0.008640686174448204*X9*X10
-0.00641012019143096*X9*Z10
-0.042308599255825224*Z9
+0.0033005482717231548*Z9*X10
+0.0024514303165071353*Z9*Z10
-0.006583545256676178*X10
-0.007287160094179741*X10*X11
+0.004086379532445629*X10*Z11
-0.04957343856301523*Z10
-0.005120355594249221*Z10*X11
+0.00289351687114843*Z10*Z11
-0.006327031384126281*X11
-0.018400863161434074*X11*X12
-0.012367083572855944*X11*Z12
-0.0383955241060451*Z11
+0.01091376335262716*Z11*X12
+0.007334390217786859*Z11*Z12
+0.009699304994889427*X12
-0.004742884975867166*X12*X13
-0.0011410992924187095*X12*Z13
-0.03672437524536075*Z12
-0.0028540627220499546*Z12*X13
-0.0006758931704842049*Z12*Z13
-0.00854671803827525*X13
+0.0012774322501627909*X13*X14
-0.0006862884757300207*X13*Z14
-0.04002978784162181*Z13
+0.00041811989160710434*Z13*X14
-0.00024183242207808828*Z13*Z14
-0.004220761908087874*X14
-0.007850802949685707*X14*X15
-0.004536735382497122*X14*Z15
-0.041302161404488*Z14
+0.005221816809904011*Z14*X15
+0.0030235540496796774*Z14*Z15
+0.005276029874809778*X15
+0.003908746500200686*X15*X16
+0.002296023695924426*X15*Z16
-0.03970158623823018*Z15
+0.002172368884806159*Z15*X16
+0.0012504359603084797*Z15*Z16
+0.017716036489895275*X16
+0.01778039478113682*X16*X17
-0.006896704529177856*X16*Z17
-0.03133198450237143*Z16
+0.01147477512130614*Z16*X17
-0.0044445630328744015*Z16*Z17
+0.009522097764876072*X17
-0.008640686174448204*X17*X18
-0.00641012019143096*X17*Z18
-0.04230859925582521*Z17
+0.0033005482717231548*Z17*X18
+0.0024514303165071353*Z17*Z18
-0.006583545256676184*X18
-0.007287160094179738*X18*X19
+0.004086379532445626*X18*Z19
-0.04957343856301524*Z18
-0.005120355594249219*Z18*X19
+0.0028935168711484273*Z18*Z19
-0.006327031384126297*X19
-0.01840086316143414*X19*X20
-0.012367083572855986*X19*Z20
-0.038395524106045104*Z19
+0.010913763352627196*Z19*X20
+0.007334390217786885*Z19*Z20
+0.009699304994889456*X20
-0.004742884975867166*X20*X21
-0.0011410992924187095*X20*Z21
-0.036724375245360735*Z20
-0.0028540627220499546*Z20*X21
-0.0006758931704842049*Z20*Z21
-0.008546718038275246*X21
+0.0012774322501628013*X21*X22
-0.0006862884757300289*X21*Z22
-0.0400297878