62 typedef typename SymmGroup::charge charge;
63 typedef boost::unordered_map<size_t,std::pair<charge,size_t> > bond_charge_map;
68 boost::function<charge (charge, charge)> phys_fuse = boost::lambda::bind(
static_cast<charge(*)(charge, charge)
>(
SymmGroup::fuse),
69 boost::lambda::_1, -boost::lambda::_2);
74 left_i.
insert( std::make_pair(SymmGroup::IdentityCharge, 1) );
76 bond_charge_map left_map, right_map;
77 left_map[0] = std::make_pair(SymmGroup::IdentityCharge, 0);
79 for (
int i=0; i<mpo.size(); ++i) {
82 boost::unordered_map<charge, size_t> right_sizes;
88 for (
size_t b1=0; b1<mpo[i].row_dim(); ++b1)
91 row_proxy row_b1 = mpo[i].row(b1);
92 for (
typename row_proxy::const_iterator it = row_b1.begin(); it != row_b1.end(); ++it)
94 size_t b2 = it.index();
97 charge l_charge;
size_t ll;
98 boost::tie(l_charge, ll) = left_map[b1];
99 size_t l_size = left_i[left_i.
position(l_charge)].second;
101 typename Matrix::value_type scale = mpo[i].at(b1, b2).scale;
103 for (
size_t n=0; n<in_block.
n_blocks(); ++n)
105 charge s1_charge;
size_t size1;
106 boost::tie(s1_charge, size1) = in_block.
left_basis()[n];
107 charge s2_charge;
size_t size2;
108 boost::tie(s2_charge, size2) = in_block.
right_basis()[n];
110 charge s_charge = phys_fuse(s1_charge, s2_charge);
112 charge out_r_charge = out_l_charge;
114 if (
false &&
run==0) {
115 maquis::cout <<
"s1: " << s1_charge << std::endl;
116 maquis::cout <<
"s2: " << s2_charge << std::endl;
117 maquis::cout <<
"s: " << s_charge << std::endl;
118 maquis::cout <<
"b1: " << b1 << std::endl;
119 maquis::cout <<
"b2: " << b2 << std::endl;
120 maquis::cout <<
"l: " << l_charge << std::endl;
121 maquis::cout <<
"r: " << out_r_charge << std::endl;
123 maquis::cout <<
" ------ " << std::endl;
127 typename bond_charge_map::const_iterator match = right_map.find(b2);
128 if (match == right_map.end()) {
129 right_map[b2] = std::make_pair(out_r_charge, right_sizes[out_r_charge]++);
131 assert(match->second.first == out_r_charge);
137 if (!out_block.
has_block(out_l_charge, out_r_charge))
138 out_block.
insert_block(Matrix(left_out.size(s_charge,l_charge), right_sizes[out_r_charge], 0.),
139 out_l_charge, out_r_charge);
141 size_t phys_offset = phys_prod(s1_charge, s2_charge);
142 size_t left_offset = left_out(s_charge, l_charge);
144 size_t rr = right_map[b2].second;
146 Matrix & out_m = out_block(out_l_charge, out_r_charge);
147 Matrix
const& in_m = in_block[n];
149 for (
size_t ss2=0; ss2<size2; ++ss2)
150 for (
size_t ss1=0; ss1<size1; ++ss1)
152 size_t ss = ss2 + ss1*size2 + phys_offset;
154 out_m(left_offset + ss*l_size + ll, rr) = in_m(ss1, ss2) * scale;
void run(std::string const &chkp1, std::string const &chkp2)
size_type n_blocks() const
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
size_type insert_block(Matrix const &, charge, charge)
block_matrix< Matrix, SymmGroup > adjoin(block_matrix< Matrix, SymmGroup > const &m)
bool has_block(charge r, charge c) const
Index< SymmGroup > const & right_basis() const
std::size_t position(charge c) const
std::size_t insert(std::pair< charge, std::size_t > const &x)
Index< SymmGroup > const & left_basis() const
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.