54 typedef typename MPSMatrix::value_type value_type;
55 typedef std::map<index_type, op_t> op_map;
56 typedef std::map<index_type, std::pair<tag_type, value_type> > op_scale_map;
57 typedef std::vector<boost::tuple<index_type, index_type, tag_type, value_type> > prempo_t;
68 index_type b1, b2, b3;
69 for (b1=0; b1 < mpo1.
row_dim(); ++b1) {
72 std::set<index_type> non_uniform;
73 op_scale_map uniform_ops;
75 row_proxy row1 = mpo1.
row(b1);
76 for (
typename row_proxy::const_iterator it1 = row1.begin(); it1 != row1.end(); ++it1) {
79 row_proxy row2 = mpo2.
row(b2);
80 for (
typename row_proxy::const_iterator it2 = row2.begin(); it2 != row2.end(); ++it2)
83 assert((mpo1.
has(b1, b2) && mpo2.
has(b2, b3)));
86 const_term_descriptor<MPSMatrix, SymmGroup> p1 = mpo1.
at(b1,b2), p2 = mpo2.
at(b2,b3);
89 kron_tag = kron_handler.get_kron_tag(phys_i1, phys_i2, mpo1.
tag_number(b1,b2), mpo2.
tag_number(b2,b3));
91 if (!kron_handler.is_uniform(mpo1.
tag_number(b1,b2)) ||
92 !kron_handler.is_uniform(mpo2.
tag_number(b2,b3)) ||
93 uniform_ops.count(b3) > 0)
95 non_uniform.insert(b3);
98 uniform_ops[b3].first = kron_tag;
99 uniform_ops[b3].second = (p1.scale * p2.scale);
103 tmp_op = kron_handler.get_op(kron_tag);
104 tmp_op *= (p1.scale * p2.scale);
105 out_row[b3] += tmp_op;
109 for (b3 = 0; b3 < mpo2.
col_dim(); ++b3) {
110 if (non_uniform.count(b3) == 0 && uniform_ops.count(b3) == 0)
113 if (non_uniform.count(b3) > 0) {
114 std::pair<tag_type, value_type> scaled_tag;
116 scaled_tag = kron_handler.get_kronecker_table()->checked_register(out_row[b3]);
117 prempo.push_back(boost::make_tuple(b1, b3, scaled_tag.first, scaled_tag.second));
122 prempo.push_back(boost::make_tuple(b1, b3, uniform_ops[b3].first, uniform_ops[b3].second));
144 maquis::cout <<
"TSMPOTensor: " << mpo1.
row_dim() <<
"x" << mpo2.
col_dim() <<
", " << prempo.size()
145 <<
" operators, " << kron_handler.get_kronecker_table()->size() <<
" tags\n";
147 using boost::tuples::get;
159 index_type b1, b2, b3;
160 for (b1=0; b1 < mpo1.
row_dim(); ++b1) {
164 row_proxy row1 = mpo1.
row(b1);
165 for (
typename row_proxy::const_iterator it1 = row1.begin(); it1 != row1.end(); ++it1) {
168 row_proxy row2 = mpo2.
row(b2);
169 for (
typename row_proxy::const_iterator it2 = row2.begin(); it2 != row2.end(); ++it2)
172 assert((mpo1.
has(b1, b2) && mpo2.
has(b2, b3)));
175 const_term_descriptor<MPSMatrix, SymmGroup> p1 = mpo1.
at(b1,b2), p2 = mpo2.
at(b2,b3);
177 op_kron(phys_i1, phys_i2, p1.op, p2.op, product);
178 product *= (p1.scale * p2.scale);
179 out_row[b3] += product;
183 for (
typename op_map::iterator it = out_row.begin(); it != out_row.end(); ++it) {
185 tag_type new_tag = op_table->
register_op(it->second);
186 prempo.push_back(boost::make_tuple(b1, b3, new_tag, 1.0));
190 using boost::tuples::get;
index_type row_dim() const
boost::shared_ptr< OPTable< Matrix, SymmGroup > > get_operator_table()
tag_detail::tag_type tag_type
void remove_empty_blocks(block_matrix< Matrix, SymmGroup > &op)
op_table_ptr get_operator_table() const
tag_type tag_number(index_type left_index, index_type right_index) const
row_proxy row(index_type row_i) const
void op_kron(Index< SymmGroup > const &phys_A, Index< SymmGroup > const &phys_B, block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix1, SymmGroup > const &B, block_matrix< Matrix2, SymmGroup > &C)
MPOTensor_detail::const_term_descriptor< Matrix, SymmGroup > at(index_type left_index, index_type right_index) const
bool has(index_type left_index, index_type right_index) const
boost::shared_ptr< OPTable< Matrix, SymmGroup > > op_table_ptr
boost::numeric::ublas::matrix_column< const CSCMatrix > col_proxy
tag_type register_op(const op_t &op_, tag_detail::operator_kind kind)
index_type col_dim() const