34 #include <boost/function.hpp>
59 template <
class Matrix,
class SymmGroup>
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;
194 template <
class Matrix,
class InSymm>
199 typedef typename InSymm::charge in_charge;
200 typedef typename OutSymm::charge out_charge;
201 typedef boost::unordered_map<size_t,std::pair<out_charge,size_t> > bond_charge_map;
206 boost::function<out_charge (in_charge, in_charge)> phys_group = boost::lambda::bind(
static_cast<out_charge(*)(in_charge, in_charge)
>(
group),
207 boost::lambda::_1, -boost::lambda::_2);
211 left_i.
insert( std::make_pair(OutSymm::IdentityCharge, 1) );
213 for (
int i=0; i<mpo.size(); ++i) {
224 for (
size_t b1=0; b1<mpo[i].row_dim(); ++b1)
226 row_proxy row_b1 = mpo[i].row(b1);
227 for (
typename row_proxy::const_iterator it = row_b1.begin(); it != row_b1.end(); ++it)
229 size_t b2 = it.index();
231 for (
size_t l=0; l<left_i.
size(); ++l)
233 out_charge l_charge = left_i[l].first;
234 size_t l_size = left_i[l].second;
237 typename Matrix::value_type scale = mpo[i].at(b1, b2).scale;
239 for (
size_t n=0; n<in_block.
n_blocks(); ++n)
241 in_charge s1_charge;
size_t size1;
242 boost::tie(s1_charge, size1) = in_block.
left_basis()[n];
243 in_charge s2_charge;
size_t size2;
244 boost::tie(s2_charge, size2) = in_block.
right_basis()[n];
246 out_charge s_charge = phys_group(s1_charge, s2_charge);
248 out_charge out_r_charge = out_l_charge;
250 if (! allowed[i+1].has(out_r_charge) )
253 if (!out_block.
has_block(out_l_charge, out_r_charge))
254 out_block.
insert_block(Matrix(left_out.
size(s_charge,l_charge), mpo[i].col_dim(), 0.),
255 out_l_charge, out_r_charge);
257 size_t phys_offset = 0;
258 size_t left_offset = left_out(s_charge, l_charge);
262 Matrix & out_m = out_block(out_l_charge, out_r_charge);
263 Matrix
const& in_m = in_block[n];
265 for (
size_t ss2=0; ss2<size2; ++ss2)
266 for (
size_t ss1=0; ss1<size1; ++ss1)
268 size_t ss = ss2 + ss1*size2 + phys_offset;
270 out_m(left_offset + ss*l_size + ll, rr) = in_m(ss1, ss2) * scale;
void run(std::string const &chkp1, std::string const &chkp2)
TrivialGroup::charge group(TrivialGroup::charge c1, TrivialGroup::charge c2)
MPS< Matrix, typename grouped_symmetry< InSymm >::type > mpo_to_smps_group(MPO< Matrix, InSymm > const &mpo, Index< InSymm > const &phys_i, std::vector< Index< typename grouped_symmetry< InSymm >::type > > const &allowed)
size_type n_blocks() const
declaration of the MPS class (vector of MPSTensor)
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
size_t size(charge pc) const
size_type insert_block(Matrix const &, charge, charge)
block_matrix< Matrix, SymmGroup > adjoin(block_matrix< Matrix, SymmGroup > const &m)
definition of MPO class (vector of MPOTensor)
bool has_block(charge r, charge c) const
MPS< Matrix, SymmGroup > mpo_to_smps(MPO< Matrix, SymmGroup > const &mpo, Index< SymmGroup > const &phys_i)
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.