initial commit
This commit is contained in:
commit
cc805c0166
3
src/.clangd
Normal file
3
src/.clangd
Normal file
@ -0,0 +1,3 @@
|
||||
CompileFlags: # Tweak the parse settings
|
||||
Add: [ -std=c++23, -Wall, -Wpedantic, -IFastor, -I., -I.., -I../include, -Imodels, -I../models, -Ialgorithms, -DEMSCRIPTEN ]
|
||||
# https://clangd.llvm.org/config
|
2924
src/.doxygen_config
Normal file
2924
src/.doxygen_config
Normal file
File diff suppressed because it is too large
Load Diff
70
src/.old/mps_fastor.cpp
Normal file
70
src/.old/mps_fastor.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
#include "Fastor/Fastor.h"
|
||||
#include "Fastor/tensor/AbstractTensorFunctions.h"
|
||||
|
||||
namespace f = Fastor;
|
||||
using dtype = double;
|
||||
|
||||
template<unsigned maxBondDim, unsigned localDim>
|
||||
class MPS {
|
||||
using BTensor_t = f::Tensor<dtype, maxBondDim, localDim, maxBondDim>;
|
||||
public:
|
||||
MPS(std::vector<f::Tensor<dtype>>&& Bs, std::vector<f::Tensor<dtype>>&& Ss) {
|
||||
assert(Bs.size() == Ss.size());
|
||||
this->Bs = std::move(Bs);
|
||||
this->Ss = std::move(Ss);
|
||||
this->L = Bs.size();
|
||||
}
|
||||
private:
|
||||
std::vector<f::Tensor<dtype>> Bs;
|
||||
std::vector<f::Tensor<dtype>> Ss;
|
||||
unsigned L;
|
||||
};
|
||||
|
||||
// class TensorContainer {
|
||||
// public:
|
||||
// TensorContainer(Tensor t);
|
||||
|
||||
// };
|
||||
|
||||
|
||||
int main() {
|
||||
// std::vector<f::Tensor<dtype, 2, 2, 1>> Bs = {
|
||||
// // f::Tensor<dtype, 1, 2, 1>({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}),
|
||||
// // f::Tensor<dtype, 1, 2, 1>({{{1, 2}}}),
|
||||
// f::Tensor<dtype, 1, 2, 1>({{{1}, {2}}}),
|
||||
// // f::Tensor<dtype, 1, 10, 1>({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}),
|
||||
// };
|
||||
f::Tensor<dtype, 10, 2, 10> t1;
|
||||
t1.zeros();
|
||||
std::cout << t1 << std::endl;
|
||||
t1(0,1,0) = .69;
|
||||
std::cout << t1 << std::endl;
|
||||
|
||||
f::Tensor<dtype, 10, 2, 10> t2;
|
||||
t2.ones();
|
||||
|
||||
std::vector<f::Tensor<dtype, 10, 2, 10>> Bs = { t1, t2 };
|
||||
|
||||
//({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}});
|
||||
// auto t2 = f::Tensor<dtype, 1, 10, 1>({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}});
|
||||
|
||||
// f::Tensor<dtype, 1, 5, 1>
|
||||
// for (auto& b : Bs) {
|
||||
// std::cout << b << std::endl;
|
||||
// }
|
||||
|
||||
// f::Tensor<dtype, 1, 2, 1> t1View = t1(f::seq(0, 1), f::all, f::seq(0, 1));
|
||||
auto t1View = t1(f::seq(0, 10), f::all, f::seq(0, 10));
|
||||
auto t2View = t2(f::seq(0, 10), f::all, f::seq(0, 10));
|
||||
// auto t1View = t1(f::seq(0, 1), f::all, f::seq(0, 1));
|
||||
// std::cout << t1View.dimension(0) << std::endl;
|
||||
// std::cout << t1View.dimension(1) << std::endl;
|
||||
// std::cout << t1View.dimension(2) << std::endl;
|
||||
// std::cout << t1View << std::endl;
|
||||
f::Tensor<dtype, 1> t3 = f::evaluate(f::einsum<f::Index<0, 1, 2>, f::Index<0, 1, 2>>(t1View, t2View));
|
||||
// f::Tensor<dtype, 1> t3 = f::einsum<f::Index<0, 1, 2>, f::Index<0, 1, 2>>(t1, t2);
|
||||
std::cout << t3.dimension(0) << std::endl;
|
||||
std::cout << t3(0) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
22
src/.vimspector.json
Normal file
22
src/.vimspector.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"configurations": {
|
||||
"gze": {
|
||||
"adapter": "vscode-cpptools",
|
||||
"configuration": {
|
||||
"name": "mps (cpp)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"externalConsole": true,
|
||||
"logging": {
|
||||
"engineLogging": true
|
||||
},
|
||||
"stopOnEntry": true,
|
||||
"stopAtEntry": true,
|
||||
"debugOptions": [],
|
||||
"MIMode": "gdb",
|
||||
"cwd": "~/Projekte/science/cpp-mps/src",
|
||||
"program": "../mps"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
131
src/Makefile
Executable file
131
src/Makefile
Executable file
@ -0,0 +1,131 @@
|
||||
# SETTINGS
|
||||
OBJECT_DIR = ../build
|
||||
WEBOBJECT_DIR = ../web-build
|
||||
EXEC = ../mps
|
||||
WEBHTML = $(WEBOBJECT_DIR)/mps.html
|
||||
# WEBEXEC = $(WEBOBJECT_DIR)/mps.js
|
||||
WEBEXEC = ~/Projekte/web/html-quintern/src/script/mps/mps-wasm.js
|
||||
|
||||
# LOG_LEVEL = LOG_LEVEL_0
|
||||
CXX = /usr/bin/g++
|
||||
CXXFLAGS = -std=c++23 -MMD -MP -Wpedantic -Wall #-O3: optimierungsstufe 3, -MMD .d files, -MP leeres Target, Wextra alle Warnungen
|
||||
CXXDEBUGFLAGS = -g -fsanitize=address -fno-omit-frame-pointer -O1
|
||||
|
||||
WEBCXX = em++
|
||||
WEBCXXFLAGS = --cache "$(WEBOBJECT_DIR)/emscripten-cache" -Wno-c++11-narrowing -Wno-unused-main -DEMSCRIPTEN
|
||||
WEBCXXDEBUGFLAGS = -gsource-map -g2 -O0
|
||||
WEBLDFLAGS = -s EXPORTED_FUNCTIONS="['_free']" -s ASYNCIFY -s EXPORTED_RUNTIME_METHODS="['cwrap', 'getValue']" -lembind -s INITIAL_MEMORY=2GB -s ALLOW_MEMORY_GROWTH=1
|
||||
# treated as error by em++
|
||||
LDFLAGS = #-lgzutil
|
||||
IFLAGS = -I../include/
|
||||
|
||||
SRCDIRS = $(wildcard */)
|
||||
IFLAGS += $(foreach dir,$(SRCDIRS), -I$(dir))
|
||||
IFLAGS += $(foreach dir,$(SRCDIRS), -I../$(dir))
|
||||
IFLAGS += -I../ -I./
|
||||
CXXFLAGS += $(IFLAGS)
|
||||
|
||||
|
||||
# CXXFLAGS += -D $(LOG_LEVEL)
|
||||
# CXXFLAGS += -fsanitize=address
|
||||
# CXXFLAGS += -fconcepts-diagnostics-depth=2
|
||||
|
||||
SRC = $(wildcard *.cpp) $(wildcard */*.cpp)
|
||||
# OBJECTS = $(SRC:%.cpp=$(OBJECT_DIR)/%.o)
|
||||
OBJECTS = $($(notdir SRC):%.cpp=$(OBJECT_DIR)/%.o)
|
||||
WEBOBJECTS = $($(notdir SRC):%.cpp=$(WEBOBJECT_DIR)/%.o)
|
||||
OBJECT_DIRS = $(foreach dir,$(SRCDIRS), $(OBJECT_DIR)/$(dir))
|
||||
WEBOBJECT_DIRS = $(foreach dir,$(SRCDIRS), $(WEBOBJECT_DIR)/$(dir))
|
||||
DEPENDS = ${OBJECTS:.o=.d}
|
||||
|
||||
|
||||
FMT_MESSAGE="\e[1;34m%s\e[0m %s %s %s\n"
|
||||
default:
|
||||
@printf $(FMT_MESSAGE) "CXXFLAGS = " "$(CXXFLAGS)"
|
||||
@printf $(FMT_MESSAGE) "LDFLAGS = " "$(LDFLAGS)"
|
||||
default: CXXFLAGS += -include pch.hpp
|
||||
default: $(EXEC)
|
||||
|
||||
web: CXXFLAGS += $(WEBCXXFLAGS)
|
||||
web: $(WEBEXEC)
|
||||
|
||||
webDebug: WEBLDFLAGS += -sASSERTIONS
|
||||
webDebug: CXXFLAGS += $(WEBCXXDEBUGFLAGS)
|
||||
webDebug: web
|
||||
|
||||
webO0: CXXFLAGS += $(WEBCXXFLAGS) -O0
|
||||
webO0: web
|
||||
webO1: CXXFLAGS += $(WEBCXXFLAGS) -O1
|
||||
webO1: web
|
||||
webO2: CXXFLAGS += $(WEBCXXFLAGS) -O2
|
||||
webO2: web
|
||||
webO3: CXXFLAGS += $(WEBCXXFLAGS) -O3
|
||||
webO3: web
|
||||
|
||||
webrun: CXXFLAGS += $(WEBCXXFLAGS)
|
||||
webrun: $(WEBHTML)
|
||||
cd $(WEBOBJECT_DIR) && emrun $(WEBHTML)
|
||||
|
||||
.PHONY: release
|
||||
release: CXXFLAGS += -O3
|
||||
release: default
|
||||
|
||||
O0: CXXFLAGS += -O0
|
||||
O0: default
|
||||
O1: CXXFLAGS += -O1
|
||||
O1: default
|
||||
O2: CXXFLAGS += -O2
|
||||
O2: default
|
||||
O3: CXXFLAGS += -O3
|
||||
O3: default
|
||||
|
||||
# rule for the executable
|
||||
$(EXEC): $(OBJECT_DIRS) $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
$(WEBHTML) $(WEBEXEC): $(WEBOBJECT_DIRS) $(WEBOBJECTS)
|
||||
$(WEBCXX) $(WEBOBJECTS) -o $@ $(CXXFLAGS) $(LDFLAGS) $(WEBLDFLAGS)
|
||||
# include the makefiles generated by the -M flag
|
||||
-include $(DEPENDS)
|
||||
|
||||
# rule for all ../build/*.o files
|
||||
$(OBJECT_DIR)/%.o: $(shell echo $<) %.cpp
|
||||
@printf $(FMT_MESSAGE) "Building:" $< "->" $@
|
||||
@$(CXX) -c $< -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
$(WEBOBJECT_DIR)/%.o: $(shell echo $<) %.cpp
|
||||
@printf $(FMT_MESSAGE) "Building:" $< "->" $@
|
||||
@$(WEBCXX) -c $< -o $@ $(CXXFLAGS) $(LDFLAGS)
|
||||
|
||||
$(OBJECT_DIRS) $(WEBOBJECT_DIRS):
|
||||
mkdir -p $@
|
||||
|
||||
#
|
||||
# Extras Options
|
||||
#
|
||||
# with debug flags
|
||||
.PHONY += debug run gdb pch clean docs
|
||||
|
||||
debug: CXXFLAGS += $(CXXDEBUGFLAGS)
|
||||
debug: default
|
||||
|
||||
# make with debug flags and run afterwards
|
||||
run: CXXFLAGS += $(CXXDEBUGFLAGS)
|
||||
run: default
|
||||
-pwd; cd $(shell dirname $(EXEC)); pwd; ./$(shell basename $(EXEC))
|
||||
|
||||
# with debug flags and run gnu debugger
|
||||
gdb: CXXFLAGS += -g
|
||||
gdb: default
|
||||
gdb $(EXEC) -ex "layout src"
|
||||
|
||||
# build pch
|
||||
pch:
|
||||
$(CXX) pch.hpp -std=c++23 -O3 -g $(IFLAGS)
|
||||
|
||||
# remove all object and dependecy files
|
||||
clean:
|
||||
-rm -r $(OBJECT_DIR)
|
||||
-rm -r $(WEBOBJECT_DIR)
|
||||
docs:
|
||||
doxygen .doxygen_config
|
131
src/algorithms/tebd.cpp
Normal file
131
src/algorithms/tebd.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include "tebd.hpp"
|
||||
#include "type.hpp"
|
||||
#include "util.hpp"
|
||||
#include <cstdio>
|
||||
#include <ostream>
|
||||
#include <unordered_map>
|
||||
#include <print>
|
||||
|
||||
template<typename InType, typename OutType>
|
||||
std::vector<std::shared_ptr<OutType>> forEachUnique(std::function<OutType(const InType&)> f, const std::vector<std::shared_ptr<InType>>& inRange) {
|
||||
std::unordered_map<std::shared_ptr<InType>, std::shared_ptr<OutType>> cache;
|
||||
std::vector<std::shared_ptr<OutType>> outRange;
|
||||
outRange.reserve(inRange.size());
|
||||
for (const auto& inPtr : inRange) {
|
||||
if (cache.contains(inPtr)) {
|
||||
outRange.push_back(cache.at(inPtr));
|
||||
} else {
|
||||
std::shared_ptr<OutType> outPtr = std::make_shared<OutType>(f(*inPtr));
|
||||
// cache.emplace(std::make_pair(inPtr, outPtr));
|
||||
cache.emplace(inPtr, outPtr);
|
||||
outRange.push_back(outPtr);
|
||||
}
|
||||
}
|
||||
return outRange;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> getTimeEvolutionMatrix(const e::MatrixX<T>& bond, T dt, unsigned localDim) {
|
||||
e::MatrixX<T> U = (-bond * dt).exp();
|
||||
// std::cout << "U = \n" << U << "\n\n";
|
||||
return bondMatrix2Tensor<T>(U, localDim);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Bonds<T> getTimeEvolutionMatrices(const std::vector<std::shared_ptr<e::MatrixX<T>>>& bonds, T dt, unsigned int localDim) {
|
||||
std::function<e::Tensor<T, 4>(const e::MatrixX<T>&)> f = std::bind(getTimeEvolutionMatrix<T>, std::placeholders::_1, dt, localDim);
|
||||
std::vector<std::shared_ptr<e::Tensor<T, 4>>> U_Bonds = forEachUnique(f, bonds);
|
||||
return U_Bonds;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void updateBond(MPS<T>& psi, size_t i, const e::Tensor<T, 4>& U, unsigned chiMax, T eps) {
|
||||
// std::println("BOND {}", i);
|
||||
auto theta = psi.getTheta2(i); // vL i j vR
|
||||
// apply U: i j i* j*
|
||||
// contraction gives vL vR i j -> shuffle to vL i j vR
|
||||
// std::cout << theta.dimension(2) << " - " << U.dimension(2) << " / " << theta.dimensions() << std::endl;
|
||||
e::Tensor<T, 4> a = theta.contract(U, e::array<iP, 2>({iP{1, 2}, iP{2, 3}}));
|
||||
e::Tensor<T, 4> b = a.shuffle(e::array<int, 4>{0, 2, 3, 1});
|
||||
// e::Tensor<T, 4> b = a.shuffle(e::array<int, 4>{2, 0, 1, 3});
|
||||
// printTensor(b, "Utheta");
|
||||
// SVD and truncation
|
||||
auto [Ai, Sj, Bj] = split_truncate_theta<T>(b, chiMax, eps);
|
||||
// printTensor(Ai, "Ai");
|
||||
// printTensor(Sj, "Sj");
|
||||
// printTensor(Bj, "Bj");
|
||||
// std::cout << "a: " << a.dimensions() << "\nA: " << Ai.dimensions() << "\nS: " << Sj.dimensions() << "\nB: " << Bj.dimensions() << std::endl;
|
||||
// renormalize to Bi
|
||||
e::Tensor<T, 1> SiInv = 1. / psi.S(i);
|
||||
e::Tensor<T, 2> SiDiv = diagonal(SiInv);
|
||||
e::Tensor<T, 3> Gi = SiDiv.contract(Ai, e::array<iP, 1>{iP{1, 0}}); // vL [vL], [vL] i vC
|
||||
// printTensor(SiDiv, "SiDiv");
|
||||
// printTensor(Gi, "Gi");
|
||||
|
||||
// e::Tensor<T, 0> SS = Sj.contract(Sj.conjugate(), e::array<iP, 1>{iP{0,0}});
|
||||
// std::println("Bond {:03}, Sj contracted with its conjugate = {}", i, SS(0));
|
||||
|
||||
// psi.B(i) = Gi.contract(diagonal(Sj), e::array<iP, 1>{iP{2, 0}}); // vL i [vC], [vC] vC
|
||||
// psi.B(i+1) = std::move(Bj);
|
||||
// psi.S(i+1) = std::move(Sj);
|
||||
MPS<dtype>::BTensor_t Bi = Gi.contract(diagonal(Sj), e::array<iP, 1>{iP{2, 0}}); // vL i [vC], [vC] vC
|
||||
// e::Tensor<bool, 0> equal = (psi.B(i) == Bi).all();
|
||||
// printTensor(psi.B(i), "old Bi");
|
||||
// printTensor(Bi, "new Bi");
|
||||
psi.B(i) = Bi;
|
||||
psi.B(i+1) = Bj;
|
||||
psi.S(i+1) = Sj;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void runTEBD_brickwall(MPS<T>& psi, const Bonds<T>& bonds, unsigned chiMax, T eps, unsigned nSteps, postUpdateFunction_t<T> postUpdateFunc) {
|
||||
for (unsigned n = 0; n < nSteps; n++) {
|
||||
// std::print("i = {:03}\r", n);
|
||||
// std::flush(std::cout);
|
||||
for (unsigned row = 0; row < 2; row++) {
|
||||
for (unsigned i = row; i < bonds.size(); i+=2) {
|
||||
// std::cout << "i = " << i << std::endl;
|
||||
updateBond(psi, i, *(bonds.at(i)), chiMax, eps);
|
||||
}
|
||||
}
|
||||
postUpdateFunc(psi, n);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
/**
|
||||
* @brief Run TEBD using a second-order decomposition
|
||||
* @todo I think this is currently only correct for even system sizes => check decomposition
|
||||
*/
|
||||
template<typename T>
|
||||
void runTEBD_secondOrder(MPS<T>& psi, const Bonds<T>& bonds, const Bonds<T>& bondsHalfDT, unsigned chiMax, T eps, unsigned nSteps, postUpdateFunction_t<T> postUpdateFunc) {
|
||||
for (unsigned n = 0; n < nSteps; n++) {
|
||||
// std::print("i = {:03}\r", n);
|
||||
// std::flush(std::cout);
|
||||
for (unsigned row = 0; row < 2; row++) {
|
||||
const Bonds<T>* useBonds = &bonds;
|
||||
if (row == 0 && (n != 0 || n != nSteps-1)) {
|
||||
useBonds = &bondsHalfDT;
|
||||
}
|
||||
for (unsigned i = row; i < bonds.size(); i+=2) {
|
||||
// std::cout << "i = " << i << std::endl;
|
||||
updateBond(psi, i, *(useBonds->at(i)), chiMax, eps);
|
||||
}
|
||||
}
|
||||
postUpdateFunc(psi, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Instantiations
|
||||
template std::vector<std::shared_ptr<e::Tensor<dtype, 4>>> forEachUnique(std::function<e::Tensor<dtype, 4> (const e::MatrixX<dtype> &)> f, const std::vector<std::shared_ptr<e::MatrixX<dtype>>>&);
|
||||
template e::Tensor<dtype, 4> getTimeEvolutionMatrix<dtype>(const e::MatrixX<dtype>& bond, dtype dt, unsigned localDim);
|
||||
template Bonds<dtype> getTimeEvolutionMatrices<dtype>(const std::vector<std::shared_ptr<e::MatrixX<dtype>>>& bonds, dtype dt, unsigned int localDim);
|
||||
template void updateBond<dtype>(MPS<dtype>& psi, size_t i, const e::Tensor<dtype, 4>& U, unsigned chiMax, dtype eps);
|
||||
template void postUpdateNoop<dtype>(const MPS<dtype>&, unsigned);
|
||||
template void runTEBD_brickwall<dtype>(MPS<dtype>& psi, const Bonds<dtype>& bonds, unsigned chiMax, dtype eps, unsigned nSteps, postUpdateFunction_t<dtype> postUpdateFunc);
|
||||
template void runTEBD_secondOrder<dtype>(MPS<dtype>& psi, const Bonds<dtype>& bonds, const Bonds<dtype>&, unsigned chiMax, dtype eps, unsigned nSteps, postUpdateFunction_t<dtype> postUpdateFunc);
|
||||
|
54
src/algorithms/tebd.hpp
Normal file
54
src/algorithms/tebd.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include "model.hpp"
|
||||
#include "mps.hpp"
|
||||
#include <eigen3/Eigen/Eigen>
|
||||
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
|
||||
#include <eigen3/unsupported/Eigen/MatrixFunctions>
|
||||
|
||||
/**
|
||||
* @brief Apply the function f on every element if inRange, but reuse a cached result when two pointers point to the same object
|
||||
*/
|
||||
template<typename InType, typename OutType>
|
||||
std::vector<std::shared_ptr<OutType>> forEachUnique(std::function<OutType(const InType&)> f, const std::vector<std::shared_ptr<InType>>& inRange);
|
||||
|
||||
template<typename T>
|
||||
using Bonds = std::vector<std::shared_ptr<e::Tensor<T, 4>>>;
|
||||
|
||||
/**
|
||||
* @brief Apply time evolution on a bond
|
||||
* @details
|
||||
* \f[U = \exp{ B \, \del t} \f]
|
||||
*/
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> getTimeEvolutionMatrix(const e::MatrixX<T>& bond, T dt, unsigned localDim);
|
||||
|
||||
template<typename T>
|
||||
Bonds<T> getTimeEvolutionMatrices(const std::vector<std::shared_ptr<e::MatrixX<T>>>& bonds, T dt, unsigned int localDim);
|
||||
|
||||
/**
|
||||
* @brief Apply U on bond i, perform SVD and truncate, update MPS
|
||||
*/
|
||||
template<typename T>
|
||||
void updateBond(MPS<T>& psi, size_t i, const e::Tensor<T, 4>& U, unsigned chiMax, T eps);
|
||||
|
||||
template<typename T>
|
||||
using postUpdateFunction_t = std::function<void (const MPS<T>&, unsigned)>;
|
||||
|
||||
template<typename T>
|
||||
void postUpdateNoop(const MPS<T>&, unsigned) {};
|
||||
|
||||
/**
|
||||
* @brief Brickwall TEBS scheme
|
||||
* @details
|
||||
* Apply U on every second bond starting from the first,
|
||||
* then apply U on every second bond starting from the second
|
||||
*
|
||||
* First order scheme
|
||||
*
|
||||
* @param postUpdateFunc function that can be used to track expectation values after each update
|
||||
*/
|
||||
template<typename T>
|
||||
void runTEBD_brickwall(MPS<T>& psi, const Bonds<T>& bonds, unsigned chiMax, T eps, unsigned nSteps, postUpdateFunction_t<T> postUpdateFunc);
|
||||
|
||||
template<typename T>
|
||||
void runTEBD_secondOrder(MPS<T>& psi, const Bonds<T>& bonds, const Bonds<T>& bondsHalfDT, unsigned chiMax, T eps, unsigned nSteps, postUpdateFunction_t<T> postUpdateFunc);
|
194
src/benchmark.cpp
Normal file
194
src/benchmark.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "benchmark.hpp"
|
||||
|
||||
#include <print>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include "mps.hpp"
|
||||
#include "tebd.hpp"
|
||||
#include "transverse_field_ising.hpp"
|
||||
#include "util.hpp"
|
||||
#include "type.hpp"
|
||||
#include "stopwatch.hpp"
|
||||
|
||||
struct Results {
|
||||
std::vector<double> E;
|
||||
std::vector<double> M;
|
||||
std::vector<double> S;
|
||||
};
|
||||
|
||||
Results _runTEBD(unsigned L, double J, double g, unsigned nSteps, dtype dt, dtype eps, unsigned chiMax) {
|
||||
auto psi = initMPS_spinUp<dtype>(L);
|
||||
auto model = TransverseFieldIsingModel1D<dtype>(L, J, g);
|
||||
// Sanity checks
|
||||
throwIfNaN(eps, "eps");
|
||||
throwIfNaN(dt, "dt");
|
||||
throwIfLessThan(nSteps, 1u, "nSteps");
|
||||
throwIfLessThan(chiMax, 1u, "chiMax");
|
||||
if (psi.getL() != model.L) {
|
||||
throw std::runtime_error("psi and model have different L");
|
||||
}
|
||||
Results result;
|
||||
result.E.reserve(nSteps+1);
|
||||
result.M.reserve(nSteps+1);
|
||||
result.S.reserve(nSteps+1);
|
||||
|
||||
e::Tensor<dtype, 2> sigma_z(2, 2);
|
||||
sigma_z.setValues({{1, 0}, {0, -1}});
|
||||
|
||||
size_t middleBond = model.L / 2;
|
||||
// collect M over time in an array
|
||||
auto F = postUpdateFunction_t<dtype>([&result, &sigma_z, &model, middleBond](const MPS<dtype>& psi, unsigned i){
|
||||
result.M.push_back(psi.getSiteExpectationValueSum(sigma_z).real());
|
||||
result.E.push_back(model.energy(psi).real());
|
||||
result.S.push_back(psi.getEntanglementEntropy(middleBond).real());
|
||||
});
|
||||
// initial values now
|
||||
F(psi, 0);
|
||||
|
||||
const Bonds<dtype> bonds = getTimeEvolutionMatrices(model.getH_BondsMatrices(), dt, model.localDim);
|
||||
runTEBD_brickwall(psi, bonds, chiMax, eps, nSteps, F);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
double _runBenchmark(std::function<T(Args...)> f, Args... args) {
|
||||
Stopwatch watch;
|
||||
watch.start();
|
||||
T result = f(std::forward<Args>(args)...);;
|
||||
double time = watch.stop();
|
||||
return time;
|
||||
}
|
||||
|
||||
int runBenchmark_oneAtATime() {
|
||||
// testing parameters
|
||||
std::vector<unsigned> chiMaxs{5, 10, 15, 25, 30};
|
||||
std::vector<dtype> epss{1e-5, 1e-15, 1e-20};
|
||||
std::vector<unsigned> Ls{4, 8, 16, 20, 24, 28, 32};
|
||||
std::vector<unsigned> nStepss{400, 600, 800, 1000};
|
||||
|
||||
std::map<std::string, double> times;
|
||||
|
||||
// default parameters
|
||||
unsigned L = 12;
|
||||
double J = 1;
|
||||
double g = 0.7;
|
||||
unsigned nSteps = 200;
|
||||
dtype dt = 0.05;
|
||||
dtype eps = 1e-10;
|
||||
unsigned chiMax = 20;
|
||||
|
||||
// get a unique string including all test parameters
|
||||
std::function<Results (unsigned, double, double, unsigned, dtype, dtype, unsigned)> f(&_runTEBD);
|
||||
auto getName = [](unsigned L, unsigned nSteps, dtype eps, unsigned chiMax) {
|
||||
return std::format("L={:02}_nSteps={:04}_eps={:e}_chiMax={:02}", L, nSteps, eps.real(), chiMax);
|
||||
};
|
||||
// test default
|
||||
{
|
||||
std::string name = getName(L, nSteps, eps, chiMax);
|
||||
std::println("Running {}", name);
|
||||
double t = _runBenchmark(f, L, J, g, nSteps, dt, eps, chiMax);
|
||||
times[name] = t;
|
||||
}
|
||||
|
||||
for (auto _chiMax : chiMaxs) {
|
||||
std::string name = getName(L, nSteps, eps, _chiMax);
|
||||
std::println("Running {}", name);
|
||||
double t = _runBenchmark(f, L, J, g, nSteps, dt, eps, _chiMax);
|
||||
times[name] = t;
|
||||
}
|
||||
for (auto _eps : epss) {
|
||||
std::string name = getName(L, nSteps, _eps, chiMax);
|
||||
std::println("Running {}", name);
|
||||
double t = _runBenchmark(f, L, J, g, nSteps, dt, _eps, chiMax);
|
||||
times[name] = t;
|
||||
}
|
||||
for (auto _L : Ls) {
|
||||
std::string name = getName(_L, nSteps, eps, chiMax);
|
||||
std::println("Running {}", name);
|
||||
double t = _runBenchmark(f, _L, J, g, nSteps, dt, eps, chiMax);
|
||||
times[name] = t;
|
||||
}
|
||||
for (auto _nSteps : nStepss) {
|
||||
std::string name = getName(L, _nSteps, eps, chiMax);
|
||||
std::println("Running {}", name);
|
||||
double t = _runBenchmark(f, L, J, g, _nSteps, dt, eps, chiMax);
|
||||
times[name] = t;
|
||||
}
|
||||
|
||||
std::ofstream file("benchmark.csv", std::ios::app);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Error opening file.\n";
|
||||
return 1;
|
||||
}
|
||||
for (auto [name, t] : times) {
|
||||
std::println("{}: {:02f}", name, t);
|
||||
file << std::format("\"{}\",{:04f}\n", name, t);
|
||||
}
|
||||
file.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int runBenchmark_all() {
|
||||
// testing parameters
|
||||
// 6 * 4 * 7 * 5 = 840
|
||||
// ~10s each => 9000s => 2h30m
|
||||
std::vector<unsigned> chiMaxs{5, 15, 25, 35};
|
||||
std::vector<dtype> epss{1e-5, 1e-10, 1e-15, 1e-20};
|
||||
// std::vector<unsigned> Ls{4, 8, 12, 16, 20, 24, 28, 32};
|
||||
std::vector<unsigned> Ls{32, 28, 24, 20, 16, 12, 8, 4};
|
||||
|
||||
// std::vector<unsigned> nStepss{200, 400, 600, 800, 1000};
|
||||
std::vector<unsigned> nStepss{200, 400, 600};
|
||||
|
||||
std::map<std::string, double> times;
|
||||
|
||||
// default parameters
|
||||
double J = 1;
|
||||
double g = 0.7;
|
||||
dtype dt = 0.05;
|
||||
|
||||
// get a unique string including all test parameters
|
||||
std::function<Results (unsigned, double, double, unsigned, dtype, dtype, unsigned)> f(&_runTEBD);
|
||||
auto getName = [](unsigned L, unsigned nSteps, dtype eps, unsigned chiMax) {
|
||||
return std::format("L={:02}_nSteps={:04}_eps={:e}_chiMax={:02}", L, nSteps, eps.real(), chiMax);
|
||||
};
|
||||
|
||||
for (auto L : Ls) {
|
||||
for (auto nSteps : nStepss) {
|
||||
for (auto eps : epss) {
|
||||
for (auto chiMax : chiMaxs) {
|
||||
std::string name = getName(L, nSteps, eps, chiMax);
|
||||
std::println("Running {}", name);
|
||||
double t = _runBenchmark(f, L, J, g, nSteps, dt, eps, chiMax);
|
||||
times[name] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream file("benchmark.csv", std::ios::app);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Error opening file.\n";
|
||||
return 1;
|
||||
}
|
||||
for (auto [name, t] : times) {
|
||||
std::println("{}: {:02f}", name, t);
|
||||
file << std::format("\"{}\",{:04f}\n", name, t);
|
||||
}
|
||||
file.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <emscripten/bind.h>
|
||||
namespace ems = emscripten;
|
||||
EMSCRIPTEN_BINDINGS(benchmark) {
|
||||
ems::function("runBenchmark_oneAtATime", &runBenchmark_oneAtATime);
|
||||
ems::function("runBenchmark_all", &runBenchmark_all);
|
||||
};
|
||||
#endif
|
||||
|
3
src/benchmark.hpp
Normal file
3
src/benchmark.hpp
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
int runBenchmark_all();
|
||||
int runBenchmark_oneAtATime();
|
193
src/main.cpp
Normal file
193
src/main.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
#include <print>
|
||||
#include <iostream>
|
||||
// #include <array>
|
||||
#include "bose_hubbard.hpp"
|
||||
#include "mps.hpp"
|
||||
#include "transverse_field_ising.hpp"
|
||||
#include "tebd.hpp"
|
||||
#include "util.hpp"
|
||||
#include "type.hpp"
|
||||
|
||||
#include "benchmark.hpp"
|
||||
|
||||
using namespace std::complex_literals;
|
||||
|
||||
void testSVD() {
|
||||
e::Tensor<dtype, 4> t4(2, 3, 4, 5);
|
||||
auto data = t4.data();
|
||||
for (unsigned i = 0; i < t4.size(); i++) {
|
||||
data[i] = i;
|
||||
}
|
||||
printTensor(t4, "t4");
|
||||
auto [A, S, B] = split_truncate_theta<dtype>(t4, 20, 1e-10);
|
||||
printTensor(A, "A");
|
||||
printTensor(S, "S");
|
||||
printTensor(B, "B");
|
||||
e::Tensor<dtype, 4> t4reconstructed = A.contract(diagonal(S).contract(B, e::array<iP, 1>{iP{1, 0}}), e::array<iP, 1>{iP{2, 0}});
|
||||
// this can only yield the original tensor if the normalization of the schmidt values in the split_truncate_theta function is removed
|
||||
printTensor(t4reconstructed, "t4reconstructed");
|
||||
}
|
||||
|
||||
|
||||
void testBoseHubbardTEBD() {
|
||||
unsigned L = 8;
|
||||
unsigned nMax = 5;
|
||||
auto model = BoseHubbardModel1D<dtype>(L, dtype(1.), dtype(2.50), dtype(0.5), nMax);
|
||||
|
||||
dtype eps = 1e-10;
|
||||
unsigned chiMax = 20;
|
||||
dtype dt = 0.05;
|
||||
std::println("dt={}", dt);
|
||||
// std::cout << "leftT:\n" << *(model.getH_Bonds().front()) << std::endl;
|
||||
// std::cout << "leftT2:\n" << bondMatrix2Tensor(*(model.getH_BondsMatrices().front()), model.localDim) << std::endl;
|
||||
std::cout << "middleT:\n" << *(model.getH_Bonds().at(1)) << std::endl;
|
||||
//
|
||||
auto bonds = getTimeEvolutionMatrices(model.getH_BondsMatrices(), dt, model.localDim);
|
||||
std::cout << "N:\n" << model.getLadderOperators().getN() << std::endl;
|
||||
std::cout << "a:\n" << model.getLadderOperators().getA() << std::endl;
|
||||
std::cout << "aDagger:\n" << model.getLadderOperators().getADagger() << std::endl;
|
||||
// std::cout << "U_Bond:\n" << *(bonds.front()) << std::endl;
|
||||
// std::cout << "H_Bond:\n" << *(bonds.front()) << std::endl;
|
||||
|
||||
// MPS<dtype> psi = initMPS_spinUp<dtype>(L);
|
||||
MPS<dtype> psi = initMPS_nParticles<dtype>(L, nMax, 2);
|
||||
|
||||
unsigned nSteps = 300;
|
||||
// postUpdateFunction_t<dtype> fUpdate = postUpdateNoop<dtype>;
|
||||
|
||||
e::TensorMap<const e::Tensor<dtype, 2>> particleNumberOperator(model.getLadderOperators().getN().data(), model.localDim, model.localDim);
|
||||
postUpdateFunction_t<dtype> fUpdate = [&model, &particleNumberOperator](const MPS<dtype>& psi, unsigned i) {
|
||||
std::println("{:03}: N={:.2f} {}", i, psi.getSiteExpectationValueSum(particleNumberOperator).real() / model.L, psi.getChi());
|
||||
};
|
||||
// auto fUpdate = postUpdateFunction_t<dtype>([](const MPS<dtype>& psi, unsigned i){
|
||||
// std::println("i={:03}: <psi|psi>={}", i, psi.collapse(0));
|
||||
// });
|
||||
std::println("E = {}", model.energy(psi).real());
|
||||
// std::println("m = {}", psi.getSiteExpectationValues(sigma_z));
|
||||
std::println("chiS: {:b}", psi.getChi());
|
||||
psi.print();
|
||||
std::println("<psi|psi>={}", psi.collapse(0));
|
||||
|
||||
runTEBD_brickwall(psi, bonds, chiMax, eps, nSteps, fUpdate);
|
||||
std::println("E = {}", model.energy(psi).real());
|
||||
std::println("<N> = {}", psi.getSiteExpectationValueSum(particleNumberOperator).real() / model.L);
|
||||
// std::println("m = {}", psi.getSiteExpectationValues(sigma_z));
|
||||
std::println("chiS: {:b}", psi.getChi());
|
||||
// psi.print();
|
||||
std::println("<psi|psi>={}", psi.collapse(0));
|
||||
}
|
||||
|
||||
|
||||
void testTFI_TEBD() {
|
||||
unsigned L = 8;
|
||||
std::println("Make model");
|
||||
auto model = TransverseFieldIsingModel1D<dtype>(L, dtype(1.), dtype(1.5));
|
||||
// auto& mpo = *(model.getH_MPO().front());
|
||||
// e::Tensor<std::complex<float>, 4> mpo(3, 3, 2, 2);
|
||||
// mpo.setValues({
|
||||
// {
|
||||
// {{0,1},{2,3}},
|
||||
// {{4,5},{6,7}},
|
||||
// {{8,9},{10,11}}
|
||||
// }, {
|
||||
// {{12,13},{14,15}},
|
||||
// {{16,17},{18,19}},
|
||||
// {{20,21},{22,23}},
|
||||
// }, {
|
||||
// {{24,25},{26,27}},
|
||||
// {{28,29},{30,31}},
|
||||
// {{32,33},{34,35}}
|
||||
|
||||
// }});
|
||||
// std::cout << "first MPO: \n" << mpo << std::endl;
|
||||
// std::cout << "mapped : \n" << e::Map<e::Matrix<dtype, 6, 6, e::RowMajor>>(mpo.data()) << std::endl;
|
||||
// for (unsigned i = 0; i < mpo.size(); i++) {
|
||||
// std::cout << mpo.data()[i] << " ";
|
||||
// if ((i+1) % 2 == 0) { std::cout << "\n"; }
|
||||
// if ((i+1) % 4 == 0) { std::cout << "\n"; }
|
||||
// }
|
||||
e::Tensor<dtype, 2> sigma_z(2, 2);
|
||||
sigma_z.setValues({{1, 0}, {0, -1}});
|
||||
|
||||
dtype eps = 1e-10;
|
||||
unsigned chiMax = 20;
|
||||
dtype dt = 0.05i;
|
||||
std::println("dt={}", dt);
|
||||
std::cout << "leftT:\n" << *(model.getH_Bonds().front()) << std::endl;
|
||||
std::cout << "leftT2:\n" << bondMatrix2Tensor(*(model.getH_BondsMatrices().front()), model.localDim) << std::endl;
|
||||
std::cout << "middleT:\n" << *(model.getH_Bonds().at(1)) << std::endl;
|
||||
auto bonds = getTimeEvolutionMatrices(model.getH_BondsMatrices(), dt, model.localDim);
|
||||
std::cout << "U_Bond:\n" << *(bonds.front()) << std::endl;
|
||||
// std::cout << "H_Bond:\n" << *(bonds.front()) << std::endl;
|
||||
|
||||
// MPS<dtype> psi = initMPS_spinUp<dtype>(L);
|
||||
MPS<dtype> psi = initMPS_spinRight<dtype>(L);
|
||||
|
||||
unsigned nSteps = 100;
|
||||
postUpdateFunction_t<dtype> fUpdate = postUpdateNoop<dtype>;
|
||||
// auto fUpdate = postUpdateFunction_t<dtype>([](const MPS<dtype>& psi, unsigned i){
|
||||
// std::println("i={:03}: <psi|psi>={}", i, psi.collapse(0));
|
||||
// });
|
||||
std::println("E = {}", model.energy(psi).real());
|
||||
std::println("m = {}", psi.getSiteExpectationValues(sigma_z));
|
||||
std::println("chiS: {:b}", psi.getChi());
|
||||
psi.print();
|
||||
std::println("<psi|psi>={}", psi.collapse(0));
|
||||
|
||||
runTEBD_brickwall(psi, bonds, chiMax, eps, nSteps, fUpdate);
|
||||
// updateBond(psi, 0, *(bonds.at(0)), chiMax, eps);
|
||||
// updateBond(psi, 2, *(bonds.at(2)), chiMax, eps);
|
||||
// updateBond(psi, 4, *(bonds.at(4)), chiMax, eps);
|
||||
// updateBond(psi, 6, *(bonds.at(6)), chiMax, eps);
|
||||
// updateBond(psi, 1, *(bonds.at(1)), chiMax, eps);
|
||||
// updateBond(psi, 3, *(bonds.at(3)), chiMax, eps);
|
||||
// updateBond(psi, 5, *(bonds.at(5)), chiMax, eps);
|
||||
// updateBond(psi, 7, *(bonds.at(7)), chiMax, eps);
|
||||
|
||||
|
||||
std::println("E = {}", model.energy(psi).real());
|
||||
std::println("m = {}", psi.getSiteExpectationValues(sigma_z));
|
||||
std::println("chiS: {:b}", psi.getChi());
|
||||
psi.print();
|
||||
std::println("<psi|psi>={}", psi.collapse(0));
|
||||
|
||||
// for (unsigned i = 0; i < L; i++) {
|
||||
// std::println("i={:02}: <psi|psi>={}",i, psi.collapse(i));
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
// testSVD(); return 0;
|
||||
testBoseHubbardTEBD();
|
||||
// testTFI_TEBD();
|
||||
// return runBenchmark_oneAtATime();
|
||||
// return runBenchmark_all();
|
||||
|
||||
// std::println("Start calculations");
|
||||
// e::Tensor<dtype, 3> t1(10, 2, 10);
|
||||
// t1.setZero();
|
||||
// std::cout << t1 << std::endl;
|
||||
// t1(0,1,0) = .69;
|
||||
// std::cout << t1 << std::endl;
|
||||
|
||||
// e::Tensor<dtype, 3> t2(10, 2, 10);
|
||||
// t2.setRandom();
|
||||
// std::cout << t2 << std::endl;
|
||||
|
||||
// e::array<iP, 3> productDims = { iP(0, 0), iP(1, 1), iP(2, 2) };
|
||||
// auto t3 = t1.contract(t2, productDims);
|
||||
// std::cout << t3 << std::endl;
|
||||
|
||||
// double eps = 1e-8;
|
||||
// size_t chi_max = 5;
|
||||
|
||||
// verified energy function works as expected
|
||||
// unsigned L = 14;
|
||||
// for (double g : {0.5, 1., 1.5}) {
|
||||
// auto model2 = TFIModel<dtype>(L, dtype(1.), dtype(g));
|
||||
// auto mps = initMPSspinUp<dtype>(L);
|
||||
// std::println("g={} => E = {}", g, model2.energy(mps));
|
||||
//
|
||||
return 0;
|
||||
}
|
90
src/model.cpp
Normal file
90
src/model.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "model.hpp"
|
||||
#include "type.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
template<typename T>
|
||||
T Model1D<T>::energy(const MPS<T>& psi) const {
|
||||
assert(psi.getL() == this->L);
|
||||
T E = 0;
|
||||
for (unsigned i = 0; i < this->L-1; i++) {
|
||||
E += psi.getBondExpectationValue(*(this->H_Bonds.at(i)), i);
|
||||
}
|
||||
return E;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> constructMPO(const std::initializer_list<std::initializer_list<e::MatrixX<T>>>& matrices) {
|
||||
size_t rows = matrices.size();
|
||||
assert(rows > 0);
|
||||
size_t cols = matrices.begin()->size();
|
||||
assert(rows > 1);
|
||||
size_t localDim = matrices.begin()->begin()->rows();
|
||||
// TODO: check every matrix?
|
||||
assert(localDim == matrices.begin()->begin()->cols());
|
||||
e::Tensor<T, 4> mpo(rows, cols, localDim, localDim);
|
||||
// for (const auto& [rowIdx, row] : std::ranges::views::enumerate(matrices)) {
|
||||
size_t rowIdx = 0;
|
||||
for (const auto& row : matrices) {
|
||||
assert(row.size() == cols);
|
||||
size_t colIdx = 0;
|
||||
// for (const auto& [colIdx, mat] : std::ranges::views::enumerate(row)) {
|
||||
for (const auto& mat : row) {
|
||||
for (size_t i = 0; i < localDim; i++) {
|
||||
for (size_t j = 0; j < localDim; j++) {
|
||||
mpo(rowIdx, colIdx, i, j) = mat(i, j);
|
||||
}
|
||||
}
|
||||
colIdx++;
|
||||
}
|
||||
rowIdx++;
|
||||
}
|
||||
return mpo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
e::MatrixX<T> MPO_Tensor2Matrix(const e::Tensor<T, 4>& mpo) {
|
||||
size_t dim = mpo.dimension(0);
|
||||
assert(mpo.dimension(1) == dim);
|
||||
size_t localDim = mpo.dimension(2);
|
||||
assert(mpo.dimension(3) == localDim);
|
||||
e::MatrixX<T> matrix(dim * localDim, dim * localDim);
|
||||
for (size_t rowIdx = 0; rowIdx < dim; rowIdx++) {
|
||||
for (size_t colIdx = 0; colIdx < dim; colIdx++) {
|
||||
for (size_t i = 0; i < localDim; i++) {
|
||||
for (size_t j = 0; j < localDim; j++) {
|
||||
matrix(rowIdx * localDim + i, colIdx * localDim + j) = mpo(rowIdx, colIdx, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> bondMatrix2Tensor(const e::MatrixX<T>& bondMatrix, unsigned localDim) {
|
||||
e::Index matDim = bondMatrix.rows();
|
||||
assert(bondMatrix.cols() == matDim);
|
||||
assert(localDim > 0);
|
||||
assert(matDim % localDim == 0);
|
||||
e::Index tensorDim = matDim / localDim;
|
||||
e::Tensor<T, 4> bondTensor(tensorDim, tensorDim, localDim, localDim);
|
||||
for (unsigned rowIdx = 0; rowIdx < tensorDim; rowIdx++) {
|
||||
for (unsigned colIdx = 0; colIdx < tensorDim; colIdx++) {
|
||||
for (unsigned i = 0; i < localDim; i++) {
|
||||
for (unsigned j = 0; j < localDim; j++) {
|
||||
bondTensor(rowIdx, i, colIdx, j) = bondMatrix(rowIdx * localDim + i, colIdx * localDim + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bondTensor;
|
||||
}
|
||||
|
||||
|
||||
template e::Tensor<dtype, 4> constructMPO<dtype>(const std::initializer_list<std::initializer_list<e::MatrixX<dtype>>>& matrices);
|
||||
template e::MatrixX<dtype> MPO_Tensor2Matrix<dtype>(const e::Tensor<dtype, 4>& mpo);
|
||||
template e::Tensor<dtype, 4> bondMatrix2Tensor<dtype>(const e::MatrixX<dtype>&, unsigned);
|
||||
template class Model1D<dtype>;
|
80
src/model.hpp
Normal file
80
src/model.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
#include "mps.hpp"
|
||||
#include <eigen3/Eigen/Eigen>
|
||||
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
namespace e = Eigen;
|
||||
|
||||
using namespace std::complex_literals;
|
||||
|
||||
/**
|
||||
* @brief Construct a matrix product operator in tensor form
|
||||
* @matrices N x N initializer lists containing localDim x localDim matrices
|
||||
* @details
|
||||
* Constructs a tensor with indices r c i j, where r and c specify the matrix and i j are indices into the matrix
|
||||
*/
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> constructMPO(const std::initializer_list<std::initializer_list<e::MatrixX<T>>>& matrices);
|
||||
|
||||
template<typename T>
|
||||
e::MatrixX<T> MPO_Tensor2Matrix(const e::Tensor<T, 4>& mpo);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reshape a N*localDim x N*localDim matrix into a N x localDim x N x localDim tensor
|
||||
*/
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> bondMatrix2Tensor(const e::MatrixX<T>& bondMatrix, unsigned localDim);
|
||||
|
||||
|
||||
template<typename T>
|
||||
class Model1D {
|
||||
public:
|
||||
Model1D(size_t L, unsigned localDim) : L(L), localDim(localDim) {
|
||||
if (L <= 2) { // needs two bonds to function correctly
|
||||
throw std::invalid_argument("L must be larger than 2");
|
||||
}
|
||||
}
|
||||
virtual ~Model1D() {};
|
||||
inline const std::vector<std::shared_ptr<e::MatrixX<T>>>& getH_BondsMatrices() const { return H_BondsMatrices; }
|
||||
inline const std::vector<std::shared_ptr<e::Tensor<T, 4>>>& getH_Bonds() const { return H_Bonds; }
|
||||
inline const std::vector<std::shared_ptr<e::Tensor<T, 4>>>& getH_MPO() const { return H_MPO; }
|
||||
const size_t L;
|
||||
const unsigned localDim;
|
||||
T energy(const MPS<T>& psi) const;
|
||||
virtual std::string format() const = 0;
|
||||
protected:
|
||||
virtual void initH_Bonds() = 0;
|
||||
virtual void initH_MPO() = 0;
|
||||
/// Bonds in tensor form, used for `energy()` function
|
||||
std::vector<std::shared_ptr<e::Tensor<T, 4>>> H_Bonds;
|
||||
/// Bonds in matrix form, used for calculating time evolution
|
||||
std::vector<std::shared_ptr<e::MatrixX<T>>> H_BondsMatrices;
|
||||
std::vector<std::shared_ptr<e::Tensor<T, 4>>> H_MPO;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Class of pauli matrices
|
||||
* @details
|
||||
* Intendend for static initialization
|
||||
*/
|
||||
template<typename T>
|
||||
class PauliMatrices {
|
||||
public:
|
||||
PauliMatrices() :
|
||||
sigmaX({{0, 1}, {1, 0}}),
|
||||
sigmaY({{0if, -1if}, {1if, 0if}}),
|
||||
sigmaZ({{1, 0}, {0, -1}}),
|
||||
identity({{1, 0}, {0, 1}}) {}
|
||||
inline const e::Matrix2<T>& getSigmaX() const { return sigmaX; }
|
||||
inline const e::Matrix2<T>& getSigmaY() const { return sigmaY; }
|
||||
inline const e::Matrix2<T>& getSigmaZ() const { return sigmaZ; }
|
||||
inline const e::Matrix2<T>& getIdentity() const { return identity; }
|
||||
private:
|
||||
e::Matrix2<T> sigmaX;
|
||||
e::Matrix2<T> sigmaY;
|
||||
e::Matrix2<T> sigmaZ;
|
||||
e::Matrix2<T> identity;
|
||||
};
|
103
src/models/bose_hubbard.cpp
Normal file
103
src/models/bose_hubbard.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "bose_hubbard.hpp"
|
||||
#include <eigen3/unsupported/Eigen/KroneckerProduct>
|
||||
|
||||
template<typename T>
|
||||
LadderOperators<T>::LadderOperators(unsigned dim) : identity(dim, dim), aDagger(dim, dim), a(dim, dim), n(dim, dim) {
|
||||
identity.setZero();
|
||||
aDagger.setZero();
|
||||
a.setZero();
|
||||
n.setZero();
|
||||
identity(0, 0) = 1;
|
||||
|
||||
for (unsigned i = 1; i < dim; i++) {
|
||||
identity(i, i) = 1;
|
||||
n(i, i) = i;
|
||||
// TODO what if T = std::complex<float>?
|
||||
double sqrtN = std::sqrt(static_cast<double>(i));
|
||||
a(i-1, i) = sqrtN;
|
||||
aDagger(i, i-1) = sqrtN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void BoseHubbardModel1D<T>::initH_Bonds() {
|
||||
T tHalf = this->t * static_cast<T>(0.5);
|
||||
T tFull = this->t;
|
||||
|
||||
/// @todo TODO figure out which is right. Doesnt t need to be halfed at the edges and not the middle?
|
||||
e::MatrixX<T> N_NminusI = this->lo.getN() * (this->lo.getN() - this->lo.getIdentity());
|
||||
e::MatrixX<T> singleParticlePart(
|
||||
(
|
||||
e::kroneckerProduct(this->lo.getIdentity(), N_NminusI)
|
||||
- e::kroneckerProduct(N_NminusI, this->lo.getIdentity())
|
||||
) * (this->U/static_cast<T>(2))
|
||||
- e::kroneckerProduct(this->lo.getN(), this->lo.getIdentity()) * (this->mu/static_cast<T>(2))
|
||||
- e::kroneckerProduct(this->lo.getIdentity(), this->lo.getN()) * (this->mu/static_cast<T>(2))
|
||||
);
|
||||
// TODO this is wrong, needs A and Adagger; check which t or t/half or identities are required
|
||||
auto left = std::make_shared<e::MatrixX<T>>(
|
||||
singleParticlePart
|
||||
- tFull * e::kroneckerProduct(this->lo.getADagger(), this->lo.getA())
|
||||
- tFull * e::kroneckerProduct(this->lo.getA(), this->lo.getADagger())
|
||||
);
|
||||
auto right = std::make_shared<e::MatrixX<T>>(
|
||||
singleParticlePart
|
||||
- tFull * e::kroneckerProduct(this->lo.getADagger(), this->lo.getA())
|
||||
- tFull * e::kroneckerProduct(this->lo.getA(), this->lo.getADagger())
|
||||
);
|
||||
auto middle = std::make_shared<e::MatrixX<T>>(
|
||||
singleParticlePart
|
||||
- tFull * e::kroneckerProduct(this->lo.getADagger(), this->lo.getA())
|
||||
- tFull * e::kroneckerProduct(this->lo.getA(), this->lo.getADagger())
|
||||
);
|
||||
// The matrices are N*N x N*N -> reshape to N x N x N x N tensors
|
||||
unsigned N = this->localDim;
|
||||
auto leftT = std::make_shared<e::Tensor<T, 4>>(N, N, N, N);
|
||||
auto middleT = std::make_shared<e::Tensor<T, 4>>(N, N, N, N);
|
||||
auto rightT = std::make_shared<e::Tensor<T, 4>>(N, N, N, N);
|
||||
for (unsigned i1 = 0; i1 < N; i1++) {
|
||||
for (unsigned i2 = 0; i2 < N; i2++) {
|
||||
for (unsigned i3 = 0; i3 < N; i3++) {
|
||||
for (unsigned i4 = 0; i4 < N; i4++) {
|
||||
(*leftT)(i1, i2, i3, i4) = (*left)(i1 * N + i2, i3 * N + i4);
|
||||
(*middleT)(i1, i2, i3, i4) = (*middle)(i1 * N + i2, i3 * N+ i4);
|
||||
(*rightT)(i1, i2, i3, i4) = (*right)(i1 * N + i2, i3 * N + i4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this->H_Bonds.reserve(this->L-1);
|
||||
this->H_Bonds.push_back(leftT);
|
||||
for (unsigned i = 0; i < this->L - 3; i++) { // there are L-3 middle bonds
|
||||
this->H_Bonds.push_back(middleT);
|
||||
}
|
||||
this->H_Bonds.push_back(rightT);
|
||||
|
||||
// TODO: merge or remove tensor version
|
||||
this->H_BondsMatrices.reserve(this->L-1);
|
||||
this->H_BondsMatrices.push_back(left);
|
||||
for (unsigned i = 0; i < this->L - 3; i++) { // there are L-3 middle bonds
|
||||
this->H_BondsMatrices.push_back(middle);
|
||||
}
|
||||
this->H_BondsMatrices.push_back(right);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void BoseHubbardModel1D<T>::initH_MPO() {
|
||||
e::MatrixX<T> zero(this->localDim, this->localDim);
|
||||
zero.setZero();
|
||||
|
||||
auto W = std::make_shared<e::Tensor<T, 4>>(std::move(constructMPO<T>({
|
||||
{this->lo.getIdentity(), this->lo.getADagger(), this->lo.getA(), (this->U / 2. * (this->lo.getN() * this->lo.getN() - this->lo.getN()) - this->mu * this->lo.getN())},
|
||||
{zero, zero, zero, (-this->t * this->lo.getA())},
|
||||
{zero, zero, zero, (-this->t * this->lo.getADagger())},
|
||||
{zero, zero, zero, this->lo.getIdentity()}
|
||||
})));
|
||||
// same for all sites
|
||||
this->H_MPO = std::vector<std::shared_ptr<e::Tensor<T, 4>>>(this->L, W);
|
||||
}
|
||||
|
||||
template class LadderOperators<dtype>;
|
||||
template class BoseHubbardModel1D<dtype>;
|
57
src/models/bose_hubbard.hpp
Normal file
57
src/models/bose_hubbard.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include "model.hpp"
|
||||
|
||||
/**
|
||||
* @brief Helper class constructing identity, particle number and both ladder operators in one loop.
|
||||
*/
|
||||
template<typename T>
|
||||
class LadderOperators {
|
||||
public:
|
||||
LadderOperators(unsigned dim);
|
||||
inline const e::MatrixX<T>& getIdentity() const { return identity; }
|
||||
inline const e::MatrixX<T>& getADagger() const { return aDagger; }
|
||||
inline const e::MatrixX<T>& getA() const { return a; }
|
||||
inline const e::MatrixX<T>& getN() const { return n; }
|
||||
private:
|
||||
e::MatrixX<T> identity;
|
||||
e::MatrixX<T> aDagger;
|
||||
e::MatrixX<T> a;
|
||||
e::MatrixX<T> n;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bose-Hubbard Model in 1 dimension
|
||||
* @details
|
||||
* The middle bonds are:
|
||||
* TODO \f[ B_i = J \, \sigma^x_i \otimes \sigma^x_{i+1} + \frac{g}{2} \,\sigma^z_i \otimes I + \frac{g}{2} \, I \otimes \sigma^z_{i+1} \f]
|
||||
*
|
||||
* The MPO is:
|
||||
* \f[ W = \begin{pmatrix} I & \hat{a}^\dagger & \hat{a} & \frac{U}{2}\hat{n}(\hat{n} - I) - \mu\hat{n} \\ 0 & 0 & 0 & -t \hat{a} \\ 0 & 0 & 0 & -t \hat{a}^\dagger\\ 0 & 0 & 0 & I \end{pmatrix} \f]
|
||||
*/
|
||||
template<typename T>
|
||||
class BoseHubbardModel1D : public Model1D<T> {
|
||||
public:
|
||||
BoseHubbardModel1D(size_t L, T U, T t, T mu, size_t nMax) : Model1D<T>(L, nMax+1), U(U), t(t), mu(mu), lo(nMax+1) {
|
||||
this->initH_Bonds();
|
||||
this->initH_MPO();
|
||||
}
|
||||
inline const T& getU() const { return U; }
|
||||
inline const T& gett() const { return t; }
|
||||
inline const T& getmu() const { return mu; }
|
||||
inline const LadderOperators<T>& getLadderOperators() const { return lo; }
|
||||
|
||||
virtual std::string format() const override {
|
||||
return std::format("BoseHubbardModel1D(L={},U={},t={},mu={})", this->L, this->U, this->t, this->mu);
|
||||
}
|
||||
|
||||
protected:
|
||||
void initH_Bonds() override;
|
||||
void initH_MPO() override;
|
||||
private:
|
||||
T U;
|
||||
T t;
|
||||
T mu;
|
||||
LadderOperators<T> lo;
|
||||
};
|
||||
|
||||
|
74
src/models/transverse_field_ising.cpp
Normal file
74
src/models/transverse_field_ising.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "transverse_field_ising.hpp"
|
||||
|
||||
#include <eigen3/unsupported/Eigen/KroneckerProduct>
|
||||
#include "model.hpp"
|
||||
|
||||
template<typename T>
|
||||
PauliMatrices<T> TransverseFieldIsingModel1D<T>::pm;
|
||||
|
||||
template<typename T>
|
||||
void TransverseFieldIsingModel1D<T>::initH_Bonds() {
|
||||
T gHalf = this->g * static_cast<T>(0.5);
|
||||
// TODO: improve code or directly initialize the tensors
|
||||
auto left = std::make_shared<e::MatrixX<T>>(
|
||||
e::kroneckerProduct(pm.getSigmaX(), pm.getSigmaX()) * (-J) -
|
||||
this->g * e::kroneckerProduct(pm.getSigmaZ(), pm.getIdentity()) -
|
||||
gHalf * e::kroneckerProduct(pm.getIdentity(), pm.getSigmaZ())
|
||||
);
|
||||
auto right = std::make_shared<e::MatrixX<T>>(
|
||||
e::kroneckerProduct(pm.getSigmaX(), pm.getSigmaX()) * (-J) -
|
||||
gHalf * e::kroneckerProduct(pm.getSigmaZ(), pm.getIdentity()) -
|
||||
this->g * e::kroneckerProduct(pm.getIdentity(), pm.getSigmaZ())
|
||||
);
|
||||
auto middle = std::make_shared<e::MatrixX<T>>(
|
||||
e::kroneckerProduct(pm.getSigmaX(), pm.getSigmaX()) * (-J) -
|
||||
gHalf * e::kroneckerProduct(pm.getSigmaZ(), pm.getIdentity()) -
|
||||
gHalf * e::kroneckerProduct(pm.getIdentity(), pm.getSigmaZ())
|
||||
);
|
||||
auto leftT = std::make_shared<e::Tensor<T, 4>>(2, 2, 2, 2);
|
||||
auto middleT = std::make_shared<e::Tensor<T, 4>>(2, 2, 2, 2);
|
||||
auto rightT = std::make_shared<e::Tensor<T, 4>>(2, 2, 2, 2);
|
||||
for (unsigned i1 = 0; i1 < 2; i1++) {
|
||||
for (unsigned i2 = 0; i2 < 2; i2++) {
|
||||
for (unsigned i3 = 0; i3 < 2; i3++) {
|
||||
for (unsigned i4 = 0; i4 < 2; i4++) {
|
||||
(*leftT)(i1, i2, i3, i4) = (*left)(i1 * 2 + i2, i3 * 2 + i4);
|
||||
(*middleT)(i1, i2, i3, i4) = (*middle)(i1 * 2 + i2, i3 * 2+ i4);
|
||||
(*rightT)(i1, i2, i3, i4) = (*right)(i1 * 2 + i2, i3 * 2 + i4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// *leftT = Bond_Matrix2Tensor(*left, 2);
|
||||
// *middleT = Bond_Matrix2Tensor(*middle, 2);
|
||||
// *rightT = Bond_Matrix2Tensor(*right, 2);
|
||||
this->H_Bonds.reserve(this->L-1);
|
||||
this->H_Bonds.push_back(leftT);
|
||||
for (unsigned i = 0; i < this->L - 3; i++) { // there are L-3 middle bonds
|
||||
this->H_Bonds.push_back(middleT);
|
||||
}
|
||||
this->H_Bonds.push_back(rightT);
|
||||
|
||||
// TODO: merge or remove tensor version
|
||||
this->H_BondsMatrices.reserve(this->L-1);
|
||||
this->H_BondsMatrices.push_back(left);
|
||||
for (unsigned i = 0; i < this->L - 3; i++) { // there are L-3 middle bonds
|
||||
this->H_BondsMatrices.push_back(middle);
|
||||
}
|
||||
this->H_BondsMatrices.push_back(right);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void TransverseFieldIsingModel1D<T>::initH_MPO() {
|
||||
e::Matrix2<T> zero(2, 2);
|
||||
zero.setZero();
|
||||
auto W = std::make_shared<e::Tensor<T, 4>>(std::move(constructMPO<T>({
|
||||
{this->pm.getIdentity(), this->pm.getSigmaZ(), (this->g * this->pm.getSigmaX())},
|
||||
{zero, zero, (-this->J * this->pm.getSigmaZ())},
|
||||
{zero, zero, this->pm.getIdentity()}
|
||||
})));
|
||||
// same for all sites
|
||||
this->H_MPO = std::vector<std::shared_ptr<e::Tensor<T, 4>>>(this->L, W);
|
||||
}
|
||||
|
||||
template class TransverseFieldIsingModel1D<dtype>;
|
36
src/models/transverse_field_ising.hpp
Normal file
36
src/models/transverse_field_ising.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include "model.hpp"
|
||||
|
||||
/**
|
||||
* @brief Transverse Field Ising Model in 1 dimension
|
||||
* @details
|
||||
* The middle bonds are:
|
||||
* \f[ B_i = J \, \sigma^x_i \otimes \sigma^x_{i+1} + \frac{g}{2} \,\sigma^z_i \otimes I + \frac{g}{2} \, I \otimes \sigma^z_{i+1} \f]
|
||||
*
|
||||
* The MPO is:
|
||||
* \f[ W = \begin{pmatrix} I & \sigma_z & g \, \sigma_x \\ 0 & 0 & J\,\sigma_z \\ 0 & 0 & I \end{pmatrix} \f]
|
||||
*/
|
||||
template<typename T>
|
||||
class TransverseFieldIsingModel1D : public Model1D<T> {
|
||||
public:
|
||||
TransverseFieldIsingModel1D(size_t L, T J, T g) : Model1D<T>(L, 2), J(J), g(g) {
|
||||
// std::println("TFIModel: L={}, J={}, g={}", L, J, g);
|
||||
this->initH_Bonds();
|
||||
this->initH_MPO();
|
||||
}
|
||||
inline const T& getJ() const { return J; }
|
||||
inline const T& getg() const { return g; }
|
||||
|
||||
virtual std::string format() const override {
|
||||
return std::format("TransverseFieldIsingModel1D(L={},J={},g={})", this->L, this->J, this->g);
|
||||
}
|
||||
protected:
|
||||
void initH_Bonds() override;
|
||||
|
||||
void initH_MPO() override;
|
||||
private:
|
||||
T J;
|
||||
T g;
|
||||
static PauliMatrices<T> pm;
|
||||
};
|
||||
|
154
src/mpl_colors.py
Normal file
154
src/mpl_colors.py
Normal file
@ -0,0 +1,154 @@
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
from cycler import cycler
|
||||
|
||||
# Palette
|
||||
P = {
|
||||
"bg0": "#282828",
|
||||
"bg0-hard": "#1d2021",
|
||||
"bg0-soft": "#32302f",
|
||||
"bg1": "#3c3836",
|
||||
"bg2": "#504945",
|
||||
"bg3": "#665c54",
|
||||
"bg4": "#7c6f64",
|
||||
"fg0": "#fbf1c7",
|
||||
"fg0-hard": "#f9f5d7",
|
||||
"fg0-soft": "#f2e5bc",
|
||||
"fg1": "#ebdbb2",
|
||||
"fg2": "#d5c4a1",
|
||||
"fg3": "#bdae93",
|
||||
"fg4": "#a89984",
|
||||
"dark-red": "#cc241d",
|
||||
"dark-green": "#98971a",
|
||||
"dark-yellow": "#d79921",
|
||||
"dark-blue": "#458588",
|
||||
"dark-purple": "#b16286",
|
||||
"dark-aqua": "#689d6a",
|
||||
"dark-orange": "#d65d0e",
|
||||
"dark-gray": "#928374",
|
||||
"light-red": "#fb4934",
|
||||
"light-green": "#b8bb26",
|
||||
"light-yellow": "#fabd2f",
|
||||
"light-blue": "#83a598",
|
||||
"light-purple": "#d3869b",
|
||||
"light-aqua": "#8ec07c",
|
||||
"light-orange": "#f38019",
|
||||
"light-gray": "#a89984",
|
||||
"alt-red": "#9d0006",
|
||||
"alt-green": "#79740e",
|
||||
"alt-yellow": "#b57614",
|
||||
"alt-blue": "#076678",
|
||||
"alt-purple": "#8f3f71",
|
||||
"alt-aqua": "#427b58",
|
||||
"alt-orange": "#af3a03",
|
||||
"alt-gray": "#7c6f64",
|
||||
}
|
||||
|
||||
COLORS_LIGHT = [
|
||||
P["light-blue"],
|
||||
P["light-orange"],
|
||||
P["light-green"],
|
||||
P["light-red"],
|
||||
P["light-purple"],
|
||||
P["light-yellow"],
|
||||
P["light-aqua"],
|
||||
P["light-gray"]]
|
||||
|
||||
COLORS_DARK = [
|
||||
P["dark-blue"],
|
||||
P["dark-orange"],
|
||||
P["dark-green"],
|
||||
P["dark-red"],
|
||||
P["dark-purple"],
|
||||
P["dark-yellow"],
|
||||
P["dark-aqua"],
|
||||
P["dark-gray"]]
|
||||
|
||||
COLORS_ALT = [
|
||||
P["alt-blue"],
|
||||
P["alt-orange"],
|
||||
P["alt-green"],
|
||||
P["alt-red"],
|
||||
P["alt-purple"],
|
||||
P["alt-yellow"],
|
||||
P["alt-aqua"],
|
||||
P["alt-gray"]]
|
||||
|
||||
COLORS = COLORS_LIGHT
|
||||
|
||||
def set_colorscheme(variant="dark"):
|
||||
global COLORS
|
||||
if variant == "dark":
|
||||
FIG_BG_COLOR = P["bg0"]
|
||||
PLT_FG_COLOR = P["fg0"]
|
||||
PLT_BG_COLOR = P["bg0"]
|
||||
PLT_GRID_COLOR = P["bg2"]
|
||||
LEGEND_FG_COLOR = PLT_FG_COLOR
|
||||
LEGEND_BG_COLOR = P["bg1"]
|
||||
LEGEND_BORDER_COLOR = P["bg2"]
|
||||
COLORS = COLORS_LIGHT
|
||||
else:
|
||||
FIG_BG_COLOR = P["fg0"]
|
||||
PLT_FG_COLOR = P["bg0"]
|
||||
PLT_BG_COLOR = P["fg0"]
|
||||
PLT_GRID_COLOR = P["fg2"]
|
||||
LEGEND_FG_COLOR = PLT_FG_COLOR
|
||||
LEGEND_BG_COLOR = P["fg1"]
|
||||
LEGEND_BORDER_COLOR = P["fg2"]
|
||||
COLORS = COLORS_DARK
|
||||
if variant == "alt":
|
||||
COLORS = COLORS_ALT
|
||||
|
||||
color_rcParams = {
|
||||
'axes.edgecolor': PLT_FG_COLOR,
|
||||
'axes.facecolor': PLT_BG_COLOR,
|
||||
'axes.labelcolor': PLT_FG_COLOR,
|
||||
'axes.titlecolor': 'auto',
|
||||
# 'axes.prop_cycle': cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']),
|
||||
'axes.prop_cycle': cycler('color', COLORS),
|
||||
# 'axes3d.xaxis.panecolor': (0.95, 0.95, 0.95, 0.5),
|
||||
# 'axes3d.yaxis.panecolor': (0.9, 0.9, 0.9, 0.5),
|
||||
# 'axes3d.zaxis.panecolor': (0.925, 0.925, 0.925, 0.5),
|
||||
# 'boxplot.boxprops.color': 'black',
|
||||
# 'boxplot.capprops.color': 'black',
|
||||
# 'boxplot.flierprops.color': 'black',
|
||||
# 'boxplot.flierprops.markeredgecolor': 'black',
|
||||
# 'boxplot.flierprops.markeredgewidth': 1.0,
|
||||
# 'boxplot.flierprops.markerfacecolor': 'none',
|
||||
# 'boxplot.meanprops.color': 'C2',
|
||||
# 'boxplot.meanprops.markeredgecolor': 'C2',
|
||||
# 'boxplot.meanprops.markerfacecolor': 'C2',
|
||||
# 'boxplot.meanprops.markersize': 6.0,
|
||||
# 'boxplot.medianprops.color': 'C1',
|
||||
# 'boxplot.whiskerprops.color': 'black',
|
||||
'figure.edgecolor': PLT_BG_COLOR,
|
||||
'figure.facecolor': PLT_BG_COLOR,
|
||||
# 'figure.figsize': [6.4, 4.8],
|
||||
# 'figure.frameon': True,
|
||||
# 'figure.labelsize': 'large',
|
||||
'grid.color': PLT_GRID_COLOR,
|
||||
# 'hatch.color': 'black',
|
||||
'legend.edgecolor': LEGEND_BORDER_COLOR,
|
||||
'legend.facecolor': LEGEND_BG_COLOR,
|
||||
'xtick.color': PLT_FG_COLOR,
|
||||
'ytick.color': PLT_FG_COLOR,
|
||||
'xtick.labelcolor': PLT_FG_COLOR,
|
||||
'ytick.labelcolor': PLT_FG_COLOR,
|
||||
# 'lines.color': 'C0',
|
||||
'text.color': PLT_FG_COLOR,
|
||||
}
|
||||
|
||||
for k, v in color_rcParams.items():
|
||||
plt.rcParams[k] = v
|
||||
|
||||
# override single char codes
|
||||
mpl.colors.get_named_colors_mapping()["b"] = COLORS[0]
|
||||
mpl.colors.get_named_colors_mapping()["o"] = COLORS[1]
|
||||
mpl.colors.get_named_colors_mapping()["g"] = COLORS[2]
|
||||
mpl.colors.get_named_colors_mapping()["r"] = COLORS[3]
|
||||
mpl.colors.get_named_colors_mapping()["m"] = COLORS[4]
|
||||
mpl.colors.get_named_colors_mapping()["y"] = COLORS[5]
|
||||
mpl.colors.get_named_colors_mapping()["c"] = COLORS[6]
|
||||
mpl.colors.get_named_colors_mapping()["k"] = P["fg0"]
|
||||
mpl.colors.get_named_colors_mapping()["w"] = P["bg0"]
|
||||
|
289
src/mps.cpp
Normal file
289
src/mps.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
#include "mps.hpp"
|
||||
#include "type.hpp"
|
||||
#include "util.hpp"
|
||||
#include <print>
|
||||
|
||||
|
||||
template<typename T>
|
||||
MPS<T>::MPS(std::vector<BTensor_t>&& Bs, std::vector<STensor_t>&& Ss) {
|
||||
this->L = Bs.size();
|
||||
assert(this->L > 0);
|
||||
assert(Ss.size() == this->L);
|
||||
this->Bs = std::move(Bs);
|
||||
this->Ss = std::move(Ss);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
MPS<T>::BTensor_t MPS<T>::getTheta1(size_t siteIdx) const {
|
||||
assert(siteIdx < L);
|
||||
auto diag = diagonal(this->S(siteIdx));
|
||||
return diag.contract(this->B(siteIdx), e::array<iP, 1>{iP(1, 0)});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
e::Tensor<T, 4> MPS<T>::getTheta2(size_t bondIdx) const {
|
||||
size_t j = bondIdx + 1;
|
||||
assert(j < L);
|
||||
auto theta1 = this->getTheta1(bondIdx);
|
||||
return theta1.contract(this->B(j), e::array<iP, 1>{iP(2, 0)});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<unsigned> MPS<T>::getChi() const {
|
||||
std::vector<unsigned> chis(this->L-1);
|
||||
for (size_t i = 0; i < (L - 1); i++) {
|
||||
chis.at(i) = this->B(i).dimension(2);
|
||||
}
|
||||
return chis;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MPS<T>::getSiteExpectationValue(const e::Tensor<T, 2>& op, size_t siteIdx) const {
|
||||
auto theta1 = this->getTheta1(siteIdx);
|
||||
// optheta: vL, vR, i
|
||||
e::Tensor<T, 3> opTheta = theta1.contract(op, e::array<iP, 1>{iP(1, 1)});
|
||||
e::Tensor<T, 0> expVal = opTheta.contract(theta1.conjugate(), e::array<iP, 3>{iP(0, 0), iP(2, 1), iP(1, 2)});
|
||||
T retVal = expVal(0);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> MPS<T>::getSiteExpectationValues(const e::Tensor<T, 2>& op) const {
|
||||
std::vector<T> results;
|
||||
results.reserve(this->L);
|
||||
for (size_t i = 0; i < this->L; i++) {
|
||||
results.push_back(this->getSiteExpectationValue(op, i));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MPS<T>::getSiteExpectationValueSum(const e::Tensor<T, 2>& op) const {
|
||||
dtype expVal = 0;
|
||||
for (unsigned i = 0; i < this->getL(); i++) {
|
||||
expVal += this->getSiteExpectationValue(op, i);
|
||||
}
|
||||
return expVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MPS<T>::getBondExpectationValue(const e::Tensor<T, 4>& op, size_t bondIdx) const {
|
||||
auto theta2 = this->getTheta2(bondIdx); // vL i j vR
|
||||
// vL [i] [i+1] vR x i i+1 [i*] [i+1*]
|
||||
e::Tensor<T, 4> opTheta = theta2.contract(op, e::array<iP, 2>{iP{1, 2}, iP{2, 3}});
|
||||
// [vL] [vR] [i] [i+1] x [vL*] [i*] [i+1*] [vR*]
|
||||
e::Tensor<T, 0> expVal = opTheta.contract(theta2.conjugate(), e::array<iP, 4>{iP(0, 0), iP(1, 3), iP(2, 1), iP{3, 2}});
|
||||
T retVal = expVal(0);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T MPS<T>::getEntanglementEntropy(size_t bondIndex) const {
|
||||
assert(bondIndex < this->L-1);
|
||||
const auto& S = this->S(bondIndex+1);
|
||||
STensor_t Ssquared = S * S;
|
||||
e::Tensor<dtype, 0> retVal = -(Ssquared * Ssquared.log()).sum();
|
||||
return retVal(0);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
T MPS<T>::collapse(size_t siteIndex) const {
|
||||
// const STensor_t& S = this->S(siteIndex);
|
||||
// e::Tensor<T, 0> SS = S.contract(S.conjugate(), e::array<iP, 1>{iP{0,0}});
|
||||
// std::println("S[{}] contracted with its conjugate = {}", siteIndex, SS(0));
|
||||
|
||||
auto theta = this->getTheta1(siteIndex);
|
||||
// vR vR*
|
||||
e::Tensor<dtype, 2> thetaTheta = theta.contract(theta.conjugate(), e::array<iP, 2>{iP{0, 0}, iP{1, 1}});
|
||||
for (size_t i = siteIndex+1; i < this->L; i++) {
|
||||
// vL vR vL* vR*
|
||||
e::Tensor<dtype, 4> BB = this->B(i).contract(this->B(i).conjugate(), e::array<iP, 1>{iP{1, 1}});
|
||||
e::Tensor<dtype, 2> thetaTheta2 = thetaTheta.contract(BB, e::array<iP, 2>{iP{0, 0}, iP{1, 2}});
|
||||
std::swap(thetaTheta, thetaTheta2);
|
||||
}
|
||||
e::Tensor<dtype, 1> id(thetaTheta.dimension(0));
|
||||
id.setConstant(1);
|
||||
auto idDiag = diagonal(id);
|
||||
e::Tensor<dtype, 0> retval = thetaTheta.contract(idDiag, e::array<iP, 2>{iP{0, 0}, iP{1, 1}});
|
||||
return retval(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
e::MatrixX<T> tensor2Matrix(const e::Tensor<T, 4>& t) {
|
||||
size_t d0 = t.dimension(0);
|
||||
size_t d1 = t.dimension(1);
|
||||
size_t d2 = t.dimension(2);
|
||||
size_t d3 = t.dimension(3);
|
||||
e::MatrixX<T> matrix(d0 * d1, d2 * d3);
|
||||
for (size_t i0 = 0; i0 < d0; i0++) {
|
||||
for (size_t i1 = 0; i1 < d1; i1++) {
|
||||
for (size_t i2 = 0; i2 < d2; i2++) {
|
||||
for (size_t i3 = 0; i3 < d3; i3++) {
|
||||
// Variant 1 (consistent with what a np.reshape would give)
|
||||
// matrix(i0 * d1 + i1, i2 * d3 + i3) = t(i0, i1, i2, i3);
|
||||
// Variant 2 (consistent with what using Eigen::Map on Tensor<ColumnMajor> produces)
|
||||
matrix(i0 * d1 + i1, i3 * d2 + i2) = t(i0, i1, i2, i3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
template<typename dtype>
|
||||
std::tuple<e::Tensor<dtype, 3>, e::Tensor<dtype, 1>, e::Tensor<dtype, 3>>
|
||||
split_truncate_theta(const e::Tensor<dtype, 4>& theta, size_t chiMax, dtype eps) {
|
||||
// Unpack dimensions of the input tensor
|
||||
e::Index chivL = theta.dimension(0);
|
||||
e::Index dL = theta.dimension(1);
|
||||
e::Index dR = theta.dimension(2);
|
||||
e::Index chivR = theta.dimension(3);
|
||||
|
||||
|
||||
|
||||
// Reshape theta to 2D matrix for the SVD
|
||||
using MatX = e::Matrix<dtype, -1, -1>;
|
||||
/// todo (DONE): Possible optimization: either use a Map and later adjust the matrix to tensor loops, or globally use RowMajor memory layout?
|
||||
// The map approach produces the same Matrix is tensor2Matrix with Variant 2
|
||||
MatX theta_mat = e::Map<const MatX>(theta.data(), chivL * dL, dR * chivR);
|
||||
// MatX theta_mat = tensor2Matrix(theta);
|
||||
|
||||
// std::cout << "theta:\n" << theta << "theta_mat\n": << theta_mat << std::endl;
|
||||
// std::cout << "theta_mat = " << std::endl;
|
||||
// std::cout << theta_mat << std::endl;
|
||||
|
||||
// perform SVD: theta = U * diag(S) * V^T
|
||||
constexpr int SVDOptions = e::ComputeThinU | e::ComputeThinV;
|
||||
e::JacobiSVD<MatX, SVDOptions> svd(theta_mat);
|
||||
// e::BDCSVD<MatX, SVDOptions> svd(theta_mat);
|
||||
const MatX& U = svd.matrixU();
|
||||
const e::VectorX<dtype>& S = svd.singularValues();
|
||||
const MatX& V = svd.matrixV().transpose();
|
||||
|
||||
// determine the truncation dimension based on chi_max and eps
|
||||
int chivC = static_cast<int>(std::min(chiMax, static_cast<size_t>((S.real().array() > std::real(eps)).count())));
|
||||
if (chivC < 1) {
|
||||
std::println("WARNING: chivC = 0. Setting to 1");
|
||||
chivC = 1;
|
||||
}
|
||||
assert(chivC >= 1);
|
||||
assert(chivC <= S.size());
|
||||
|
||||
// NOT NEEDED BECAUSE ITS ALREADY RETURNED IN ORDER
|
||||
// sort indices by singular values (descending order) and truncate
|
||||
// std::vector<size_t> indices(S.size());
|
||||
// std::iota(indices.begin(), indices.end(), 0); // fill indices with [0, 1, 2, ..., Y.size()-1]
|
||||
// std::partial_sort(indices.begin(), indices.begin() + chivC, indices.end(),
|
||||
// [&](size_t a, size_t b) { return S(a) > S(b); });
|
||||
|
||||
// std::println("chivL={}, dL={}, dR={}, chivR={}", chivL, dL, dR, chivR);
|
||||
// std::println("theta_mat.shape = {}, {}", theta_mat.rows(), theta_mat.cols());
|
||||
// std::println("U.shape = {}, {}", U.rows(), U.cols());
|
||||
// std::println("S.shape = {}, {}", S.asDiagonal().rows(), S.asDiagonal().cols());
|
||||
// std::println("V.shape = {}, {}", V.rows(), V.cols());
|
||||
// std::println("S.shape = {}", S.rows());
|
||||
// std::println("chivC={}", chivC);
|
||||
|
||||
|
||||
// TEST
|
||||
// MatX theta2 = U * S.asDiagonal() * V;
|
||||
// std::cout << "theta2" << std::endl << theta2 << std::endl;
|
||||
// for (int i = 0; i < theta2.size(); i++) {
|
||||
// std::print("{} ", theta2.data()[i]);
|
||||
// }
|
||||
// std::println();
|
||||
|
||||
// std::cout << "U" << std::endl << U << std::endl;
|
||||
// std::cout << "U[0, 1]=" << U(0, 1) << std::endl;
|
||||
// std::cout << "S" << std::endl << S << std::endl;
|
||||
// std::cout << "V" << std::endl << V << std::endl;
|
||||
|
||||
// MatX Xtrunc(dL * chivL, chivC)
|
||||
// Truncated versions for debugging
|
||||
// MatX Utrunc = U(e::placeholders::all, e::seq(0, chivC));
|
||||
// e::VectorXd Strunc = S(e::seq(0, chivC));
|
||||
// MatX Vtrunc = V(e::seq(0, chivC), e::placeholders::all);
|
||||
|
||||
// std::cout << "Utrunc" << std::endl << Utrunc << std::endl;
|
||||
// std::cout << "Strunc" << std::endl << Strunc << std::endl;
|
||||
// std::cout << "Vtrunc" << std::endl << Vtrunc << std::endl;
|
||||
// std::println("U.shape = {}, {}", Utrunc.rows(), Utrunc.cols());
|
||||
// std::println("S.shape = {}, {}", Strunc.asDiagonal().rows(), Strunc.asDiagonal().cols());
|
||||
// std::println("V.shape = {}, {}", Vtrunc.rows(), Vtrunc.cols());
|
||||
|
||||
// MatX theta3 = Utrunc * Strunc.asDiagonal() * Vtrunc;
|
||||
// std::cout << "theta3" << std::endl << theta2 << std::endl;
|
||||
// for (int i = 0; i < theta3.size(); i++) {
|
||||
// std::print("{} ", theta3.data()[i]);
|
||||
// }
|
||||
// std::println();
|
||||
|
||||
// reshape X and Z into 3D tensors A and B
|
||||
e::Tensor<dtype, 3> A(chivL, dL, chivC);
|
||||
e::Tensor<dtype, 3> B(chivC, dR, chivR);
|
||||
for (int ivC = 0; ivC < chivC; ivC++) {
|
||||
for (int ivL = 0; ivL < chivL; ivL++) {
|
||||
for (int idL = 0; idL < dL; idL++) {
|
||||
// Variant 1: When the Matrix is constructed with matrix(i0 * d1 + i1) = tensor(i0, i1, i2, i3);
|
||||
// dtype value = U(idL + ivL * dL, ivC);
|
||||
// std::println("A(ivL={}, idL={}, ivC={}) = U(idL={}+ivL={}*dL={}={}, ivC={}) = {}",
|
||||
// ivL, idL, ivC, idL, ivL, dL, idL+ivL*dL, ivC, value);
|
||||
|
||||
// Variant 2: When the Matrix is constructed with matrix(i1 * d0 + i0) = tensor(i0, i1, i2, i3);
|
||||
dtype value = U(ivL + idL * chivL, ivC);
|
||||
// std::println("A(ivL={}, idL={}, ivC={}) = U(ivL={}+idL={}*chivL={}={}, ivC={}) = {}",
|
||||
// ivL, idL, ivC, ivL, idL, chivL, ivL+idL*chivL, ivC, value
|
||||
// );
|
||||
A(ivL, idL, ivC) = value;
|
||||
}
|
||||
}
|
||||
for (int ivR = 0; ivR < chivR; ivR++) {
|
||||
for (int idR = 0; idR < dR; idR++) {
|
||||
// dtype value = V(ivC, ivR + idR * chivR);
|
||||
// Variant 1: When the Matrix is constructed with matrix(..., i2 * d3 + i3) = tensor(i0, i1, i2, i3);
|
||||
// dtype value = V(ivC, ivR + idR * chivR);
|
||||
// std::println("B(ivC={}, idR={}, ivR={}) = V(ivC={}, ivR={}+idR={}*chivR={}={}) = {}",
|
||||
// ivC, idR, ivR, ivC, idR, ivR, dR, ivR+idR*chivR, value);
|
||||
// Variant 2: When the Matrix is constructed with matrix(..., i3 * d2 + i2) = tensor(i0, i1, i2, i3);
|
||||
dtype value = V(ivC, idR + ivR * dR);
|
||||
// std::println("B(ivC={}, idR={}, ivR={}) = V(ivC={}, idR={}+ivR={}*dR={}={}) = {}",
|
||||
// ivC, idR, ivR, ivC, idR, ivR, dR, idR+ivR*dR, value
|
||||
// );
|
||||
B(ivC, idR, ivR) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// S: truncate, normalize, and put into a Tensor
|
||||
auto norm = S.head(chivC).norm();
|
||||
e::Tensor<dtype, 1> Sret(chivC);
|
||||
for (int ivC = 0; ivC < chivC; ivC++) {
|
||||
Sret(ivC) = S(ivC) / norm;
|
||||
// skip normalization for testing if the SVD returns the original matrix after truncation:
|
||||
// Sret(ivC) = S(ivC);
|
||||
}
|
||||
|
||||
|
||||
// Verify that A * S * B gives the original matrix back
|
||||
// std::cout << "A" << std::endl << A << std::endl;
|
||||
// std::println("B.shape = {}, {}, {}", B.dimension(0), B.dimension(1), B.dimension(2));
|
||||
// std::cout << "B" << std::endl << B << std::endl;
|
||||
// std::println("A.shape = {}, {}, {}", A.dimension(0), A.dimension(1), A.dimension(2));
|
||||
|
||||
// e::Tensor<dtype, 2> Sdiag = diagonal(Sret);
|
||||
// std::println("Sdiag.shape = {}, {}", Sdiag.dimension(0), Sdiag.dimension(1));
|
||||
// e::Tensor<dtype, 3> theta4 = A.contract(Sdiag, e::array<iP, 1>{iP(2, 0)});
|
||||
// e::Tensor<dtype, 4> theta5 = theta4.contract(B, e::array<iP, 1>{iP(2, 0)});
|
||||
|
||||
// std::cout << "theta5" << std::endl << theta5 << std::endl;
|
||||
// std::println("theta5.shape = {}, {}, {} {}", theta5.dimension(0), theta5.dimension(1), theta5.dimension(2), theta5.dimension(3));
|
||||
|
||||
return {A, Sret, B};
|
||||
}
|
||||
|
||||
|
||||
// instantiations
|
||||
template class MPS<dtype>;
|
||||
template std::tuple<e::Tensor<dtype, 3>, e::Tensor<dtype, 1>, e::Tensor<dtype, 3>>
|
||||
split_truncate_theta<dtype>(const e::Tensor<dtype, 4>&, size_t, dtype);
|
164
src/mps.hpp
Normal file
164
src/mps.hpp
Normal file
@ -0,0 +1,164 @@
|
||||
#pragma once
|
||||
#include "util.hpp"
|
||||
#include <eigen3/Eigen/Eigen>
|
||||
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace e = Eigen;
|
||||
using iP = e::IndexPair<int>;
|
||||
|
||||
template<typename T>
|
||||
e::Tensor<T, 2> diagonal(const e::Tensor<T, 1>& t) {
|
||||
e::Tensor<T, 2> out(t.dimension(0), t.dimension(0));
|
||||
out.setZero();
|
||||
for (e::Index i = 0; i < t.dimension(0); i++) {
|
||||
out(i, i) = t(i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
/**
|
||||
* @brief Matrix Product State class
|
||||
* @todo Possible Optimization: Store S as full tensor and not just the diagonal values: we always need to construct a diagonal tensor with `diagonal` function which leads to memory allocations. Shouldnt be too bad from storage perspective
|
||||
*/
|
||||
template<typename T>
|
||||
class MPS {
|
||||
public:
|
||||
using BTensor_t = e::Tensor<T, 3>;
|
||||
using STensor_t = e::Tensor<T, 1>;
|
||||
MPS() {};
|
||||
MPS(std::vector<BTensor_t>&& Bs, std::vector<STensor_t>&& Ss);
|
||||
/**
|
||||
* @brief Return single site contraction of the $S_i * B_i$ tensors
|
||||
* @returns Contraction with legs `vL i vR`
|
||||
*/
|
||||
BTensor_t getTheta1(size_t siteIdx) const;
|
||||
|
||||
/**
|
||||
* @brief Return two-site contraction of the $S_i * S_B * B_{i+1}$ tensors
|
||||
* @returns Contraction with legs `vL i i+1 vR`
|
||||
*/
|
||||
e::Tensor<T, 4> getTheta2(size_t bondIdx) const;
|
||||
|
||||
/**
|
||||
* @brief Return the dimensions of all bonds
|
||||
*/
|
||||
std::vector<unsigned> getChi() const;
|
||||
|
||||
/**
|
||||
* @brief Compute the expectation value of a single-site operator on a single site
|
||||
* @param op Single-site operator with legs i i*
|
||||
*/
|
||||
T getSiteExpectationValue(const e::Tensor<T, 2>& op, size_t siteIdx) const;
|
||||
std::vector<T> getSiteExpectationValues(const e::Tensor<T, 2>& op) const;
|
||||
T getSiteExpectationValueSum(const e::Tensor<T, 2>& op) const;
|
||||
|
||||
/**
|
||||
* @brief Compute the expectation value of a two-site operator on a single bond
|
||||
* @param op Two-site operator with legs i j i* j*
|
||||
*/
|
||||
T getBondExpectationValue(const e::Tensor<T, 4>& op, size_t bondIdx) const;
|
||||
|
||||
T getEntanglementEntropy(size_t bondIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Collapse the MPS, calculating \f[<\psi|\psi>\f]
|
||||
*/
|
||||
T collapse(size_t sizeIndex) const;
|
||||
|
||||
BTensor_t& B(size_t i) { return this->Bs.at(i); }
|
||||
STensor_t& S(size_t i) { return this->Ss.at(i); }
|
||||
const BTensor_t& B(size_t i) const { return this->Bs.at(i); }
|
||||
const STensor_t& S(size_t i) const { return this->Ss.at(i); }
|
||||
size_t getL() const { return this->L; }
|
||||
void print() const {
|
||||
for (size_t i = 0; i < this->L; i++) {
|
||||
printTensor(Ss.at(i), "S["s + std::to_string(i) + "]");
|
||||
printTensor(Bs.at(i), "B["s + std::to_string(i) + "]");
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<BTensor_t> Bs;
|
||||
std::vector<STensor_t> Ss;
|
||||
size_t L;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function to perform split and truncate on a two-site wave function
|
||||
* @param theta Two-site wave function in mixed canonical form, with legs `vL, i, j, vR`
|
||||
* @param chi_max Maximum number of singular values to keep
|
||||
* @param eps Discard any singular values smaller than that.
|
||||
*
|
||||
* @returns (A, S, B) where A is the left-canonical matrix on site i (legs `vL, i, vC`),
|
||||
* S are the singular values and
|
||||
* B is the right-canonical matrix on site i+1, with legs `vC, j, vR`
|
||||
*/
|
||||
template<typename dtype>
|
||||
std::tuple<e::Tensor<dtype, 3>, e::Tensor<dtype, 1>, e::Tensor<dtype, 3>>
|
||||
split_truncate_theta(const e::Tensor<dtype, 4>& theta, size_t chiMax, dtype eps);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize a MPS in spin-up state
|
||||
* @details
|
||||
* Return a MPS spin-up MPS with length L and bond dimension 1
|
||||
*/
|
||||
template<typename T>
|
||||
MPS<T> initMPS_spinUp(size_t L) {
|
||||
assert(L > 0);
|
||||
e::Tensor<T, 3> B(1, 2, 1);
|
||||
B.setZero();
|
||||
B(0, 0, 0) = 1;
|
||||
std::vector<e::Tensor<T, 3>> Bs(L, B);
|
||||
e::Tensor<T, 1> S(1);
|
||||
S(0) = 1;
|
||||
std::vector<e::Tensor<T, 1>> Ss(L, S);
|
||||
return MPS<T>(std::move(Bs), std::move(Ss));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize a MPS in spin-right state
|
||||
* @details
|
||||
* Return a MPS spin-right MPS with length L and bond dimension 1
|
||||
*/
|
||||
template<typename T>
|
||||
MPS<T> initMPS_spinRight(size_t L) {
|
||||
assert(L > 0);
|
||||
e::Tensor<T, 3> B(1, 2, 1);
|
||||
B.setZero();
|
||||
T value = std::sqrt(0.5);
|
||||
B(0, 0, 0) = value;
|
||||
B(0, 1, 0) = value;
|
||||
std::vector<e::Tensor<T, 3>> Bs(L, B);
|
||||
e::Tensor<T, 1> S(1);
|
||||
S(0) = 1;
|
||||
std::vector<e::Tensor<T, 1>> Ss(L, S);
|
||||
return MPS<T>(std::move(Bs), std::move(Ss));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize a MPS with particle number states
|
||||
* @details
|
||||
* Return a MPS of dimension `nMax+1`, where each site is occupied by `nParticles`.
|
||||
*/
|
||||
template<typename T>
|
||||
MPS<T> initMPS_nParticles(size_t L, size_t nMax, size_t nParticles) {
|
||||
assert(L > 0);
|
||||
assert(nParticles <= nMax);
|
||||
e::Tensor<T, 3> B(1, nMax+1, 1);
|
||||
B.setZero();
|
||||
B(0, nParticles, 0) = 1;
|
||||
std::vector<e::Tensor<T, 3>> Bs(L, B);
|
||||
e::Tensor<T, 1> S(1);
|
||||
S(0) = 1;
|
||||
std::vector<e::Tensor<T, 1>> Ss(L, S);
|
||||
return MPS<T>(std::move(Bs), std::move(Ss));
|
||||
}
|
562
src/output
Normal file
562
src/output
Normal file
@ -0,0 +1,562 @@
|
||||
[1;34mBuilding:[0m main.cpp -> ../build/main.o
|
||||
In file included from main.cpp:3:
|
||||
mps.hpp: In instantiation of 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]':
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
mps.hpp:140:83: error: no match for 'operator>' (operand types are 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' and 'std::complex<float>')
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/bits/stl_algobase.h:64,
|
||||
from /usr/include/c++/14.2.1/vector:62,
|
||||
from ./pch.hpp:1,
|
||||
from <command-line>:
|
||||
/usr/include/c++/14.2.1/bits/stl_pair.h:1023:5: note: candidate: 'template<class _T1, class _T2, class _U1, class _U2> constexpr std::common_comparison_category_t<decltype (std::__detail::__synth3way(declval<_T1&>(), declval<_U1&>())), decltype (std::__detail::__synth3way(declval<_T2&>(), declval<_U2&>()))> std::operator<=>(const pair<_T1, _T2>&, const pair<_U1, _U2>&)' (reversed)
|
||||
1023 | operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_pair.h:1023:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::pair<_T1, _T2>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/bits/stl_algobase.h:67:
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:576:5: note: candidate: 'template<class _IteratorL, class _IteratorR> requires three_way_comparable_with<_IteratorR, _IteratorL, std::partial_ordering> constexpr std::compare_three_way_result_t<_IteratorL, _IteratorR> std::operator<=>(const reverse_iterator<_IteratorL>&, const reverse_iterator<_IteratorR>&)' (reversed)
|
||||
576 | operator<=>(const reverse_iterator<_IteratorL>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:576:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::reverse_iterator<_IteratorL>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:1679:5: note: candidate: 'template<class _IteratorL, class _IteratorR> requires three_way_comparable_with<_IteratorR, _IteratorL, std::partial_ordering> constexpr std::compare_three_way_result_t<_IteratorL, _IteratorR> std::operator<=>(const move_iterator<_IteratorL>&, const move_iterator<_IteratorR>&)' (reversed)
|
||||
1679 | operator<=>(const move_iterator<_IteratorL>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:1679:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::move_iterator<_IteratorL>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/bits/uses_allocator_args.h:39,
|
||||
from /usr/include/c++/14.2.1/bits/memory_resource.h:41,
|
||||
from /usr/include/c++/14.2.1/vector:87:
|
||||
/usr/include/c++/14.2.1/tuple:2589:5: note: candidate: 'template<class ... _Tps, class ... _Ups> constexpr std::common_comparison_category_t<decltype (std::__detail::__synth3way(declval<_Tps&>(), declval<_Ups&>()))...> std::operator<=>(const tuple<_Ts ...>&, const tuple<_Elements ...>&)' (reversed)
|
||||
2589 | operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/tuple:2589:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::tuple<_Ts ...>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/bits/basic_string.h:47,
|
||||
from /usr/include/c++/14.2.1/string:54,
|
||||
from /usr/include/c++/14.2.1/bits/locale_classes.h:40,
|
||||
from /usr/include/c++/14.2.1/locale:41,
|
||||
from /usr/include/c++/14.2.1/format:47,
|
||||
from /usr/include/c++/14.2.1/print:41,
|
||||
from ./pch.hpp:2:
|
||||
/usr/include/c++/14.2.1/string_view:617:5: note: candidate: 'template<class _CharT, class _Traits> constexpr decltype (__char_traits_cmp_cat<_Traits>(0)) std::operator<=>(basic_string_view<_CharT, _Traits>, __type_identity_t<basic_string_view<_CharT, _Traits> >)' (reversed)
|
||||
617 | operator<=>(basic_string_view<_CharT, _Traits> __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/string_view:617:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'std::basic_string_view<_CharT, _Traits>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/basic_string.h:3805:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> constexpr decltype (__char_traits_cmp_cat<_Traits>(0)) std::operator<=>(const __cxx11::basic_string<_CharT, _Traits, _Allocator>&, const _CharT*)' (reversed)
|
||||
3805 | operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/basic_string.h:3805:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/format:48:
|
||||
/usr/include/c++/14.2.1/optional:1283:5: note: candidate: 'template<class _Tp, class _Up> requires three_way_comparable_with<_Up, _Tp, std::partial_ordering> constexpr std::compare_three_way_result_t<_IteratorL, _IteratorR> std::operator<=>(const optional<_Tp>&, const optional<_Up>&)' (reversed)
|
||||
1283 | operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1283:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::optional<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1298:5: note: candidate: 'template<class _Tp> constexpr std::strong_ordering std::operator<=>(const optional<_Tp>&, nullopt_t)' (reversed)
|
||||
1298 | operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1298:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::optional<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1435:5: note: candidate: 'template<class _Tp, class _Up> requires !(__is_optional_v<_Up>) && (three_way_comparable_with<_Up, _Tp, std::partial_ordering>) constexpr std::compare_three_way_result_t<_IteratorL, _IteratorR> std::operator<=>(const optional<_Tp>&, const _Up&)' (reversed)
|
||||
1435 | operator<=>(const optional<_Tp>& __x, const _Up& __v)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1435:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::optional<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/bits/shared_ptr_base.h:59,
|
||||
from /usr/include/c++/14.2.1/bits/shared_ptr.h:53,
|
||||
from /usr/include/c++/14.2.1/chrono:49,
|
||||
from /usr/include/eigen3/unsupported/Eigen/CXX11/Tensor:38,
|
||||
from ./pch.hpp:4:
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:996:5: note: candidate: 'template<class _Tp, class _Dp, class _Up, class _Ep> requires three_way_comparable_with<typename std::unique_ptr<_Tp, _Dp>::pointer, typename std::unique_ptr<_Up, _Ep>::pointer, std::partial_ordering> constexpr std::compare_three_way_result_t<typename std::unique_ptr<_Tp, _Dp>::pointer, typename std::unique_ptr<_Up, _Ep>::pointer> std::operator<=>(const unique_ptr<_Tp, _Dp>&, const unique_ptr<_Up, _Ep>&)' (reversed)
|
||||
996 | operator<=>(const unique_ptr<_Tp, _Dp>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:996:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::unique_ptr<_Tp, _Dp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:1005:5: note: candidate: 'template<class _Tp, class _Dp> requires three_way_comparable<typename std::unique_ptr<_Tp, _Dp>::pointer, std::partial_ordering> constexpr std::compare_three_way_result_t<typename std::unique_ptr<_Tp, _Dp>::pointer> std::operator<=>(const unique_ptr<_Tp, _Dp>&, nullptr_t)' (reversed)
|
||||
1005 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:1005:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::unique_ptr<_Tp, _Dp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr_base.h:1809:5: note: candidate: 'template<class _Tp, class _Up, __gnu_cxx::_Lock_policy _Lp> std::strong_ordering std::operator<=>(const __shared_ptr<_Tp1, _Lp>&, const __shared_ptr<_Tp2, _Lp>&)' (reversed)
|
||||
1809 | operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr_base.h:1809:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::__shared_ptr<_Tp1, _Lp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr_base.h:1815:5: note: candidate: 'template<class _Tp, __gnu_cxx::_Lock_policy _Lp> std::strong_ordering std::operator<=>(const __shared_ptr<_Tp, _Lp>&, nullptr_t)' (reversed)
|
||||
1815 | operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr_base.h:1815:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::__shared_ptr<_Tp, _Lp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr.h:566:5: note: candidate: 'template<class _Tp, class _Up> std::strong_ordering std::operator<=>(const shared_ptr<_Tp>&, const shared_ptr<_Tp>&)' (reversed)
|
||||
566 | operator<=>(const shared_ptr<_Tp>& __a,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr.h:566:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::shared_ptr<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr.h:572:5: note: candidate: 'template<class _Tp> std::strong_ordering std::operator<=>(const shared_ptr<_Tp>&, nullptr_t)' (reversed)
|
||||
572 | operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/shared_ptr.h:572:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::shared_ptr<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:594:5: note: candidate: 'template<class _Iterator> requires three_way_comparable<_Iterator, std::partial_ordering> constexpr std::compare_three_way_result_t<_Iterator, _Iterator> std::operator<=>(const reverse_iterator<_IteratorL>&, const reverse_iterator<_IteratorL>&)' (rewritten)
|
||||
594 | operator<=>(const reverse_iterator<_Iterator>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:594:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::reverse_iterator<_IteratorL>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:1745:5: note: candidate: 'template<class _Iterator> requires three_way_comparable<_Iterator, std::partial_ordering> constexpr std::compare_three_way_result_t<_Iterator, _Iterator> std::operator<=>(const move_iterator<_IteratorL>&, const move_iterator<_IteratorL>&)' (rewritten)
|
||||
1745 | operator<=>(const move_iterator<_Iterator>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:1745:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::move_iterator<_IteratorL>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/vector:66:
|
||||
/usr/include/c++/14.2.1/bits/stl_vector.h:2069:5: note: candidate: 'template<class _Tp, class _Alloc> constexpr std::__detail::__synth3way_t<_Iterator> std::operator<=>(const vector<_Tp, _Alloc>&, const vector<_Tp, _Alloc>&)' (rewritten)
|
||||
2069 | operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_vector.h:2069:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::vector<_Tp, _Alloc>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/format:43:
|
||||
/usr/include/c++/14.2.1/array:310:5: note: candidate: 'template<class _Tp, long unsigned int _Nm> constexpr std::__detail::__synth3way_t<_Iterator> std::operator<=>(const array<_Tp, _Nm>&, const array<_Tp, _Nm>&)' (rewritten)
|
||||
310 | operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/array:310:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::array<_Tp, _Nm>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/basic_string.h:3790:5: note: candidate: 'template<class _CharT, class _Traits, class _Alloc> constexpr decltype (__char_traits_cmp_cat<_Traits>(0)) std::operator<=>(const __cxx11::basic_string<_CharT, _Traits, _Allocator>&, const __cxx11::basic_string<_CharT, _Traits, _Allocator>&)' (rewritten)
|
||||
3790 | operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/basic_string.h:3790:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/format:52:
|
||||
/usr/include/c++/14.2.1/variant:1280:5: note: candidate: 'template<class ... _Types> requires (three_way_comparable<_Types, std::partial_ordering> && ...) constexpr std::common_comparison_category_t<typename std::__detail::__cmp3way_res_impl<_Types, _Types>::type ...> std::operator<=>(const variant<_Types ...>&, const variant<_Types ...>&)' (rewritten)
|
||||
1280 | operator<=>(const variant<_Types...>& __v, const variant<_Types...>& __w)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/variant:1280:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::variant<_Types ...>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/map:63,
|
||||
from /usr/include/eigen3/Eigen/SparseCore:16,
|
||||
from /usr/include/eigen3/Eigen/Sparse:26,
|
||||
from /usr/include/eigen3/Eigen/Eigen:2,
|
||||
from ./pch.hpp:5:
|
||||
/usr/include/c++/14.2.1/bits/stl_map.h:1533:5: note: candidate: 'template<class _Key, class _Tp, class _Compare, class _Alloc> std::__detail::__synth3way_t<std::pair<const _Key, _Val> > std::operator<=>(const map<_Key, _Tp, _Compare, _Allocator>&, const map<_Key, _Tp, _Compare, _Allocator>&)' (rewritten)
|
||||
1533 | operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_map.h:1533:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::map<_Key, _Tp, _Compare, _Allocator>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/map:64:
|
||||
/usr/include/c++/14.2.1/bits/stl_multimap.h:1155:5: note: candidate: 'template<class _Key, class _Tp, class _Compare, class _Alloc> std::__detail::__synth3way_t<std::pair<const _Key, _Val> > std::operator<=>(const multimap<_Key, _Tp, _Compare, _Allocator>&, const multimap<_Key, _Tp, _Compare, _Allocator>&)' (rewritten)
|
||||
1155 | operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_multimap.h:1155:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::multimap<_Key, _Tp, _Compare, _Allocator>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/list:65,
|
||||
from /usr/include/eigen3/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h:15,
|
||||
from /usr/include/eigen3/Eigen/IterativeLinearSolvers:47,
|
||||
from /usr/include/eigen3/Eigen/Sparse:31:
|
||||
/usr/include/c++/14.2.1/bits/stl_list.h:2158:5: note: candidate: 'template<class _Tp, class _Alloc> std::__detail::__synth3way_t<_Iterator> std::operator<=>(const __cxx11::list<_Tp, _Alloc>&, const __cxx11::list<_Tp, _Alloc>&)' (rewritten)
|
||||
2158 | operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_list.h:2158:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::__cxx11::list<_Tp, _Alloc>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
In file included from /usr/include/c++/14.2.1/bits/ios_base.h:46,
|
||||
from /usr/include/c++/14.2.1/bits/locale_facets.h:43,
|
||||
from /usr/include/c++/14.2.1/locale:42:
|
||||
/usr/include/c++/14.2.1/system_error:316:3: note: candidate: 'std::strong_ordering std::operator<=>(const error_code&, const error_code&)' (rewritten)
|
||||
316 | operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/system_error:316:33: note: no known conversion for argument 1 from 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' to 'const std::error_code&'
|
||||
316 | operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
|
||||
| ~~~~~~~~~~~~~~~~~~^~~~~
|
||||
/usr/include/c++/14.2.1/system_error:498:3: note: candidate: 'std::strong_ordering std::operator<=>(const error_condition&, const error_condition&)' (rewritten)
|
||||
498 | operator<=>(const error_condition& __lhs,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/system_error:498:38: note: no known conversion for argument 1 from 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' to 'const std::error_condition&'
|
||||
498 | operator<=>(const error_condition& __lhs,
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~
|
||||
/usr/include/c++/14.2.1/variant:1303:3: note: candidate: 'constexpr std::strong_ordering std::operator<=>(monostate, monostate)' (rewritten)
|
||||
1303 | operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; }
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/variant:1303:15: note: no known conversion for argument 1 from 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' to 'std::monostate'
|
||||
1303 | operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; }
|
||||
| ^~~~~~~~~
|
||||
In file included from /usr/include/eigen3/unsupported/Eigen/CXX11/Tensor:45:
|
||||
/usr/include/c++/14.2.1/thread:75:3: note: candidate: 'std::strong_ordering std::operator<=>(thread::id, thread::id)' (rewritten)
|
||||
75 | operator<=>(thread::id __x, thread::id __y) noexcept
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/thread:75:26: note: no known conversion for argument 1 from 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' to 'std::thread::id'
|
||||
75 | operator<=>(thread::id __x, thread::id __y) noexcept
|
||||
| ~~~~~~~~~~~^~~
|
||||
In file included from /usr/include/eigen3/Eigen/src/Core/ArrayBase.h:99,
|
||||
from /usr/include/eigen3/Eigen/Core:309,
|
||||
from /usr/include/eigen3/unsupported/Eigen/CXX11/Tensor:14:
|
||||
/usr/include/eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.inc:204:1: note: candidate: 'template<class OtherDerived> const Eigen::CwiseBinaryOp<Eigen::internal::scalar_cmp_op<typename OtherDerived::Scalar, typename Eigen::internal::traits<T>::Scalar, Eigen::internal::cmp_LT>, const OtherDerived, const Derived> Eigen::ArrayBase<Derived>::operator>(const Eigen::ArrayBase<OtherDerived>&) const [with Derived = Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >]'
|
||||
204 | EIGEN_MAKE_CWISE_COMP_R_OP(operator>, operator<, LT)
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.inc:204:1: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const Eigen::ArrayBase<Derived>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.inc:204:1: note: candidate: 'const Eigen::ArrayBase<Derived>::RCmpLTReturnType Eigen::ArrayBase<Derived>::operator>(const Scalar&) const [with Derived = Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >; RCmpLTReturnType = Eigen::CwiseBinaryOp<Eigen::internal::scalar_cmp_op<double, double, Eigen::internal::cmp_LT, false>, const Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Array<double, -1, 1> >, const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> > >; Scalar = double]'
|
||||
204 | EIGEN_MAKE_CWISE_COMP_R_OP(operator>, operator<, LT)
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.inc:204:1: note: no known conversion for argument 1 from 'std::complex<float>' to 'const Eigen::ArrayBase<Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> > >::Scalar&' {aka 'const double&'}
|
||||
204 | EIGEN_MAKE_CWISE_COMP_R_OP(operator>, operator<, LT)
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:551:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator>(const reverse_iterator<_IteratorL>&, const reverse_iterator<_IteratorR>&) requires requires{{std::operator>::__x->base() < std::operator>::__y->base()} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];}'
|
||||
551 | operator>(const reverse_iterator<_IteratorL>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:551:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::reverse_iterator<_IteratorL>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:1714:5: note: candidate: 'template<class _IteratorL, class _IteratorR> constexpr bool std::operator>(const move_iterator<_IteratorL>&, const move_iterator<_IteratorR>&) requires requires{{std::operator>::__y->base() < std::operator>::__x->base()} -> decltype(auto) [requires std::convertible_to<<placeholder>, bool>];}'
|
||||
1714 | operator>(const move_iterator<_IteratorL>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/stl_iterator.h:1714:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::move_iterator<_IteratorL>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1258:5: note: candidate: 'template<class _Tp, class _Up> constexpr std::__optional_gt_t<_Tp, _Up> std::operator>(const optional<_Tp>&, const optional<_Up>&)'
|
||||
1258 | operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1258:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::optional<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1396:5: note: candidate: 'template<class _Tp, class _Up> constexpr std::__optional_gt_t<_Tp, _Up> std::operator>(const optional<_Tp>&, const _Up&)'
|
||||
1396 | operator>(const optional<_Tp>& __lhs, const _Up& __rhs)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1396:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::optional<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1402:5: note: candidate: 'template<class _Tp, class _Up> constexpr std::__optional_gt_t<_Up, _Tp> std::operator>(const _Up&, const optional<_Tp>&)'
|
||||
1402 | operator>(const _Up& __lhs, const optional<_Tp>& __rhs)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/optional:1402:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::optional<_Tp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/variant:1269:3: note: candidate: 'template<class ... _Types> constexpr bool std::operator>(const variant<_Types ...>&, const variant<_Types ...>&)'
|
||||
1269 | _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater)
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/c++/14.2.1/variant:1269:3: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::variant<_Types ...>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:942:5: note: candidate: 'template<class _Tp, class _Dp, class _Up, class _Ep> constexpr bool std::operator>(const unique_ptr<_Tp, _Dp>&, const unique_ptr<_Up, _Ep>&)'
|
||||
942 | operator>(const unique_ptr<_Tp, _Dp>& __x,
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:942:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::unique_ptr<_Tp, _Dp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:950:5: note: candidate: 'template<class _Tp, class _Dp> constexpr bool std::operator>(const unique_ptr<_Tp, _Dp>&, nullptr_t)'
|
||||
950 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:950:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' is not derived from 'const std::unique_ptr<_Tp, _Dp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:960:5: note: candidate: 'template<class _Tp, class _Dp> constexpr bool std::operator>(nullptr_t, const unique_ptr<_Tp, _Dp>&)'
|
||||
960 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
| ^~~~~~~~
|
||||
/usr/include/c++/14.2.1/bits/unique_ptr.h:960:5: note: template argument deduction/substitution failed:
|
||||
mps.hpp:140:83: note: 'std::complex<float>' is not derived from 'const std::unique_ptr<_Tp, _Dp>'
|
||||
140 | int chivC = static_cast<int>(std::min(chi_max, static_cast<size_t>((S.array() > eps).count())));
|
||||
| ~~~~~~~~~~~^~~~~~
|
||||
/usr/include/eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.inc:204:1: note: candidate: 'const Eigen::ArrayBase<Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> > >::CmpLTReturnType Eigen::operator>(const ArrayBase<ArrayWrapper<const Matrix<double, -1, 1> > >::Scalar&, const ArrayWrapper<const Matrix<double, -1, 1> >&)'
|
||||
204 | EIGEN_MAKE_CWISE_COMP_R_OP(operator>, operator<, LT)
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.inc:204:1: note: no known conversion for argument 1 from 'const Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> >' to 'const Eigen::ArrayBase<Eigen::ArrayWrapper<const Eigen::Matrix<double, -1, 1> > >::Scalar&' {aka 'const double&'}
|
||||
204 | EIGEN_MAKE_CWISE_COMP_R_OP(operator>, operator<, LT)
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
In file included from /usr/include/eigen3/Eigen/Core:300:
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h: In instantiation of 'struct Eigen::internal::traits<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >':
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:248:7: required from 'class Eigen::internal::dense_product_base<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1, 8>'
|
||||
248 | class dense_product_base : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {};
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:276:7: required from 'class Eigen::ProductImpl<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1, Eigen::Dense>'
|
||||
276 | class ProductImpl<Lhs, Rhs, Option, Dense> : public internal::dense_product_base<Lhs, Rhs, Option> {
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:198:7: required from 'class Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>'
|
||||
198 | class Product
|
||||
| ^~~~~~~
|
||||
mps.hpp:159:21: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
159 | MatX theta2 = U * S.asDiagonal() * V;
|
||||
| ~~^~~~~~~~~~~~~~~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:33:90: error: no type named 'ReturnType' in 'struct Eigen::ScalarBinaryOpTraits<std::complex<float>, double, Eigen::internal::scalar_product_op<std::complex<float>, double> >'
|
||||
33 | typename traits<RhsCleaned>::Scalar>::ReturnType Scalar;
|
||||
| ^~~~~~
|
||||
In file included from /usr/include/eigen3/Eigen/Core:296:
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h: In instantiation of 'class Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >':
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:52:7: required from 'class Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >'
|
||||
52 | class MatrixBase : public DenseBase<Derived> {
|
||||
| ^~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:248:7: required from 'class Eigen::internal::dense_product_base<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1, 8>'
|
||||
248 | class dense_product_base : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {};
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:276:7: required from 'class Eigen::ProductImpl<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1, Eigen::Dense>'
|
||||
276 | class ProductImpl<Lhs, Rhs, Option, Dense> : public internal::dense_product_base<Lhs, Rhs, Option> {
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:198:7: required from 'class Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>'
|
||||
198 | class Product
|
||||
| ^~~~~~~
|
||||
mps.hpp:159:21: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
159 | MatX theta2 = U * S.asDiagonal() * V;
|
||||
| ~~^~~~~~~~~~~~~~~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:72:15: error: 'coeff' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
72 | using Base::coeff;
|
||||
| ^~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:73:15: error: 'coeffByOuterInner' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
73 | using Base::coeffByOuterInner;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:81:24: error: 'operator()' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
81 | using Base::operator();
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:82:24: error: 'operator[]' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
82 | using Base::operator[];
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:88:15: error: 'w' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
88 | using Base::w;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:89:15: error: 'x' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
89 | using Base::x;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:90:15: error: 'y' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
90 | using Base::y;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:91:15: error: 'z' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
91 | using Base::z;
|
||||
| ^
|
||||
In file included from /usr/include/eigen3/Eigen/Core:297:
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h: In instantiation of 'class Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >':
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:248:7: required from 'class Eigen::internal::dense_product_base<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1, 8>'
|
||||
248 | class dense_product_base : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {};
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:276:7: required from 'class Eigen::ProductImpl<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1, Eigen::Dense>'
|
||||
276 | class ProductImpl<Lhs, Rhs, Option, Dense> : public internal::dense_product_base<Lhs, Rhs, Option> {
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:198:7: required from 'class Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>'
|
||||
198 | class Product
|
||||
| ^~~~~~~
|
||||
mps.hpp:159:21: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
159 | MatX theta2 = U * S.asDiagonal() * V;
|
||||
| ~~^~~~~~~~~~~~~~~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:72:15: error: 'coeff' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
72 | using Base::coeff;
|
||||
| ^~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:77:15: error: 'eval' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
77 | using Base::eval;
|
||||
| ^~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:81:23: error: 'operator-' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
81 | using Base::operator-;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:84:23: error: 'operator*=' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
84 | using Base::operator*=;
|
||||
| ^~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:85:23: error: 'operator/=' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1> >::Base'
|
||||
85 | using Base::operator/=;
|
||||
| ^~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h: In instantiation of 'class Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >':
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:52:7: required from 'class Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >'
|
||||
52 | class MatrixBase : public DenseBase<Derived> {
|
||||
| ^~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:248:7: required from 'class Eigen::internal::dense_product_base<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0, 8>'
|
||||
248 | class dense_product_base : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {};
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:276:7: required from 'class Eigen::ProductImpl<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0, Eigen::Dense>'
|
||||
276 | class ProductImpl<Lhs, Rhs, Option, Dense> : public internal::dense_product_base<Lhs, Rhs, Option> {
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:198:7: required from 'class Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0>'
|
||||
198 | class Product
|
||||
| ^~~~~~~
|
||||
mps.hpp:159:38: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
159 | MatX theta2 = U * S.asDiagonal() * V;
|
||||
| ~~~~~~~~~~~~~~~~~~~^~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:72:15: error: 'coeff' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
72 | using Base::coeff;
|
||||
| ^~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:73:15: error: 'coeffByOuterInner' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
73 | using Base::coeffByOuterInner;
|
||||
| ^~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:81:24: error: 'operator()' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
81 | using Base::operator();
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:82:24: error: 'operator[]' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
82 | using Base::operator[];
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:88:15: error: 'w' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
88 | using Base::w;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:89:15: error: 'x' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
89 | using Base::x;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:90:15: error: 'y' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
90 | using Base::y;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/DenseBase.h:91:15: error: 'z' has not been declared in 'Eigen::DenseBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
91 | using Base::z;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h: In instantiation of 'class Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >':
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:248:7: required from 'class Eigen::internal::dense_product_base<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0, 8>'
|
||||
248 | class dense_product_base : public internal::dense_xpr_base<Product<Lhs, Rhs, Option>>::type {};
|
||||
| ^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:276:7: required from 'class Eigen::ProductImpl<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0, Eigen::Dense>'
|
||||
276 | class ProductImpl<Lhs, Rhs, Option, Dense> : public internal::dense_product_base<Lhs, Rhs, Option> {
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Product.h:198:7: required from 'class Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0>'
|
||||
198 | class Product
|
||||
| ^~~~~~~
|
||||
mps.hpp:159:38: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
159 | MatX theta2 = U * S.asDiagonal() * V;
|
||||
| ~~~~~~~~~~~~~~~~~~~^~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:72:15: error: 'coeff' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
72 | using Base::coeff;
|
||||
| ^~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:77:15: error: 'eval' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
77 | using Base::eval;
|
||||
| ^~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:81:23: error: 'operator-' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
81 | using Base::operator-;
|
||||
| ^
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:84:23: error: 'operator*=' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
84 | using Base::operator*=;
|
||||
| ^~
|
||||
/usr/include/eigen3/Eigen/src/Core/MatrixBase.h:85:23: error: 'operator/=' has not been declared in 'Eigen::MatrixBase<Eigen::Product<Eigen::Product<Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, Eigen::DiagonalWrapper<const Eigen::Matrix<double, -1, 1> >, 1>, Eigen::Matrix<std::complex<float>, -1, -1, 1, -1, -1>, 0> >::Base'
|
||||
85 | using Base::operator/=;
|
||||
| ^~
|
||||
/usr/include/c++/14.2.1/format: In instantiation of 'class std::__format::_Checking_scanner<char, std::complex<float> >':
|
||||
/usr/include/c++/14.2.1/format:4210:4: required from 'consteval std::basic_format_string<_CharT, _Args>::basic_format_string(const _Tp&) [with _Tp = char [4]; _CharT = char; _Args = {std::complex<float>&}]'
|
||||
4210 | __scanner(_M_str);
|
||||
| ^~~~~~~~~
|
||||
mps.hpp:162:19: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
162 | std::print("{} ", theta2.data()[i]);
|
||||
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/c++/14.2.1/format:4065:10: error: static assertion failed: std::formatter must be specialized for each type being formatted
|
||||
4065 | (is_default_constructible_v<formatter<_Args, _CharT>> && ...),
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/c++/14.2.1/format:4065:10: note: 'std::is_default_constructible_v<std::formatter<std::complex<float>, char> >' evaluates to false
|
||||
/usr/include/c++/14.2.1/format: In instantiation of 'constexpr void std::__format::_Checking_scanner<_CharT, _Args>::_M_parse_format_spec(std::size_t) [with _Tp = std::complex<float>; _OtherArgs = {}; _CharT = char; _Args = {std::complex<float>}; std::size_t = long unsigned int]':
|
||||
/usr/include/c++/14.2.1/format:4082:33: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
4082 | _M_parse_format_spec<_Args...>(__id);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
mps.hpp:162:19: in 'constexpr' expansion of 'std::basic_format_string<char, std::complex<float>&>("{} ")'
|
||||
/usr/include/c++/14.2.1/format:4211:19: in 'constexpr' expansion of '__scanner.std::__format::_Checking_scanner<char, std::complex<float> >::std::__format::_Scanner<char>.std::__format::_Scanner<char>::_M_scan()'
|
||||
/usr/include/c++/14.2.1/format:3952:30: in 'constexpr' expansion of '((std::__format::_Scanner<char>*)this)->std::__format::_Scanner<char>::_M_on_replacement_field()'
|
||||
/usr/include/c++/14.2.1/format:4004:15: in 'constexpr' expansion of '((std::__format::_Scanner<char>*)this)->std::__format::_Scanner<char>::_M_format_arg(__id)'
|
||||
/usr/include/c++/14.2.1/format:4095:38: error: use of deleted function 'std::formatter<_Tp, _CharT>::formatter() [with _Tp = std::complex<float>; _CharT = char]'
|
||||
4095 | formatter<_Tp, _CharT> __f;
|
||||
| ^~~
|
||||
/usr/include/c++/14.2.1/format:178:7: note: declared here
|
||||
178 | formatter() = delete; // No std::formatter specialization for this type.
|
||||
| ^~~~~~~~~
|
||||
/usr/include/c++/14.2.1/format:4095:38: note: use '-fdiagnostics-all-candidates' to display considered candidates
|
||||
4095 | formatter<_Tp, _CharT> __f;
|
||||
| ^~~
|
||||
/usr/include/c++/14.2.1/format:4096:42: error: 'class std::formatter<std::complex<float>, char>' has no member named 'parse'
|
||||
4096 | this->_M_pc.advance_to(__f.parse(this->_M_pc));
|
||||
| ~~~~^~~~~
|
||||
mps.hpp: In instantiation of 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]':
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
mps.hpp:162:19: error: call to consteval function 'std::basic_format_string<char, std::complex<float>&>("{} ")' is not a constant expression
|
||||
162 | std::print("{} ", theta2.data()[i]);
|
||||
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
In file included from /usr/include/eigen3/Eigen/Core:175:
|
||||
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h: In instantiation of 'constexpr void Eigen::internal::call_assignment_no_alias(Dst&, const Src&, const Func&) [with Dst = Eigen::Matrix<double, -1, 1>; Src = Eigen::Matrix<float, -1, 1>; Func = assign_op<double, float>]':
|
||||
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:770:39: required from 'constexpr Derived& Eigen::PlainObjectBase<Derived>::_set_noalias(const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::Matrix<float, -1, 1>; Derived = Eigen::Matrix<double, -1, 1>]'
|
||||
770 | internal::call_assignment_no_alias(this->derived(), other.derived(),
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
771 | internal::assign_op<Scalar, typename OtherDerived::Scalar>());
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:565:17: required from 'Eigen::PlainObjectBase<Derived>::PlainObjectBase(const Eigen::DenseBase<OtherDerived>&) [with OtherDerived = Eigen::Matrix<float, -1, 1>; Derived = Eigen::Matrix<double, -1, 1>]'
|
||||
565 | _set_noalias(other);
|
||||
| ~~~~~~~~~~~~^~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/Matrix.h:386:108: required from 'Eigen::Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_>::Matrix(const Eigen::EigenBase<OtherDerived>&) [with OtherDerived = Eigen::Matrix<float, -1, 1>; Scalar_ = double; int Rows_ = -1; int Cols_ = 1; int Options_ = 0; int MaxRows_ = -1; int MaxCols_ = 1]'
|
||||
386 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived>& other) : Base(other.derived()) {}
|
||||
| ^
|
||||
mps.hpp:136:24: required from 'std::tuple<Eigen::Tensor<dtype, 3, Storage, long int>, Eigen::Tensor<dtype, 1, Storage, long int>, Eigen::Tensor<dtype, 3, Storage, long int> > split_truncate_theta(const Eigen::Tensor<dtype, 4, Storage>&, size_t, dtype) [with dtype = std::complex<float>; unsigned int Storage = 1; size_t = long unsigned int]'
|
||||
136 | const e::VectorXd& S = svd.singularValues();
|
||||
| ^
|
||||
main.cpp:37:62: required from here
|
||||
37 | auto [A, S, B] = split_truncate_theta<dtype, e::RowMajor>(t4, chi_max, eps);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:839:3: error: static assertion failed: YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY
|
||||
839 | EIGEN_CHECK_BINARY_COMPATIBILIY(Func, typename ActualDstTypeCleaned::Scalar, typename Src::Scalar);
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:839:3: note: 'Eigen::internal::has_ReturnType<Eigen::ScalarBinaryOpTraits<double, float, Eigen::internal::assign_op<double, float> > >::value' evaluates to false
|
||||
make: *** [Makefile:47: ../build/main.o] Error 1
|
18
src/pch.hpp
Normal file
18
src/pch.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <print>
|
||||
#include <algorithm>
|
||||
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
|
||||
#include <eigen3/Eigen/Eigen>
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
#include <ranges>
|
||||
|
||||
// using dtype = std::complex<float>;
|
||||
// namespace e = Eigen;
|
||||
// template class e::Matrix<dtype, 2, 2>;
|
||||
// template class e::Matrix<dtype, 4, 4>;
|
||||
// template class e::Tensor<dtype, 1>;
|
||||
// template class e::Tensor<dtype, 2>;
|
||||
// template class e::Tensor<dtype, 3>;
|
||||
// template class e::Tensor<dtype, 4>;
|
BIN
src/pch.hpp.gch
Normal file
BIN
src/pch.hpp.gch
Normal file
Binary file not shown.
270
src/process_benchmarks.py
Normal file
270
src/process_benchmarks.py
Normal file
@ -0,0 +1,270 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from sys import argv
|
||||
import os
|
||||
import re
|
||||
from scipy.optimize import curve_fit
|
||||
import matplotlib as mpl
|
||||
|
||||
import mpl_colors
|
||||
|
||||
|
||||
def get_name(L, n_steps, eps, chi_max):
|
||||
return f"L={L:02}_nSteps={n_steps:04}_eps={eps:e}_chiMax={chi_max:02}"
|
||||
|
||||
def power2_(x, a, b):
|
||||
return a * 2**x + b
|
||||
|
||||
def power2(x, a, b, c):
|
||||
return a * 2**(x*b) + c
|
||||
|
||||
def powerX(x, a, b, c, d):
|
||||
return a * b**(x*c) + d
|
||||
|
||||
def power2squared(x, a, b, c):
|
||||
return a * 2**(x**2 *b) + c
|
||||
|
||||
def exp(x, a, b):
|
||||
return a * np.exp(b * x)
|
||||
|
||||
def total4D(x, a, b, c, d, e):
|
||||
L, n, eps, chi = np.split(x, 4, axis=1)
|
||||
return (a * n * e**(L*d) * (1 + b * eps) * 2**chi + c).flatten()
|
||||
# fit_and_plot(Ldata, 0, powerX, axL)
|
||||
# fit_and_plot(Ndata, 1, lambda x, a, b: a * x + b, axN)
|
||||
# fit_and_plot(Epsdata, 2, lambda x, a: x * 0 + a, axEps)
|
||||
# fit_and_plot(Chidata, 3, power2, axChi)
|
||||
|
||||
|
||||
def fit(f, x, y):
|
||||
popt, pcov = curve_fit(f, x, y)
|
||||
yfit = f(x, *popt)
|
||||
return yfit, popt, pcov
|
||||
|
||||
platform_colors = {
|
||||
"firefox": "o",
|
||||
"chromium": "b",
|
||||
"native": "g",
|
||||
}
|
||||
|
||||
|
||||
def process_benchmarks_1AT(benchmarks):
|
||||
L_default = 12
|
||||
n_steps_default = 200
|
||||
eps_default = 1e-10
|
||||
chi_max_default = 20
|
||||
|
||||
get_benchmarks_lambdas = [
|
||||
lambda a: a[(a[:,1] == n_steps_default) & (a[:,2] == eps_default) & (a[:,3] == chi_max_default)],
|
||||
lambda a: a[(a[:,0] == L_default) & (a[:,2] == eps_default) & (a[:,3] == chi_max_default)],
|
||||
lambda a: a[(a[:,0] == L_default) & (a[:,1] == n_steps_default) & (a[:,3] == chi_max_default)],
|
||||
lambda a: a[(a[:,0] == L_default) & (a[:,1] == n_steps_default) & (a[:,2] == eps_default)],
|
||||
]
|
||||
fit_fs = [
|
||||
# powerX,
|
||||
power2,
|
||||
lambda x, a, b: a * x + b,
|
||||
lambda x, a: x * 0 + a,
|
||||
power2,
|
||||
]
|
||||
|
||||
|
||||
params = ["L", "N", "Eps", "Chi"]
|
||||
N_params = len(params)
|
||||
xlabels = ["$L$", r"$n_\text{steps}$", r"$\epsilon$", r"$\chi_\text{max}$"]
|
||||
colors = ["b", "g", "o", "r"]
|
||||
fig_ax_platform = [plt.subplots(figsize=(4,3)) for _ in range(N_params)]
|
||||
linestyles = {"desktop": "solid", "laptop": "dashed"}
|
||||
markers = {"desktop": "o", "laptop": "x"}
|
||||
for device, platforms in benchmarks.items():
|
||||
linestyle = linestyles[device]
|
||||
marker = markers[device]
|
||||
for platform, opt_levels in platforms.items():
|
||||
fig_ax = [plt.subplots() for _ in range(N_params)]
|
||||
|
||||
for opt, data in sorted(opt_levels.items()):
|
||||
score = int(np.sum(data[:,4], axis=0))
|
||||
print(f"{platform} O{opt}: {score}")
|
||||
|
||||
for i in range(N_params):
|
||||
c = colors[opt]
|
||||
d = get_benchmarks_lambdas[i](data)
|
||||
x = d[:,i]
|
||||
y = d[:,4]
|
||||
y_fit, popt, pcov = fit(fit_fs[i], x, y)
|
||||
print(f"{platform:10} O{opt} {params[i]:3}: {popt}")
|
||||
ax = fig_ax[i][1]
|
||||
ax.scatter(x, y, color=c, marker=marker)
|
||||
ax.plot(x, y_fit, color=c, label=f"O{opt}", linestyle=linestyle)
|
||||
ax.set_xlabel(xlabels[i])
|
||||
if params[i] in ["Eps"]: ax.set_xscale("log")
|
||||
|
||||
if opt == 2: # platform comparison
|
||||
c = platform_colors[platform]
|
||||
ax = fig_ax_platform[i][1]
|
||||
ax.scatter(x, y, color=c, gid=f"{platform}", marker=marker)
|
||||
ax.plot(x, y_fit, color=c, label=f"{platform} {device}", gid=f"{platform}", linestyle=linestyle)
|
||||
ax.set_xlabel(xlabels[i])
|
||||
if params[i] in ["Eps"]: ax.set_xscale("log")
|
||||
# if params[i] in ["L"]: ax.set_yscale("log")
|
||||
|
||||
|
||||
for i, (fig, ax) in enumerate(fig_ax):
|
||||
ax.legend()
|
||||
ax.set_ylabel("$t$ [s]")
|
||||
ax.set_title(f"{xlabels[i]} Benchmark")
|
||||
fig.tight_layout()
|
||||
# fig.savefig(f"plt_{platform}_{params[i]}.svg")
|
||||
|
||||
from matplotlib.lines import Line2D
|
||||
legend_elements = []
|
||||
for platform in platform_colors.keys():
|
||||
legend_elements.append(Line2D([0], [0], linestyle="", marker='o', color=platform_colors[platform], label=platform, markersize=12))
|
||||
for device in benchmarks.keys():
|
||||
legend_elements.append(Line2D([0], [0], linestyle=linestyles[device], color=mpl_colors.P["fg0"], label=device))
|
||||
|
||||
for i, (fig, ax) in enumerate(fig_ax_platform):
|
||||
# ax.legend()
|
||||
ax.legend(handles=legend_elements)
|
||||
ax.set_ylabel("$t$ [s]")
|
||||
ax.set_title(f"{xlabels[i]} Benchmark")
|
||||
fig.tight_layout()
|
||||
fig.savefig(f"plt_platforms_{params[i]}.svg")
|
||||
plt.close('all')
|
||||
|
||||
|
||||
def process_benchmarks_all(benchmarks):
|
||||
for platform, opt_levels in benchmarks.items():
|
||||
figL, axL = plt.subplots()
|
||||
figN, axN = plt.subplots()
|
||||
figEps, axEps = plt.subplots()
|
||||
figChi, axChi = plt.subplots()
|
||||
axs = [axL, axN, axEps, axChi]
|
||||
|
||||
|
||||
colors = ["blue", "green", "orange", "red"]
|
||||
for opt, data in sorted(opt_levels.items()):
|
||||
c = colors[opt]
|
||||
score = int(np.sum(data[:,4], axis=0))
|
||||
print(f"{platform} O{opt}: {score}")
|
||||
# fit
|
||||
x = data[:,0:4]
|
||||
y = data[:,4].flatten()
|
||||
y_fit, popt, pcov = fit(total4D, x, y)
|
||||
print(popt, pcov)
|
||||
# for plots with only one param varied
|
||||
L, n, eps, chi = np.split(x, 4, axis=1)
|
||||
fixed_vals = [np.max(L), np.max(n), np.min(eps), np.max(chi)]
|
||||
for i in range(4):
|
||||
ax = axs[i]
|
||||
# selected data
|
||||
sel_data = data
|
||||
sel_y_fit = y_fit
|
||||
for j in range(4):
|
||||
if i == j: continue
|
||||
selection = np.where(sel_data[:,j] == fixed_vals[j])
|
||||
sel_data = sel_data[selection]
|
||||
sel_y_fit = sel_y_fit[selection]
|
||||
sel_x = sel_data[:,i]
|
||||
sel_y = sel_data[:,4].flatten()
|
||||
ax.scatter(sel_x, sel_y, color=c)
|
||||
ax.plot(sel_x, sel_y_fit, color=c, label=f"O{opt}")
|
||||
|
||||
for ax in axs:
|
||||
ax.legend()
|
||||
ax.set_ylabel("$t$ [s]")
|
||||
ax.set_title(f"{platform}")
|
||||
# ax.set_yscale("log")
|
||||
axL.set_xlabel("$L$")
|
||||
axN.set_xlabel(r"$n_\text{steps}$")
|
||||
axEps.set_xlabel(r"$\epsilon$")
|
||||
axEps.set_xscale("log")
|
||||
axChi.set_xlabel(r"$\chi_\text{max}$")
|
||||
plt.show()
|
||||
|
||||
def get_benchmarks(filename_begin):
|
||||
files = [f for f in os.listdir('.') if f.startswith(filename_begin) and f.endswith('.csv')]
|
||||
|
||||
if len(files) == 0:
|
||||
print("No benchmarks found")
|
||||
exit(1)
|
||||
|
||||
benchmarks = {}
|
||||
# read the files
|
||||
for f in files:
|
||||
match = re.fullmatch(filename_begin + r"-?(\w+)-(\w+)(?:-\d+)?-O(\d).csv", f)
|
||||
if not match:
|
||||
print("Failed to parse benchmark: " + f)
|
||||
continue
|
||||
device = match.group(1)
|
||||
platform = match.group(2)
|
||||
opt_level = int(match.group(3))
|
||||
if not device in benchmarks: benchmarks[device] = {}
|
||||
if not platform in benchmarks[device]: benchmarks[device][platform] = {}
|
||||
benchmarks[device][platform][opt_level] = []
|
||||
with open(f, 'r') as file:
|
||||
for line in file:
|
||||
n, time = line.strip("\n").split(",")
|
||||
time = float(time)
|
||||
match = re.fullmatch(r"L=(\d+)_nSteps=(\d+)_eps=(.+)_chiMax=(\d+)", n.replace("\"", ""))
|
||||
if not match:
|
||||
print("Failed to parse benchmark: " + n)
|
||||
exit(1)
|
||||
L = int(match.group(1))
|
||||
n_steps = int(match.group(2))
|
||||
eps = float(match.group(3))
|
||||
chi_max = int(match.group(4))
|
||||
benchmarks[device][platform][opt_level].append([L, n_steps, eps, chi_max, time])
|
||||
benchmarks[device][platform][opt_level] = np.array(benchmarks[device][platform][opt_level])
|
||||
return benchmarks
|
||||
|
||||
|
||||
|
||||
def repl_colors():
|
||||
"""
|
||||
In all svgs in img_dir, replace all occurances of hex colors defined in mpl_colors.P with
|
||||
var(--<color-name>)
|
||||
so that when the svg is inlined into a html it can be fully (and dynamically!) styled with css
|
||||
"""
|
||||
img_dir = "."
|
||||
|
||||
hex_to_name = {v.lower(): k for k, v in mpl_colors.P.items()}
|
||||
hex_color_pattern = re.compile(r"#([0-9a-fA-F]{6})")
|
||||
|
||||
for filename in os.listdir(img_dir):
|
||||
if not filename.endswith(".svg"): continue
|
||||
print(f"Replacing colors in {filename}")
|
||||
file_path = os.path.join(img_dir, filename)
|
||||
with open(file_path, "r") as file:
|
||||
content = file.read()
|
||||
hex_colors = hex_color_pattern.findall(content)
|
||||
modified_content = content
|
||||
for hex_color in hex_colors:
|
||||
hex_code = f"#{hex_color.lower()}"
|
||||
|
||||
# Check if the hex code is in our map
|
||||
if hex_code in hex_to_name:
|
||||
color_name = hex_to_name[hex_code]
|
||||
css_name = f"var(--{color_name})"
|
||||
modified_content = modified_content.replace(hex_code, css_name)
|
||||
else:
|
||||
# Print a warning if the color is not defined
|
||||
print(f"Warning: Color {hex_code} in {filename} is not defined in the color map.")
|
||||
|
||||
# Write the modified content back to the SVG file
|
||||
with open(file_path, "w", encoding="utf-8") as file:
|
||||
file.write(modified_content)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# correct fonts
|
||||
mpl.rcParams["mathtext.fontset"] = "stix"
|
||||
mpl.rcParams["font.family"] = "Ubuntu"
|
||||
# set replaceable colorscheme
|
||||
mpl_colors.set_colorscheme("dark")
|
||||
benchmarks1 =get_benchmarks("benchmarks-1AT")
|
||||
process_benchmarks_1AT(benchmarks1)
|
||||
repl_colors()
|
||||
|
||||
# benchmarks2 =get_benchmarks("benchmarks-all")
|
||||
# process_benchmarks_all(benchmarks2)
|
390
src/run.cpp
Normal file
390
src/run.cpp
Normal file
@ -0,0 +1,390 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <cmath>
|
||||
#include <print>
|
||||
// #include <array>
|
||||
#include "mps.hpp"
|
||||
#include "transverse_field_ising.hpp"
|
||||
#include "bose_hubbard.hpp"
|
||||
#include "tebd.hpp"
|
||||
#include "util.hpp"
|
||||
#include "type.hpp"
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/bind.h>
|
||||
namespace ems = emscripten;
|
||||
|
||||
using TfiModel = TransverseFieldIsingModel1D<dtype>;
|
||||
using BhModel = BoseHubbardModel1D<dtype>;
|
||||
|
||||
/**
|
||||
* @brief A class for generating a range of values.
|
||||
* @details
|
||||
* Returns `nSteps` values with `start` being the first and `stop` being the last value.
|
||||
* The same value is returned `countsPerStep` times before the next value is returned.
|
||||
* After the last `stop` value has been returned, the cycle is restarted from the first `start` value.
|
||||
*/
|
||||
template<typename T>
|
||||
struct Range {
|
||||
using value_type = T;
|
||||
Range(T start, T stop, unsigned nSteps, unsigned countsPerStep=1) : start(start), stop(stop), nSteps(nSteps), stepCounter(0), countsPerStep(countsPerStep), counter(0) {
|
||||
if (nSteps <= 1) {
|
||||
throw std::invalid_argument("nSteps must be greater than 1");
|
||||
}
|
||||
step = (stop - start) / (nSteps - 1);
|
||||
};
|
||||
T getNext() {
|
||||
T result = start + stepCounter * step;
|
||||
if (++counter >= countsPerStep) {
|
||||
counter = 0;
|
||||
if (++stepCounter >= nSteps) {
|
||||
stepCounter = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
private:
|
||||
T start;
|
||||
T stop;
|
||||
T step;
|
||||
unsigned nSteps;
|
||||
unsigned stepCounter;
|
||||
unsigned countsPerStep;
|
||||
unsigned counter;
|
||||
};
|
||||
|
||||
/**
|
||||
* This ugly mechanism lets the javascript pass
|
||||
* any combination of Range and basic types to a function.
|
||||
* Every time the function is called, the Range classes will return a new value while the rest stays the same.
|
||||
*/
|
||||
template<class T, template<class> class U>
|
||||
inline constexpr bool is_instance_of_v = std::false_type{};
|
||||
template<template<class> class U, class V>
|
||||
inline constexpr bool is_instance_of_v<U<V>,U> = std::true_type{};
|
||||
|
||||
template<typename T>
|
||||
concept isRange = is_instance_of_v<std::remove_reference_t<T>, Range>;
|
||||
|
||||
|
||||
// All types except Range
|
||||
template <typename T, typename Enable = void>
|
||||
struct transform_type {
|
||||
using type = T;
|
||||
};
|
||||
// Range
|
||||
template <typename T>
|
||||
struct transform_type<T, std::enable_if_t<isRange<T>>> {
|
||||
using type = typename std::remove_reference_t<T>::value_type; // If T is a Range, return its value_type
|
||||
};
|
||||
|
||||
|
||||
static_assert(isRange<Range<int>>);
|
||||
static_assert(isRange<Range<double>&>);
|
||||
static_assert(!isRange<double>);
|
||||
|
||||
// Dispatcher
|
||||
template<isRange T>
|
||||
std::remove_reference_t<T>::value_type processType(T&& obj) {
|
||||
return obj.getNext();
|
||||
}
|
||||
template<typename T>
|
||||
requires(!isRange<T>)
|
||||
T processType(T obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// Make a shared model pointer from a arguments, which may contain Range objects
|
||||
template<typename Model, typename... Args>
|
||||
std::shared_ptr<Model> makeModel(Args&&... args) {
|
||||
std::tuple<typename transform_type<Args>::type...> results = std::make_tuple(processType(std::forward<Args>(args))...);
|
||||
return std::apply([](auto&&... args) { return std::make_shared<Model>(args...); }, results);
|
||||
}
|
||||
|
||||
// template<typename Arg>
|
||||
// void printArgs(Arg&& val) {
|
||||
// std::cout << val << std::endl;
|
||||
// }
|
||||
// template<typename Arg, typename... Args>
|
||||
// void printArgs(Arg&& val, Args&&... values) {
|
||||
// std::cout << val << ", ";
|
||||
// printArgs(std::forward<Args>(values)...);
|
||||
// }
|
||||
|
||||
// template<typename... Args>
|
||||
// void processDebug(Args&&... args) {
|
||||
// std::tuple<typename transform_type<Args>::type...> results = std::make_tuple(processType(std::forward<Args>(args))...);
|
||||
// std::apply([](auto&&... args){ printArgs(args...); }, results);
|
||||
// }
|
||||
|
||||
/**
|
||||
*/
|
||||
template<typename Model>
|
||||
class Results {
|
||||
public:
|
||||
virtual ~Results() {};
|
||||
virtual postUpdateFunction_t<dtype> getPostUpdateFunction(std::shared_ptr<Model> model) = 0;
|
||||
virtual void postUpdateFunction(std::shared_ptr<Model> model, const MPS<dtype>& psi) = 0;
|
||||
};
|
||||
|
||||
|
||||
class TfiResults : public Results<TfiModel> {
|
||||
public:
|
||||
using Model_t = TfiModel;
|
||||
TfiResults(ems::val callback) : callback(callback) {
|
||||
sigmaZ.setValues({{1, 0}, {0, -1}});
|
||||
};
|
||||
/// @todo write a second postUpdateFunction without the JS callback and return that one if callback is null
|
||||
postUpdateFunction_t<dtype> getPostUpdateFunction(std::shared_ptr<TfiModel> model) override {
|
||||
return [model, this](const MPS<dtype>& psi, unsigned i){ this->postUpdateFunction(model, psi); };
|
||||
}
|
||||
void postUpdateFunction(std::shared_ptr<TfiModel> model, const MPS<dtype>& psi) override {
|
||||
auto Mval = psi.getSiteExpectationValueSum(this->sigmaZ).real();
|
||||
auto Eval = model->energy(psi).real();
|
||||
auto Sval = psi.getEntanglementEntropy(psi.getL()/2).real();
|
||||
callback(Mval, Eval, Sval);
|
||||
// hand control back to browser, otherwise site hangs and callback will not be executed
|
||||
emscripten_sleep(0);
|
||||
}
|
||||
private:
|
||||
e::TensorFixedSize<dtype, e::Sizes<2, 2>> sigmaZ;
|
||||
ems::val callback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Measures <N>, E and S
|
||||
*/
|
||||
class BoseHubbardResults : public Results<BhModel> {
|
||||
public:
|
||||
BoseHubbardResults(ems::val callback) : callback(callback) {};
|
||||
postUpdateFunction_t<dtype> getPostUpdateFunction(std::shared_ptr<BhModel> model) override {
|
||||
return [this, model](const MPS<dtype>& psi, unsigned) { this->postUpdateFunction(model, psi); };
|
||||
}
|
||||
void postUpdateFunction(std::shared_ptr<BhModel> model, const MPS<dtype>& psi) override {
|
||||
e::TensorMap<const e::Tensor<dtype, 2>> particleNumberOperator(model->getLadderOperators().getN().data(), model->localDim, model->localDim);
|
||||
auto Nval = psi.getSiteExpectationValueSum(particleNumberOperator).real() / model->L;
|
||||
auto Eval = model->energy(psi).real();
|
||||
auto Sval = psi.getEntanglementEntropy(model->L/2).real();
|
||||
callback(Nval, Eval, Sval);
|
||||
// hand control back to browser, otherwise site hangs and callback will not be executed
|
||||
emscripten_sleep(0);
|
||||
}
|
||||
private:
|
||||
ems::val callback;
|
||||
};
|
||||
|
||||
// EMSCRIPTEN_BINDINGS(my_class_example) {
|
||||
// class_<MyClass>("MyClass")
|
||||
// .constructor<int, std::string>()
|
||||
// .function("incrementX", &MyClass::incrementX)
|
||||
// .property("x", &MyClass::getX, &MyClass::setX)
|
||||
// .property("x_readonly", &MyClass::getX)
|
||||
// .class_function("getStringFromInstance", &MyClass::getStringFromInstance)
|
||||
// ;
|
||||
// };
|
||||
|
||||
|
||||
enum Tfi_INIT {
|
||||
INIT_SPIN_UP = 0,
|
||||
};
|
||||
// struct Tfi {
|
||||
// Tfi(unsigned L, double _g, double _J, Tfi_INIT init) {
|
||||
// throwIfLessThan(L, 2u, "L");
|
||||
// dtype g(_g);
|
||||
// dtype J(_J);
|
||||
// throwIfNaN(g, "g");
|
||||
// throwIfNaN(J, "J");
|
||||
// this->model = TfiModel<dtype>(L, J, g);
|
||||
// if (init == INIT_SPIN_UP) {
|
||||
// mps = initMPSspinUp<dtype>(L);
|
||||
// }
|
||||
|
||||
// }
|
||||
// TfiModel<dtype> model;
|
||||
// MPS<dtype> mps;
|
||||
// };
|
||||
|
||||
// TODO unify
|
||||
// Model1D<dtype> initModel_Tfi(unsigned L, double _g, double _J) {
|
||||
// dtype g(_g);
|
||||
// dtype J(_J);
|
||||
// throwIfNaN(g, "g");
|
||||
// throwIfNaN(J, "J");
|
||||
// throwIfLessThan(L, 3u, "L");
|
||||
// return TfiModel<dtype>(L, J, g);
|
||||
// }
|
||||
|
||||
|
||||
enum class TEBD_TYPE {
|
||||
BRICKWALL = 0,
|
||||
SECOND_ORDER = 1,
|
||||
};
|
||||
// EMSCRIPTEN_BINDINGS(tebd_module) {
|
||||
// enum_<TEBD_TYPE>(TEBD_BRICKWALL)
|
||||
// .value("TEBD_BRICKWALL", TEBD_BRICKWALL)
|
||||
// ;
|
||||
// class<MPS<dtype>>("MPS")
|
||||
// .constructor<unsigned>()
|
||||
// .function("getL", &MPS<dtype>::getL)
|
||||
// .function("getN", &MPS<dtype>::getN)
|
||||
// .function("getN_real",
|
||||
// };
|
||||
|
||||
/**
|
||||
* @brief Run TEBD on a model and measure energy, magnetization and half-chain entropy after each TEBD iteration
|
||||
* @param callback: A javascript function taking 3 parameters, M, E and S after each iteration
|
||||
*/
|
||||
template<typename Model>
|
||||
void runTEBD(MPS<dtype>& psi, const std::shared_ptr<Model> model, unsigned nSteps, double dtReal, double dtImag, double _eps, unsigned chiMax, TEBD_TYPE type, Results<Model>& result) {
|
||||
dtype eps(_eps);
|
||||
dtype dt(dtReal, dtImag);
|
||||
// Sanity checks
|
||||
throwIfNaN(eps, "eps");
|
||||
throwIfNaN(dt, "dt");
|
||||
throwIfLessThan(nSteps, 1u, "nSteps");
|
||||
throwIfLessThan(chiMax, 1u, "chiMax");
|
||||
if (psi.getL() != model->L) {
|
||||
throw std::runtime_error("psi and model have different L");
|
||||
}
|
||||
std::println("Running TEBD type={}, nSteps={}, dt={}, eps={}, chiMax={}", static_cast<int>(type), nSteps, dt, eps, chiMax);
|
||||
|
||||
// collect M over time in an array
|
||||
auto F = result.getPostUpdateFunction(model);
|
||||
// initial values now
|
||||
F(psi, 0);
|
||||
|
||||
// std::println("Bonds:");
|
||||
const auto& bondsMat = model->getH_BondsMatrices();
|
||||
// std::cout << "First: \n" << *(bondsMat.front()) << std::endl;
|
||||
// std::cout << "Secnd: \n" << *(bondsMat.at(1)) << std::endl;
|
||||
// std::cout << "Last : \n" << *(bondsMat.back()) << std::endl;
|
||||
|
||||
// const Bonds<dtype> bonds = model.getH_Bonds();
|
||||
const Bonds<dtype> bonds = getTimeEvolutionMatrices(model->getH_BondsMatrices(), dt, model->localDim);
|
||||
// std::println("U:");
|
||||
// int i = 0;
|
||||
// for (const auto& bond : bonds) {
|
||||
// printTensor(*bond, std::format("Bond[{:02}]", i));
|
||||
// i++;
|
||||
// }
|
||||
if (type == TEBD_TYPE::BRICKWALL) {
|
||||
runTEBD_brickwall(psi, bonds, chiMax, eps, nSteps, F);
|
||||
} else if (type == TEBD_TYPE::SECOND_ORDER) {
|
||||
const Bonds<dtype> bondsHalf = getTimeEvolutionMatrices(model->getH_BondsMatrices(), dt/2., model->localDim);
|
||||
runTEBD_secondOrder(psi, bonds, bondsHalf, chiMax, eps, nSteps, F);
|
||||
} else {
|
||||
throw std::invalid_argument(std::format("Got invalid TEBD_TYPE: {}", static_cast<int>(type)));
|
||||
}
|
||||
std::println("Chis: {}", psi.getChi());
|
||||
std::println("Collapse: {}", psi.collapse(0));
|
||||
};
|
||||
|
||||
|
||||
|
||||
// @TODO
|
||||
template<typename Model, typename... ModelArgs>
|
||||
void runTEBD_phaseDiagram(MPS<dtype>& psiI, unsigned nSteps, double dtReal, double dtImag, double _eps, unsigned chiMax, TEBD_TYPE type, unsigned nValues, Results<Model>& result, ModelArgs&&... args) {
|
||||
dtype eps(_eps);
|
||||
dtype dt(dtReal, dtImag);
|
||||
size_t L = psiI.getL();
|
||||
// Sanity checks
|
||||
throwIfNaN(eps, "eps");
|
||||
throwIfNaN(dt, "dt");
|
||||
throwIfLessThan(nSteps, 2u, "nSteps");
|
||||
throwIfLessThan(chiMax, 1u, "chiMax");
|
||||
std::println("Running TEBD type={}, nSteps={}, dt={}, eps={}, chiMax={}", static_cast<int>(type), nSteps, dt, eps, chiMax);
|
||||
|
||||
postUpdateFunction_t<dtype> F = [](const MPS<dtype>&, unsigned) {
|
||||
emscripten_sleep(0);
|
||||
};
|
||||
for (unsigned i = 0; i < nValues; i++) {
|
||||
// TfiModel model(L, U, g);
|
||||
std::shared_ptr<Model> model = makeModel<Model>(std::forward<ModelArgs>(args)...);
|
||||
std::println("{:02} - Model: {}", i, *model);
|
||||
auto psi = psiI;
|
||||
const Bonds<dtype> bonds = getTimeEvolutionMatrices(model->getH_BondsMatrices(), dt, model->localDim);
|
||||
runTEBD_brickwall(psi, bonds, chiMax, eps, nSteps, F);
|
||||
result.postUpdateFunction(model, psi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test(unsigned x) {
|
||||
Range<double> range(0, 1.0, 3, 2);
|
||||
|
||||
std::println("test({})", x);
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
std::println("range({})", range.getNext());
|
||||
|
||||
std::println("{}", processType(0.5));
|
||||
std::println("{}", processType(range));
|
||||
|
||||
// processDebug(range, 4.3, -3, range);
|
||||
// process2(range);
|
||||
}
|
||||
|
||||
|
||||
EMSCRIPTEN_BINDINGS(run) {
|
||||
// see https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#advanced-class-concepts
|
||||
// Results
|
||||
ems::class_<Results<TfiModel>>("ResultsBaseTfi");
|
||||
ems::class_<Results<BhModel>>("ResultsBaseBh");
|
||||
ems::class_<TfiResults, ems::base<Results<TfiModel>>>("ResultsTfi")
|
||||
.constructor<ems::val>()
|
||||
;
|
||||
ems::class_<BoseHubbardResults, ems::base<Results<BhModel>>>("ResultsBh")
|
||||
.constructor<ems::val>()
|
||||
;
|
||||
// Models
|
||||
ems::class_<Model1D<dtype>>("Model1D")
|
||||
.smart_ptr<std::shared_ptr<Model1D<dtype>>>("Model1D")
|
||||
;
|
||||
ems::class_<TfiModel, ems::base<Model1D<dtype>>>("ModelTfi")
|
||||
// .constructor<unsigned, double ,double>()
|
||||
.smart_ptr_constructor("ModelTfi", &std::make_shared<TfiModel, unsigned, double ,double>)
|
||||
;
|
||||
ems::class_<BhModel, ems::base<Model1D<dtype>>>("ModelBh")
|
||||
// .constructor<unsigned, double, double, double, unsigned>()
|
||||
.smart_ptr_constructor("ModelBh", &std::make_shared<BhModel, unsigned, double, double, double, unsigned>)
|
||||
;
|
||||
ems::class_<Range<double>>("DoubleRange")
|
||||
.constructor<double, double, unsigned, unsigned>()
|
||||
;
|
||||
// Other
|
||||
ems::class_<MPS<dtype>>("MPS");
|
||||
ems::function("initMpsSpinUp", &initMPS_spinUp<dtype>);
|
||||
ems::function("initMpsSpinRight", &initMPS_spinRight<dtype>);
|
||||
ems::function("initMpsNParticles", &initMPS_nParticles<dtype>);
|
||||
// ems::function("initMPS_spinUp", &initMPS_spinUp);
|
||||
ems::register_vector<double>("stdVectorDouble");
|
||||
ems::register_vector<std::vector<double>>("stdVectorDouble2D");
|
||||
// ems::class_<Results>("TEBDResults")
|
||||
// .property("M", &Results::M)
|
||||
// .property("E", &Results::E)
|
||||
// .property("S", &Results::S)
|
||||
// ;
|
||||
ems::enum_<TEBD_TYPE>("TEBD_TYPE")
|
||||
.value("BRICKWALL", TEBD_TYPE::BRICKWALL)
|
||||
.value("SECOND_ORDER", TEBD_TYPE::SECOND_ORDER)
|
||||
;
|
||||
ems::function("runTebdTfi", &runTEBD<TfiModel>);
|
||||
ems::function("runTebdPhaseDiagramTfi", &runTEBD_phaseDiagram<TfiModel, unsigned, Range<double>, Range<double>>);
|
||||
ems::function("runTebdBh", &runTEBD<BhModel>);
|
||||
ems::function("runTebdPhaseDiagramBh", &runTEBD_phaseDiagram<BhModel, unsigned, double, Range<double>, Range<double>, unsigned>);
|
||||
ems::function("test", &test);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
22
src/stopwatch.cpp
Normal file
22
src/stopwatch.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "stopwatch.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
|
||||
Stopwatch::Stopwatch() : running(false) {}
|
||||
|
||||
void Stopwatch::start() {
|
||||
t_start = std::chrono::steady_clock::now();
|
||||
running = true;
|
||||
}
|
||||
|
||||
double Stopwatch::stop() {
|
||||
if (!running) { return 0; }
|
||||
else {
|
||||
running = false;
|
||||
// (time_point - time_point) = std::chrono::duration, not double
|
||||
return std::chrono::duration<double>(std::chrono::steady_clock::now() - t_start).count();
|
||||
}
|
||||
}
|
||||
|
36
src/stopwatch.hpp
Normal file
36
src/stopwatch.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* @brief Stopwatches measure the time between two points
|
||||
* @details
|
||||
* The stopwatch makes use of std::chronos::steady_clock to measure the time between
|
||||
* when it was startet and when it was stoped. It returnes the time in seconds.
|
||||
*/
|
||||
class Stopwatch {
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new Stopwatch instance
|
||||
*/
|
||||
Stopwatch();
|
||||
|
||||
/**
|
||||
* @brief Start the stopwatch
|
||||
* @details
|
||||
* If the watch is started while already running, it restarts
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief Stop the stopwatch
|
||||
* @returns The elapsed time in seconds as double. If the watch was not started, it returns 0
|
||||
*/
|
||||
double stop();
|
||||
|
||||
///@returns true if stopwatch is running, false if not
|
||||
bool isRunning() { return running; }
|
||||
private:
|
||||
std::chrono::steady_clock::time_point t_start;
|
||||
bool running;
|
||||
};
|
4
src/type.hpp
Normal file
4
src/type.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include <complex>
|
||||
/// the datatype for all template instantiations
|
||||
using dtype = std::complex<double>;
|
||||
|
132
src/util.hpp
Normal file
132
src/util.hpp
Normal file
@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
#include <format>
|
||||
#include <complex>
|
||||
#include <iostream>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
|
||||
#include "type.hpp"
|
||||
|
||||
template<typename U>
|
||||
struct std::formatter<std::vector<U>> {
|
||||
using T = std::vector<U>;
|
||||
// using std::formatter<int>::parse;
|
||||
constexpr auto parse(std::format_parse_context& ctx){
|
||||
auto pos = ctx.begin();
|
||||
while (pos != ctx.end() && *pos != '}') {
|
||||
if (*pos == 'a') { useChar = 1; }
|
||||
else if (*pos == 'b') { useChar = 2; }
|
||||
else if (*pos == 'p') { useChar = 3; }
|
||||
++pos;
|
||||
}
|
||||
return pos; // expect `}` at this position, otherwise its an error
|
||||
}
|
||||
|
||||
auto format(const T& v, auto& ctx) const {
|
||||
// TODO figure out why tf it doesnt compile with openChars.at(..)
|
||||
auto out = ctx.out();
|
||||
// out = std::format_to(out, "{}", openChars.at(useChar));
|
||||
char c = '{';
|
||||
if (useChar > 0) { c = '<'; }
|
||||
out = std::format_to(out, "{}", c);
|
||||
|
||||
auto it = v.begin();
|
||||
if (it != v.end()) {
|
||||
out = std::format_to(out, "{}", *it);
|
||||
}
|
||||
it++;
|
||||
for (; it != v.end(); it++) {
|
||||
out = std::format_to(out, ", {}", *it);
|
||||
}
|
||||
// return std::format_to(out, "{}", closeChars.at(useChar));
|
||||
c = '}';
|
||||
if (useChar > 0) { c = '>'; }
|
||||
return std::format_to(out, "{}", c);
|
||||
// return out;
|
||||
}
|
||||
public:
|
||||
size_t useChar = 0;
|
||||
static constexpr std::string openChars{"(<[{"};
|
||||
static constexpr std::string closeChars{")>]}"};
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename U>
|
||||
struct std::formatter<std::complex<U>> : std::formatter<U> {
|
||||
using T = std::complex<U>;
|
||||
using std::formatter<U>::parse;
|
||||
auto format(const T& v, auto& ctx) const {
|
||||
auto out = ctx.out();
|
||||
out = std::format_to(out, "({}, {})", v.real(), v.imag());
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
// // Formatter specialization for std::complex
|
||||
// template <typename T>
|
||||
// struct std::formatter<std::complex<T>> {
|
||||
// std::formatter<char> inner_formatter; // Inner formatter for real/imaginary parts
|
||||
|
||||
// // Parse the format specifier
|
||||
// constexpr auto parse(std::format_parse_context& ctx) {
|
||||
// // Use the same format specifier for real/imaginary parts as for other types
|
||||
// return inner_formatter.parse(ctx);
|
||||
// }
|
||||
|
||||
// // Format the complex number
|
||||
// template <typename FormatContext>
|
||||
// auto format(const std::complex<T>& c, FormatContext& ctx) {
|
||||
// // Format both real and imaginary parts using the inner formatter
|
||||
// return std::format_to(
|
||||
// ctx.out(),
|
||||
// "({} + {}i)",
|
||||
// std::format(inner_formatter, c.real()), // Format real part
|
||||
// std::format(inner_formatter, c.imag()) // Format imaginary part
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
template<typename T, typename string_type>
|
||||
void printTensor(const T& t, string_type name="") {
|
||||
std::cout << name << "(" << t.dimensions() << ") = \n" << t << "\n" << std::endl;
|
||||
}
|
||||
|
||||
template<typename T, typename string_type>
|
||||
void printTensorDims(const T& t, string_type name="") {
|
||||
std::cout << name << "(" << t.dimensions() << ")" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void throwIfNaN(const std::complex<T>& v, std::string_view name) {
|
||||
if (std::isnan(v.real())) {
|
||||
throw std::invalid_argument(std::format("Real part of variable '{}' is NaN", name));
|
||||
}
|
||||
else if (std::isnan(v.imag())) {
|
||||
throw std::invalid_argument(std::format("Imaginary part of variable '{}' is NaN", name));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void throwIfLessThan(const T& v, const T& compare, std::string_view name) {
|
||||
if (v < compare) {
|
||||
throw std::invalid_argument(std::format("Variable '{}' must not be less than '{}', but is '{}'", name, v, compare));
|
||||
}
|
||||
}
|
||||
|
||||
// Make every class with public std::string format() const member formatable
|
||||
template <typename T>
|
||||
concept HasFormat = requires(const T obj) {
|
||||
{ obj.format() } -> std::convertible_to<std::string>;
|
||||
};
|
||||
template<HasFormat T>
|
||||
struct std::formatter<T> {
|
||||
constexpr auto parse(std::format_parse_context& ctx) {
|
||||
return ctx.begin();
|
||||
}
|
||||
auto format(const T& obj, auto& ctx) const {
|
||||
return std::format_to(ctx.out(), "{}", obj.format());
|
||||
}
|
||||
};
|
35
src/wasm-test.cpp
Normal file
35
src/wasm-test.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <print>
|
||||
#include "model.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <emscripten/bind.h>
|
||||
namespace ems = emscripten;
|
||||
|
||||
struct Test {
|
||||
std::vector<int> v;
|
||||
size_t var1;
|
||||
size_t var2;
|
||||
};
|
||||
|
||||
Test makeTest(unsigned n) {
|
||||
Test test;
|
||||
test.v.resize(n);
|
||||
std::iota(test.v.begin(), test.v.end(), 0);
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
void useTest(const Test& test, unsigned x) {
|
||||
std::println("useTest: size={}, x={}", test.v.size(), x);
|
||||
}
|
||||
|
||||
// EMSCRIPTEN_BINDINGS(test) {
|
||||
// // ems::class_<TFIModel<dtype>>("TFIModel");
|
||||
// // ems::class_<MPS<dtype>>("MPS");
|
||||
// ems::function("makeTest", &makeTest);
|
||||
// ems::function("useTest", &useTest);
|
||||
// }
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user