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
101 typedef std::vector<std::pair<typename SymmGroup::charge, std::size_t> >
data_type;
104 typedef typename SymmGroup::charge
charge;
127 if (pos == data_.size())
129 return (*
this)[pos].second;
140 if (match != data_.end() && (*match).first != c) match = data_.end();
141 return std::distance(data_.begin(), match);
144 std::size_t
position(std::pair<charge, std::size_t> x)
const
146 assert(
has(x.first) );
150 boost::lambda::_1 + boost::lambda::bind(index_detail::get_second<SymmGroup>, boost::lambda::_2)
159 return std::find_if(data_.begin(), data_.end(),
169 std::size_t
insert(std::pair<charge, std::size_t>
const & x)
172 std::size_t d = destination(x.first);
173 data_.insert(data_.begin() + d, x);
177 return data_.size()-1;
183 data_.insert(data_.begin() +
position, x);
189 for (std::size_t k = 0; k < data_.size(); ++k)
200 return !( *
this == o );
205 assert( data_.size() > 0 );
211 std::vector<charge> ret(data_.size());
212 for (std::size_t k = 0; k < data_.size(); ++k) ret[k] = (*
this)[k].first;
216 std::vector<std::size_t>
sizes()
const
218 std::vector<std::size_t> ret(data_.size());
219 for (std::size_t k = 0; k < data_.size(); ++k) ret[k] = (*
this)[k].second;
226 return std::accumulate(data_.begin(), data_.end(), 0, boost::lambda::ret<std::size_t>(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 data_.size(); }
261 swap(a.data_, b.data_);
262 swap(a.sorted_, b.sorted_);
269 void push_back(std::pair<charge, std::size_t>
const & x){
273 std::size_t destination(
charge c)
const
275 return std::find_if(data_.begin(), data_.end(),
276 boost::lambda::bind(index_detail::lt<SymmGroup>,
278 std::make_pair(c, 0))) - data_.begin();
282 #ifdef PYTHON_EXPORTS
283 std::size_t py_insert(wrapped_pair<SymmGroup> p)
285 return data_.insert(p.data_);
289 template <
class Archive>
292 ar[
"Index"] >> data_;
294 template <
class Archive>
297 ar[
"Index"] << data_;
300 friend class boost::serialization::access;
302 template <
class Archive>
303 void load(Archive & ar,
const unsigned int version)
307 template <
class Archive>
308 void save(Archive & ar,
const unsigned int version)
const
313 BOOST_SERIALIZATION_SPLIT_MEMBER()
316 template<
class SymmGroup>
320 typedef typename SymmGroup::charge
charge;
329 template<
class Fusion>
338 template<
class Fusion>
343 keys_vals_.rehash((keys_vals_.size() + a.
size()*b.
size()) / keys_vals_.max_load_factor() + 1);
347 charge pc = f(it1->first, it2->first);
348 keys_vals_[std::make_pair(it1->first, it2->first)] = size_[pc];
350 size_[pc] += it1->second * it2->second;
357 typedef typename boost::unordered_map<std::pair<charge, charge>,
size_t>::const_iterator match_type;
358 match_type match = keys_vals_.find(std::make_pair(a,b));
359 assert( match != keys_vals_.end() );
360 return match->second;
365 assert(size_.count(pc) > 0);
374 template<
class Fusion>
378 assert(size_.count(pc) > 0);
383 mutable boost::unordered_map<charge, size_t> size_;
384 boost::unordered_map<std::pair<charge, charge>,
size_t> keys_vals_;
387 template<
class SymmGroup>
391 typedef typename SymmGroup::charge
charge;
395 , cur_block(idx.begin())
397 , max_i(cur_block->second)
402 return std::make_pair(cur_block->first, cur_i);
405 boost::shared_ptr<std::pair<charge, std::size_t> >
operator->()
const
407 return boost::shared_ptr<std::pair<charge, std::size_t> >(
new std::pair<charge, std::size_t>(cur_block->first, cur_i));
417 if (cur_block != idx_.end()) {
419 max_i = cur_block->second;
436 return cur_block == idx_.end();
442 std::size_t cur_i, max_i;
445 template<
class SymmGroup>
457 #if defined(WIN32) || defined(WIN64)
458 template<
class A,
class B> std::pair<A, B> mypair(A & a, B & b) {
return std::pair<A,B>(a,b); }
462 template<
class SymmGroup>
468 template<
class SymmGroup>
471 typedef typename SymmGroup::charge charge;
474 std::transform(nc.begin(), nc.end(), nc.begin(), std::negate<charge>());
475 std::sort(nc.begin(), nc.end());
477 std::vector<std::size_t> nd(inp.
size()), od = inp.
sizes();
478 for (
unsigned int i = 0; i < nd.size(); ++i)
479 nd[i] = od[std::find(oc.begin(), oc.end(),
483 for (
size_t i=0; i<nc.size(); ++i)
484 #
if not defined(WIN32) && not defined(WIN64)
485 ret.
insert(std::make_pair(nc[i], nd[i]));
487 ret.
insert(mypair(nc[i], nd[i]));
492 template<
class SymmGroup>
493 std::ostream& operator<<(std::ostream& os, Index<SymmGroup>
const & idx)
500 os <<
"( " << it->first <<
": " << it->second <<
" )";
507 template<
class SymmGroup>
511 typedef typename SymmGroup::charge charge;
518 std::size_t ps = it1->second * it2->second;
519 std::size_t match = ret.
position(pdc);
520 if (match < ret.
size())
521 ret[match].second += ps;
523 ret.
insert(std::make_pair(pdc, ps));
529 template<
class SymmGroup>
535 boost::lambda::bind(index_detail::get_first<SymmGroup>, boost::lambda::_1))),
540 boost::lambda::bind(index_detail::get_first<SymmGroup>, boost::lambda::_1))),
545 template<
class charge>
546 std::pair<charge, std::size_t>
operator-(std::pair<charge, std::size_t>
const & p)
548 return std::make_pair(-p.first, p.second);
551 template<
class T> boost::array<T, 1>
_(T
const & a)
553 boost::array<T, 1> r;
558 template<
class T> boost::array<T, 2>
_(T
const & a, T
const & b)
560 boost::array<T, 2> r;
566 #define IMPL_COMMA(tpl, type) \
567 tpl boost::array<type, 2> operator^(type const & a, type const & b) { \
568 boost::array<type, 2> ret; \
573 #define IMPL_COMMA_2(tpl, type) \
574 tpl boost::array<type, L+1> operator^(boost::array<type, L> const & a, type const & b) { \
575 boost::array<type, L+1> ret; \
576 std::copy(a.begin(), a.end(), ret.begin()); \
584 IMPL_COMMA(template<class charge>, std::pair<charge
CO std::
size_t>)
590 template<
class T,
unsigned long L>
591 boost::array<T, L+1>
operator^(boost::array<T, L>
const & a, T
const & b)
593 boost::array<T, L+1> ret;
594 std::copy(a.begin(), a.end(), ret.begin());
599 template<
class T,
unsigned long L>
600 boost::array<T, L+1>
operator^(T
const & a, boost::array<T, L>
const & b)
602 boost::array<T, L+1> ret;
604 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
data_type::const_reverse_iterator const_reverse_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 > common_subset(Index< SymmGroup > &a, Index< SymmGroup > &b)
Index< SymmGroup > adjoin(Index< SymmGroup > const &inp)
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
bool weak_equal(Index< SymmGroup > const &a, Index< SymmGroup > const &b)
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)
std::vector< boost::shared_ptr< Vector > > data_type
friend void swap(Index &a, Index &b)
basis_iterator_ operator+(int k)
SymmGroup::charge get_first(std::pair< typename SymmGroup::charge, std::size_t > const &x)
boost::array< T, 1 > _(T const &a)
reverse_iterator rbegin()
iterator erase(iterator p)
bool operator()(std::pair< typename SymmGroup::charge, std::size_t > const &x) const
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
data_type::const_iterator const_iterator
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)
boost::array< T, L+1 > operator^(boost::array< T, L > const &a, T const &b)
base_t::value_type value_type
std::size_t insert(std::pair< charge, std::size_t > const &x)
basis_iterator_< SymmGroup > operator+(basis_iterator_< SymmGroup > it, std::size_t p)
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)
data_type::reverse_iterator reverse_iterator
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
void save(Archive &ar) const
bool operator!=(Index const &o) const
data_type::value_type value_type
size_t operator()(charge a, charge b) const
data_type::iterator iterator
base_t::iterator iterator
Index< SymmGroup > operator*(Index< SymmGroup > const &i1, Index< SymmGroup > const &i2)
std::pair< charge, std::size_t > operator-(std::pair< charge, std::size_t > const &p)
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