28 #ifndef GENERATE_MPO_TAGGED_MPO_MAKER_H
29 #define GENERATE_MPO_TAGGED_MPO_MAKER_H
43 #include <boost/bind.hpp>
47 namespace generate_mpo
52 template <
typename pos_t,
typename tag_type,
typename index_type>
87 template <
typename T,
typename U>
88 std::pair<T,U>
to_pair(boost::tuple<T,U>
const& t)
90 return std::make_pair( boost::get<0>(t), boost::get<1>(t) );
93 template<
class Matrix,
class SymmGroup>
96 typedef typename Matrix::value_type scale_type;
103 typedef boost::tuple<std::size_t, std::size_t, tag_type, scale_type> tag_block;
105 typedef ::term_descriptor<typename Matrix::value_type>
term_descriptor;
108 typedef std::pair<tag_type, scale_type> prempo_value_type;
110 typedef std::map<std::pair<prempo_key_type, prempo_key_type>, prempo_value_type> prempo_map_type;
112 enum merge_kind {attach, detach};
119 , tag_handler(model.operators_table())
123 , leftmost_right(length)
126 for (
size_t p = 0; p < length-1; ++p)
127 prempo[p][make_pair(trivial_left,trivial_left)] = prempo_value_type(model.identity_matrix_tag(lat.
get_prop<
int>(
"type",p)), 1.);
135 std::sort(term.begin(), term.end(),
pos_tag_lt());
136 index_type nops = term.size();
156 leftmost_right = std::min(leftmost_right, boost::get<0>(*term.rbegin()));
161 if (!finalized) finalize();
164 typedef std::map<prempo_key_type, index_type> index_map;
165 typedef typename index_map::iterator index_iterator;
167 left[trivial_left] = 0;
169 for (pos_t p = 0; p < length; ++p) {
170 std::vector<tag_block> pre_tensor; pre_tensor.reserve(prempo[p].size());
174 for (
typename prempo_map_type::const_iterator it = prempo[p].begin();
175 it != prempo[p].end(); ++it) {
178 prempo_value_type
const& val = it->second;
180 index_iterator ll = left.find(k1);
181 if (ll == left.end())
182 throw std::runtime_error(
"k1 not found!");
184 index_iterator rr = right.find(k2);
185 if (k2 == trivial_left && rr == right.end())
186 boost::tie(rr, boost::tuples::ignore) = right.insert( make_pair(k2, 0) );
187 else if (k2 == trivial_right && rr == right.end())
188 boost::tie(rr, boost::tuples::ignore) = right.insert( make_pair(k2, 1) );
189 else if (rr == right.end())
190 boost::tie(rr, boost::tuples::ignore) = right.insert( make_pair(k2, r++) );
192 pre_tensor.push_back( tag_block(ll->second, rr->second, val.first, val.second) );
195 std::pair<std::size_t, std::size_t> rcd =
rcdim(pre_tensor);
198 else if (p == length - 1)
212 assert(term.size() == 1);
216 op_t current_op = tag_handler->get_op(term.
operator_tag(0));
217 current_op *= term.
coeff;
218 site_terms[term.
position(0)] += current_op;
223 assert(term.size() == 2);
225 prempo_key_type k1 = trivial_left;
229 k2.pos_op.push_back(
to_pair(term[i+1]));
232 bool trivial_fill = !tag_handler->is_fermionic(term.
operator_tag(1));
236 prempo_key_type k2 = trivial_right;
237 insert_operator(term.
position(i), make_pair(k1, k2), prempo_value_type(term.
operator_tag(i), 1.), detach);
243 assert(term.size() == 3);
244 int nops = term.size();
248 for (
int i = 0; i < nops; ++i) {
253 prempo_key_type k1 = trivial_left;
254 std::vector<pos_op_type> ops_left;
260 k2.pos_op.push_back(
to_pair(term[i]));
261 k1 = insert_operator(term.
position(i), make_pair(k1, k2), prempo_value_type(term.
operator_tag(i), 1.), attach);
265 bool trivial_fill = (nferm % 2 == 0);
272 k2.pos_op.push_back(
to_pair(term[i+1]));
277 bool trivial_fill = (nferm % 2 == 0);
283 insert_operator(term.
position(i), make_pair(k1, trivial_right), prempo_value_type(term.
operator_tag(i), 1.), detach);
289 assert(term.size() == 4);
290 int nops = term.size();
294 for (
int i = 0; i < nops; ++i) {
299 prempo_key_type k1 = trivial_left;
300 std::vector<pos_op_type> ops_left;
303 for (
int i = 0; i < 2; ++i) {
304 ops_left.push_back(
to_pair(term[i])); prempo_key_type k2(ops_left);
305 k1 = insert_operator(term.
position(i), make_pair(k1, k2), prempo_value_type(term.
operator_tag(i), 1.), attach);
309 bool trivial_fill = (nferm % 2 == 0);
316 k2.pos_op.push_back(
to_pair(term[3]));
321 bool trivial_fill = (nferm % 2 == 0);
328 insert_operator(term.
position(i), make_pair(k1, trivial_right), prempo_value_type(term.
operator_tag(i), 1.), detach);
334 int nops = term.size();
337 static index_type next_offset = 0;
338 index_type current_offset = (next_offset++);
340 prempo_key_type k1 = trivial_left;
342 k2.pos_op.push_back(
to_pair(term[nops-1]) );
350 throw std::runtime_error(
"for n > 4 operators filling is assumed to be done manually. the list of operators contains empty sites.");
354 for (
int i = 1; i < nops; ++i) {
358 insert_operator(term.
position(i), make_pair(k1, k2), prempo_value_type(term.
operator_tag(i), 1.), detach);
361 throw std::runtime_error(
"for n > 4 operators filling is assumed to be done manually. the list of operators contains empty sites.");
366 void insert_filling(pos_t i, pos_t j, prempo_key_type k,
bool trivial_fill)
369 tag_type op = (trivial_fill) ? model.identity_matrix_tag(lat.
get_prop<
int>(
"type",i)) : model.filling_matrix_tag(lat.
get_prop<
int>(
"type",i));
370 std::pair<typename prempo_map_type::iterator,bool> ret = prempo[i].insert( make_pair(make_pair(k,k), prempo_value_type(op, 1.)) );
371 if (!ret.second && ret.first->second.first != op)
372 throw std::runtime_error(
"Pre-existing term at site "+boost::lexical_cast<std::string>(i)
373 +
". Needed "+boost::lexical_cast<std::string>(op)
374 +
", found "+boost::lexical_cast<std::string>(ret.first->second.first));
378 prempo_key_type insert_operator(pos_t p, std::pair<prempo_key_type, prempo_key_type> kk, prempo_value_type val,
379 merge_kind merge_behavior=detach)
383 std::pair<typename prempo_map_type::iterator,bool> match = prempo[p].insert( make_pair(kk, val) );
384 if (merge_behavior == detach) {
386 std::pair<prempo_key_type, prempo_key_type> kk_max = kk;
387 kk_max.second.offset = std::numeric_limits<index_type>::max();
389 typename prempo_map_type::iterator highest_offset = prempo[p].upper_bound(kk_max);
391 kk.second.offset = highest_offset->first.second.offset + 1;
392 prempo[p].insert(highest_offset, make_pair(kk, val));
397 while (!match.second && match.first->second != val) {
398 kk.second.offset += 1;
399 match = prempo[p].insert( make_pair(kk, val) );
408 std::pair<prempo_key_type,prempo_key_type> kk = make_pair(trivial_left,trivial_right);
409 for (
typename std::map<pos_t, op_t>::const_iterator it = site_terms.begin();
410 it != site_terms.end(); ++it) {
412 std::pair<typename prempo_map_type::iterator,bool> ret;
413 ret = prempo[it->first].insert( make_pair( kk, prempo_value_type(site_tag,1.) ) );
415 throw std::runtime_error(
"another site term already existing!");
419 bool trivial_fill =
true;
420 insert_filling(leftmost_right+1, length, trivial_right, trivial_fill);
432 boost::shared_ptr<TagHandler<Matrix, SymmGroup> > tag_handler;
433 std::vector<prempo_map_type> prempo;
434 prempo_key_type trivial_left, trivial_right;
435 std::map<pos_t, op_t> site_terms;
437 pos_t leftmost_right;
std::pair< pos_t, tag_type > op_pair_t
definition of Lattice base class
void add_term(term_descriptor term)
include all symmetry definitions
OPTable< Matrix, SymmGroup >::tag_type tag_type
definition of Model base class
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
declaration of block_matrix class
prempo_key(std::vector< pos_op_type > const &po_, index_type o_=0)
std::pair< T, U > to_pair(boost::tuple< T, U > const &t)
tag_type operator_tag(size_type i) const
prempo_key(kind_type k_=bulk, index_type o_=0)
bool operator<(prempo_key const &lhs) const
utility functions for the MPO
TaggedMPOMaker(Lattice const &lat_, Model< Matrix, SymmGroup > const &model_)
definition of MPO class (vector of MPOTensor)
std::pair< pos_t, tag_type > pos_op_type
T get_prop(std::string property, pos_t site) const
bool operator==(prempo_key const &lhs) const
std::pair< size_t, size_t > rcdim(Vector const &pm)
algorithms for block_matrix (gemm, svd, etc.)
MPO< Matrix, SymmGroup > create_mpo()
std::vector< pos_op_type > pos_op
pos_type position(size_type i) const
impl_type::terms_type terms_type