27 #ifndef TENSOR_INDEXING_H
28 #define TENSOR_INDEXING_H
34 #include <boost/unordered_map.hpp>
35 #include <boost/container/flat_set.hpp>
36 #include <boost/container/flat_map.hpp>
37 #include <boost/array.hpp>
38 #include <boost/lambda/lambda.hpp>
39 #include <boost/lambda/bind.hpp>
42 #include <mp_tensors/wrappers.h>
45 #include <boost/serialization/serialization.hpp>
46 #include <boost/serialization/utility.hpp>
47 #include <boost/serialization/vector.hpp>
50 namespace index_detail
52 template<
class SymmGroup>
53 bool lt(std::pair<typename SymmGroup::charge, std::size_t>
const & a,
54 std::pair<typename SymmGroup::charge, std::size_t>
const & b)
56 return a.first < b.first;
59 template<
class SymmGroup>
61 bool operator()(std::pair<typename SymmGroup::charge, std::size_t>
const & a,
62 std::pair<typename SymmGroup::charge, std::size_t>
const & b){
63 return a.first > b.first;
67 template<
class SymmGroup>
68 typename SymmGroup::charge
get_first(std::pair<typename SymmGroup::charge, std::size_t>
const & x)
73 template<
class SymmGroup>
74 std::size_t
get_second(std::pair<typename SymmGroup::charge, std::size_t>
const & x)
80 template<
class SymmGroup>
86 bool operator()(std::pair<typename SymmGroup::charge, std::size_t>
const & x)
const
92 typename SymmGroup::charge c_;
96 template<
class SymmGroup>
99 template<
class SymmGroup>
class Index
100 :
protected std::vector<std::pair<typename SymmGroup::charge, std::size_t> >
102 typedef std::vector<std::pair<typename SymmGroup::charge, std::size_t> > base_t;
103 typedef boost::container::flat_map<typename SymmGroup::charge, std::size_t> pos_t;
106 typedef typename SymmGroup::charge
charge;
122 std::swap(static_cast<base_t&>(*
this), static_cast<base_t&>(rhs));
123 positions.swap(rhs.positions);
136 typename pos_t::const_iterator it = positions.find(c);
137 if (it == positions.end())
139 return (*
this)[it->second].second;
144 typename pos_t::const_iterator it = positions.find(c);
145 if (it == positions.end())
148 return positions.find(c)->second;
151 std::size_t
position(std::pair<charge, std::size_t> x)
const
153 assert(
has(x.first) );
157 boost::lambda::_1 + boost::lambda::bind(index_detail::get_second<SymmGroup>, boost::lambda::_2)
163 return positions.count(c) > 0;
172 std::size_t
insert(std::pair<charge, std::size_t>
const & x)
174 std::size_t d = destination(x.first);
175 std::vector<std::pair<charge, std::size_t> >
::insert(this->
begin() + d, x);
182 std::vector<std::pair<charge, std::size_t> >
::insert(this->
begin() + position, x);
188 for (std::size_t k = 0; k < this->
size(); ++k)
200 return !( *
this == o );
205 assert( this->
size() > 0 );
211 std::vector<charge> ret(this->
size());
212 for (std::size_t k = 0; k < this->
size(); ++k) ret[k] = (*
this)[k].first;
216 std::vector<std::size_t>
sizes()
const
218 std::vector<std::size_t> ret(this->
size());
219 for (std::size_t k = 0; k < this->
size(); ++k) ret[k] = (*
this)[k].second;
226 boost::lambda::_1 + boost::lambda::bind(index_detail::get_second<SymmGroup>, boost::lambda::_2));
243 boost::tuple<charge, std::size_t>
element(std::size_t p)
const
246 while (p >= (*
this)[i].second) {
247 p -= (*this)[i].second;
250 return boost::make_tuple( (*
this)[i].first, p );
253 std::size_t
size()
const {
return base_t::size(); }
261 void push_back(std::pair<charge, std::size_t>
const & x){
262 base_t::push_back(x);
265 void calc_positions() {
268 positions[it->first] = it-this->begin();
271 std::size_t destination(
charge c)
const
273 return std::find_if(this->
begin(), this->
end(),
274 boost::lambda::bind(index_detail::lt<SymmGroup>,
276 std::make_pair(c, 0))) - this->
begin();
280 #ifdef PYTHON_EXPORTS
281 std::size_t py_insert(wrapped_pair<SymmGroup> p)
283 return this->
insert(p.data_);
287 template<
class Archive>
290 typedef std::vector<std::pair<typename SymmGroup::charge, std::size_t> > my_type;
291 ar[
"Index"] >>
static_cast<my_type&
>(*this);
295 template<
class Archive>
298 typedef std::vector<std::pair<typename SymmGroup::charge, std::size_t> > my_type;
299 ar[
"Index"] <<
static_cast<my_type
const &
>(*this);
302 friend class boost::serialization::access;
304 template <
class Archive>
305 void load(Archive & ar,
const unsigned int version)
307 ar & boost::serialization::base_object<base_t>(*this);
310 template <
class Archive>
311 void save(Archive & ar,
const unsigned int version)
const
313 ar & boost::serialization::base_object<base_t>(*this);
316 BOOST_SERIALIZATION_SPLIT_MEMBER()
319 template<
class SymmGroup>
323 typedef typename SymmGroup::charge
charge;
332 template<
class Fusion>
341 template<
class Fusion>
346 keys_vals_.rehash((keys_vals_.size() + a.
size()*b.
size()) / keys_vals_.max_load_factor() + 1);
350 charge pc = f(it1->first, it2->first);
351 keys_vals_[std::make_pair(it1->first, it2->first)] = size_[pc];
353 size_[pc] += it1->second * it2->second;
360 typedef typename boost::unordered_map<std::pair<charge, charge>,
size_t>::const_iterator match_type;
361 match_type match = keys_vals_.find(std::make_pair(a,b));
362 assert( match != keys_vals_.end() );
363 return match->second;
368 assert(size_.count(pc) > 0);
377 template<
class Fusion>
381 assert(size_.count(pc) > 0);
386 mutable boost::unordered_map<charge, size_t> size_;
387 boost::unordered_map<std::pair<charge, charge>,
size_t> keys_vals_;
390 template<
class SymmGroup>
394 typedef typename SymmGroup::charge
charge;
398 , cur_block(idx.begin())
400 , max_i(cur_block->second)
405 return std::make_pair(cur_block->first, cur_i);
408 boost::shared_ptr<std::pair<charge, std::size_t> >
operator->()
const
410 return boost::shared_ptr<std::pair<charge, std::size_t> >(
new std::pair<charge, std::size_t>(cur_block->first, cur_i));
420 if (cur_block != idx_.end()) {
422 max_i = cur_block->second;
439 return cur_block == idx_.end();
445 std::size_t cur_i, max_i;
448 template<
class SymmGroup>
460 #if defined(WIN32) || defined(WIN64)
461 template<
class A,
class B> std::pair<A, B> mypair(A & a, B & b) {
return std::pair<A,B>(a,b); }
465 template<
class SymmGroup>
471 template<
class SymmGroup>
474 typedef typename SymmGroup::charge charge;
477 std::transform(nc.begin(), nc.end(), nc.begin(), std::negate<charge>());
478 std::sort(nc.begin(), nc.end());
480 std::vector<std::size_t> nd(inp.
size()), od = inp.
sizes();
481 for (
unsigned int i = 0; i < nd.size(); ++i)
482 nd[i] = od[std::find(oc.begin(), oc.end(),
486 for (
size_t i=0; i<nc.size(); ++i)
487 #
if not defined(WIN32) && not defined(WIN64)
488 ret.
insert(std::make_pair(nc[i], nd[i]));
490 ret.
insert(mypair(nc[i], nd[i]));
495 template<
class SymmGroup>
496 std::ostream& operator<<(std::ostream& os, Index<SymmGroup>
const & idx)
503 os <<
"( " << it->first <<
": " << it->second <<
" )";
510 template<
class SymmGroup>
514 typedef typename SymmGroup::charge charge;
521 std::size_t ps = it1->second * it2->second;
522 std::size_t match = ret.
position(pdc);
523 if (match < ret.
size())
524 ret[match].second += ps;
526 ret.
insert(std::make_pair(pdc, ps));
532 template<
class SymmGroup>
538 boost::lambda::bind(index_detail::get_first<SymmGroup>, boost::lambda::_1))),
543 boost::lambda::bind(index_detail::get_first<SymmGroup>, boost::lambda::_1))),
548 template<
class charge>
549 std::pair<charge, std::size_t>
operator-(std::pair<charge, std::size_t>
const & p)
551 return std::make_pair(-p.first, p.second);
554 template<
class T> boost::array<T, 1>
_(T
const & a)
556 boost::array<T, 1> r;
561 template<
class T> boost::array<T, 2>
_(T
const & a, T
const & b)
563 boost::array<T, 2> r;
569 #define IMPL_COMMA(tpl, type) \
570 tpl boost::array<type, 2> operator^(type const & a, type const & b) { \
571 boost::array<type, 2> ret; \
576 #define IMPL_COMMA_2(tpl, type) \
577 tpl boost::array<type, L+1> operator^(boost::array<type, L> const & a, type const & b) { \
578 boost::array<type, L+1> ret; \
579 std::copy(a.begin(), a.end(), ret.begin()); \
587 IMPL_COMMA(template<class charge>, std::pair<charge
CO std::
size_t>)
593 template<
class T,
unsigned long L>
594 boost::array<T, L+1>
operator^(boost::array<T, L>
const & a, T
const & b)
596 boost::array<T, L+1> ret;
597 std::copy(a.begin(), a.end(), ret.begin());
602 template<
class T,
unsigned long L>
603 boost::array<T, L+1>
operator^(T
const & a, boost::array<T, L>
const & b)
605 boost::array<T, L+1> ret;
607 for (
int i = 0; i < L; i++)
size_t size(charge a, charge b, Fusion f) const
void load(Archive &ar, const unsigned int version)
bool operator==(Index const &o) const
basis_iterator_< SymmGroup > basis_iterator
std::vector< std::size_t > sizes() const
const_iterator end() const
#define IMPL_COMMA(tpl, type)
const_reverse_iterator rbegin() const
void insert(std::size_t position, std::pair< charge, std::size_t > const &x)
base_t::const_iterator const_iterator
bool lt(std::pair< typename SymmGroup::charge, std::size_t > const &a, std::pair< typename SymmGroup::charge, std::size_t > const &b)
Index< SymmGroup > adjoin(Index< SymmGroup > const &inp)
Index< SymmGroup > operator*(Index< SymmGroup > const &i1, Index< SymmGroup > const &i2)
const_reverse_iterator rend() const
basis_iterator basis_begin() const
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
boost::tuple< charge, std::size_t > element(std::size_t p) const
boost::shared_ptr< std::pair< charge, std::size_t > > operator->() const
std::pair< charge, std::size_t > operator*() const
size_t size(charge pc) const
is_first_equal(typename SymmGroup::charge c)
std::size_t size_of_block(charge c) const
const_iterator begin() const
void save(Archive &ar, const unsigned int version) const
basis_iterator_ & operator++()
basis_iterator_(Index< SymmGroup > const &idx, bool at_end=false)
std::size_t size_of_block(charge c, bool position_check) const
value_type const & operator[](std::size_t p) const
base_t::reverse_iterator reverse_iterator
size_t size(charge a, charge b) const
ProductBasis(Index< SymmGroup > const &a, Index< SymmGroup > const &b)
basis_iterator_< SymmGroup > operator+(basis_iterator_< SymmGroup > it, std::size_t p)
basis_iterator_ operator+(int k)
boost::array< T, 1 > _(T const &a)
SymmGroup::charge get_first(std::pair< typename SymmGroup::charge, std::size_t > const &x)
std::pair< charge, std::size_t > operator-(std::pair< charge, std::size_t > const &p)
bool weak_equal(Index< SymmGroup > const &a, Index< SymmGroup > const &b)
reverse_iterator rbegin()
iterator erase(iterator p)
bool operator()(std::pair< typename SymmGroup::charge, std::size_t > const &x) const
Index & operator=(Index rhs)
bool operator()(std::pair< typename SymmGroup::charge, std::size_t > const &a, std::pair< typename SymmGroup::charge, std::size_t > const &b)
std::size_t position(std::pair< charge, std::size_t > x) const
std::size_t position(charge c) const
value_type & operator[](std::size_t p)
iterator erase(iterator a, iterator b)
std::pair< bool, typename Matrix::value_type > equal(block_matrix< Matrix, SymmGroup > const &reference, block_matrix< Matrix, SymmGroup > const &sample)
base_t::value_type value_type
std::size_t insert(std::pair< charge, std::size_t > const &x)
boost::array< T, L+1 > operator^(boost::array< T, L > const &a, T const &b)
ProductBasis(Index< SymmGroup > const &a, Index< SymmGroup > const &b, Fusion f)
std::size_t get_second(std::pair< typename SymmGroup::charge, std::size_t > const &x)
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
void save(Archive &ar) const
Index< SymmGroup > common_subset(Index< SymmGroup > &a, Index< SymmGroup > &b)
bool operator!=(Index const &o) const
size_t operator()(charge a, charge b) const
base_t::iterator iterator
std::vector< charge > charges() const
std::size_t sum_of_sizes() const
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.
base_t::const_reverse_iterator const_reverse_iterator