ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
model.hpp
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * ALPS MPS DMRG Project
4  *
5  * Copyright (C) 2013 Institute for Theoretical Physics, ETH Zurich
6  * 2011-2011 by Michele Dolfi <dolfim@phys.ethz.ch>
7  *
8  * This software is part of the ALPS Applications, published under the ALPS
9  * Application License; you can use, redistribute it and/or modify it under
10  * the terms of the license, either version 1 or (at your option) any later
11  * version.
12  *
13  * You should have received a copy of the ALPS Application License along with
14  * the ALPS Applications; see the file LICENSE.txt. If not, the license is also
15  * available from http://alps.comp-phys.org/.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  *****************************************************************************/
26 
27 #ifndef APP_ALPS_MODEL_H
28 #define APP_ALPS_MODEL_H
29 
30 #include "dmrg/models/model.h"
33 
34 #include <alps/parameter.h>
35 #include <alps/lattice.h>
36 #include <alps/model.h>
37 
38 #undef tolower
39 #undef toupper
40 #include <boost/tokenizer.hpp>
41 #include <boost/regex.hpp>
42 #include <boost/container/flat_map.hpp>
43 
44 #include "symm_handler.hpp"
45 
46 namespace detail {
47  inline alps::graph_helper<> const& get_graph(Lattice const& lat_)
48  {
49  alps_lattice const* alattice = static_cast<alps_lattice const*>(lat_.impl().get());
50  return alattice->alps_graph();
51  }
52 }
53 
54 template <class Matrix, class SymmGroup>
55 class ALPSModel : public model_impl<Matrix, SymmGroup>
56 {
58 
59  typedef alps::SiteOperator SiteOperator;
60  typedef alps::BondOperator BondOperator;
61 
62  typedef typename Matrix::value_type value_type;
63  typedef typename maquis::traits::scalar_type<Matrix>::type scalar_type;
64  typedef boost::multi_array<value_type,2> alps_matrix;
65  typedef std::map<std::string, int> qn_map_type;
66 
67  typedef short I;
68  typedef alps::graph_helper<> graph_type;
69 
70  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
71 
72 
73 public:
74  typedef typename base::table_type table_type;
75  typedef typename base::table_ptr table_ptr;
76  typedef typename base::tag_type tag_type;
77 
79  typedef typename alps::expression::Term<value_type> expression_type;
80  typedef ::term_descriptor<expression_type> expression_term;
81  typedef typename base::terms_type terms_type;
82  typedef typename base::op_t op_t;
85 
86  typedef typename base::size_t size_t;
87 
88  typedef std::vector<std::pair<std::vector<op_t>, bool> > meas_operators_type;
89 
90  typedef std::pair<std::string, int> opkey_type;
91  typedef std::map<opkey_type, tag_type> opmap_type;
92  typedef typename opmap_type::const_iterator opmap_const_iterator;
93 
94  typedef typename SymmGroup::charge charge;
95 
96 
97  ALPSModel (Lattice const& lattice_, const alps::Parameters& parms_)
98  : parms(parms_)
99  , raw_lattice(lattice_)
100  , lattice(detail::get_graph(lattice_))
101  , model(lattice, parms, true)
102  , tag_handler(new table_type())
103  {
104  locale_shared i;
105 
106  size_t num_vertex_types = alps::maximum_vertex_type(lattice.graph())+1;
107  symm_basis.reserve(num_vertex_types);
108  basis_descriptors.reserve(num_vertex_types);
109  site_bases.reserve(num_vertex_types);
110 
111  /// Parsing conserved quantum numbers
112  for (int type=0; type<=alps::maximum_vertex_type(lattice.graph()); ++type) {
113  std::set<std::string> type_qn = model.quantum_numbers(type);
114  all_qn.insert(type_qn.begin(), type_qn.end());
115  }
116 
117  if (parms.defined("CONSERVED_QUANTUMNUMBERS")) {
118  boost::char_separator<char> sep(" ,");
119  std::string qn_string = parms["CONSERVED_QUANTUMNUMBERS"];
120  tokenizer qn_tokens(qn_string, sep);
121  int n=0;
122  for (tokenizer::iterator it=qn_tokens.begin(); it != qn_tokens.end(); it++) {
123  if (parms.defined(*it + "_total")) {
124  if (all_qn.find(*it) != all_qn.end())
125  all_conserved_qn.insert( std::make_pair(*it, n++) );
126  else
127  throw std::runtime_error("quantumnumber "+(*it)+" not defined in the model.");
128  }
129  }
130  }
131 
132  /// Load all possible basis
133  for (int type=0; type<=alps::maximum_vertex_type(lattice.graph()); ++type) {
134  basis_descriptors.push_back(model.site_basis(type));
135  site_bases.push_back(alps::site_basis<I>(basis_descriptors[type]));
136  symm_basis.push_back(symmetric_basis_descriptor<SymmGroup>(basis_descriptors[type], all_conserved_qn));
137 
138  op_t ident, fill;
139  for (int i=0; i<symm_basis[type].size(); ++i) {
140  charge c = symm_basis[type].charge(i);
141  size_t bsize = symm_basis[type].block_size(i);
142  // maquis::cout << "Inserting " << c << " for " << site_bases[type][i] << std::endl;
143 
144  if (!ident.has_block(c, c))
145  ident.insert_block(Matrix::identity_matrix(bsize), c, c);
146 
147  int sign = (alps::is_fermionic(basis_descriptors[type], site_bases[type][i])) ? -1 : 1;
148  if (!fill.has_block(c, c))
149  fill.insert_block(Matrix::identity_matrix(bsize), c, c);
150  fill(symm_basis[type].coords(i), symm_basis[type].coords(i)) = sign;
151  }
152  operators[opkey_type("ident", type)] = tag_handler->register_op(ident, tag_detail::bosonic);
153  operators[opkey_type("fill", type)] = tag_handler->register_op(fill, tag_detail::bosonic);
154  }
155 
156 
157  /// site_term loop with cache to avoid recomputing matrices
158  std::vector<std::vector<std::pair<value_type, tag_type> > > site_terms(num_vertex_types);
159  for (graph_type::site_iterator it=lattice.sites().first; it!=lattice.sites().second; ++it) {
160  int p = lattice.vertex_index(*it);
161  int type = lattice.site_type(*it);
162 
163  if (site_terms[type].size() == 0) {
164  typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator> > V;
165  V ops = model.site_term(type).template templated_split<value_type>();
166 
167  for (int n=0; n<ops.size(); ++n) {
168  SiteOperator op = boost::get<1>(ops[n]);
169  opmap_const_iterator match = operators.find(opkey_type(simplify_name(op), type));
170  if (match == operators.end())
171  match = register_operator(op, type, parms);
172  // site_terms[type].push_back( std::make_pair(boost::get<0>(ops[n]).value(), match->second) );
173 
174  expression_term term;
175  term.coeff = boost::get<0>(ops[n]);
176  term.is_fermionic = false;
177  term.push_back( boost::make_tuple(p, match->second) );
178  expression_coeff.insert( std::make_pair(term.coeff, value_type()) );
179  expression_terms.push_back(term);
180  }
181  }
182 
183  // All site terms summed into one
184 // if (site_terms[type].size() > 0) {
185 // opmap_const_iterator match = operators.find(opkey_type("site_terms", type));
186 // if (match == operators.end()) {
187 // op_t op_matrix;
188 // for (int n=0; n<site_terms[type].size(); ++n)
189 // op_matrix += site_terms[type][n].first * tag_handler->get_op(site_terms[type][n].second);
190 // tag_type mytag = tag_handler->register_op(op_matrix, tag_detail::bosonic);
191 // boost::tie(match, boost::tuples::ignore) = operators.insert( std::make_pair(opkey_type("site_terms", type), mytag) );
192 // }
193 //
194 // term_descriptor term;
195 // term.coeff = 1.;
196 // term.is_fermionic = false;
197 // term.push_back( boost::make_tuple(p, match->second) );
198 // this->terms_.push_back(term);
199 // }
200 
201 
202  }
203 
204  /// bond terms loop
205  for (graph_type::bond_iterator it=lattice.bonds().first; it!=lattice.bonds().second; ++it) {
206  int p_s = lattice.source(*it);
207  int p_t = lattice.target(*it);
208  int type = lattice.bond_type(*it);
209  int type_s = lattice.site_type(lattice.source(*it));
210  int type_t = lattice.site_type(lattice.target(*it));
211 
212  bool wrap_pbc = boost::get(alps::boundary_crossing_t(), lattice.graph(), *it);
213 
214  BondOperator bondop = model.bond_term(type);
215 
216  typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator,alps::SiteOperator > > V;
217  alps::SiteBasisDescriptor<I> const& b1 = basis_descriptors[type_s];
218  alps::SiteBasisDescriptor<I> const& b2 = basis_descriptors[type_t];
219 
220 
221  V ops = bondop.template templated_split<value_type>(b1,b2);
222  for (typename V::iterator tit=ops.begin(); tit!=ops.end();++tit) {
223  SiteOperator op1 = boost::get<1>(*tit);
224  SiteOperator op2 = boost::get<2>(*tit);
225 
226  opmap_const_iterator match1 = operators.find(opkey_type(simplify_name(op1), type_s));
227  if (match1 == operators.end())
228  match1 = register_operator(op1, type_s, parms);
229  opmap_const_iterator match2 = operators.find(opkey_type(simplify_name(op2), type_t));
230  if (match2 == operators.end())
231  match2 = register_operator(op2, type_t, parms);
232 
233  bool with_sign = fermionic(b1, op1, b2, op2);
234 
235  expression_term term;
236  term.coeff = boost::get<0>(*tit);
237  term.is_fermionic = with_sign;
238 
239  {
240  tag_type mytag = match1->second;
241  if (with_sign && !wrap_pbc) {
242  // Note inverse notation because of notation in operator.
243  std::pair<tag_type, value_type> ptag = tag_handler->get_product_tag(operators[opkey_type("fill",type_s)],
244  mytag);
245  mytag = ptag.first;
246  term.coeff *= ptag.second;
247  }
248  if (with_sign && wrap_pbc)
249  term.coeff *= value_type(-1.);
250  term.push_back( boost::make_tuple(p_s, mytag) );
251  }
252  {
253  tag_type mytag = match2->second;
254  if (with_sign && wrap_pbc) {
255  // Note inverse notation because of notation in operator.
256  std::pair<tag_type, value_type> ptag = tag_handler->get_product_tag(operators[opkey_type("fill",type_t)],
257  mytag);
258  mytag = ptag.first;
259  term.coeff *= ptag.second;
260  }
261  term.push_back( boost::make_tuple(p_t, mytag) );
262  }
263 
264  expression_coeff.insert( std::make_pair(term.coeff, value_type()) );
265  expression_terms.push_back(term);
266  }
267  }
268 
269  generate_terms();
270  }
271 
272  void update(BaseParameters const& p)
273  {
274  parms << p;
275  generate_terms();
276  }
277 
278  Index<SymmGroup> const& phys_dim(size_t type) const
279  {
280  return symm_basis[type].phys_dim();
281  }
282 
283  typename SymmGroup::charge total_quantum_numbers(BaseParameters& parms_) const
284  {
285  return init_charge<SymmGroup>(parms_, all_conserved_qn);
286  }
287 
288  tag_type identity_matrix_tag(size_t type) const
289  {
290  return operators[opkey_type("ident", type)]; // TODO: avoid using map here
291  }
292 
293  tag_type filling_matrix_tag(size_t type) const
294  {
295  return operators[opkey_type("fill", type)]; // TODO: avoid using map here
296  }
297 
298  tag_type get_operator_tag(std::string const & name, size_t type) const
299  {
300  if (name == "id" || name == "ident" || name == "identity") {
301  return operators[opkey_type("ident", type)];
302  } else {
303  opmap_const_iterator match = operators.find(opkey_type(name, type));
304  if (match == operators.end()) {
305  SiteOperator op = make_site_term(name, parms);
306  match = register_operator(op, type, parms);
307  }
308  return match->second;
309  }
310  }
311 
313  {
314  return tag_handler;
315  }
316 
317  initializer_ptr initializer(Lattice const& lat, BaseParameters & p_) const;
318  boost::ptr_vector<measurement<Matrix, SymmGroup> > measurements () const;
319 
320 private:
321 
322  template <class SiteOp>
323  std::string simplify_name(const SiteOp &op) const
324  {
325  std::string term = op.term();
326  std::string arg = "("+op.site()+")";
327  boost::algorithm::replace_all(term,arg,"");
328  return term;
329  }
330 
331  bool fermionic (alps::SiteBasisDescriptor<I> const& b1, SiteOperator const& op1,
332  alps::SiteBasisDescriptor<I> const& b2, SiteOperator const& op2) const
333  {
334  return b1.is_fermionic(simplify_name(op1)) && b2.is_fermionic(simplify_name(op2));
335  }
336 
337  inline op_t convert_matrix (const alps_matrix& m, int type) const
338  {
339  op_t newm;
340  for (int i=0; i<m.shape()[0]; ++i) {
341  for (int j=0; j<m.shape()[1]; ++j) {
342  if (m[i][j] != 0.) {
343  charge c_i = symm_basis[type].charge(i);
344  size_t bsize_i = symm_basis[type].block_size(i);
345  charge c_j = symm_basis[type].charge(j);
346  size_t bsize_j = symm_basis[type].block_size(j);
347 
348  if (!newm.has_block(c_i, c_j))
349  newm.insert_block(Matrix(bsize_i, bsize_j, 0), c_i, c_j);
350  // Notation: going from state i to state j
351  newm(symm_basis[type].coords(i), symm_basis[type].coords(j)) = m[i][j];
352  }
353  }
354  }
355  return newm;
356  }
357 
358  alps::SiteOperator make_site_term(std::string x, alps::Parameters const & parms) const
359  {
360  if (x[x.size()-1]!=')')
361  x += "(i)";
362  alps::SiteOperator op(x,"i");
363  model.substitute_operators(op, parms);
364  return op;
365  }
366 
367  opmap_const_iterator register_operator(SiteOperator const& op, int type, alps::Parameters const& p) const
368  {
369  alps::SiteBasisDescriptor<I> const& b = basis_descriptors[type];
370  alps_matrix m = alps::get_matrix(value_type(), op, b, p, true);
371  tag_detail::operator_kind kind = b.is_fermionic(simplify_name(op)) ? tag_detail::fermionic : tag_detail::bosonic;
372  tag_type mytag = tag_handler->register_op(convert_matrix(m, type), kind);
373 
374  opmap_const_iterator match;
375  boost::tie(match, boost::tuples::ignore) = operators.insert( std::make_pair(opkey_type(simplify_name(op), type), mytag) );
376  return match;
377  }
378 
379  std::pair<meas_operators_type, short> operators_for_meas(std::string const& ops, bool repeat_one=false) const
380  {
382 
383  int ntypes = alps::maximum_vertex_type(lattice.graph())+1;
384  int f_ops = 0;
385 
386  boost::char_separator<char> sep(":");
387  tokenizer corr_tokens(ops, sep);
388  std::vector<std::string> opnames;
389  short op_types = 0;
390  /// get list of all local operators
391  for (tokenizer::iterator it=corr_tokens.begin(); it != corr_tokens.end(); it++)
392  {
393  if (model.has_bond_operator(*it)) {
394  /// extract all site operators in the bond term
395  BondOperator bondop = model.get_bond_operator(*it);
396 
397  typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator,alps::SiteOperator > > V;
398 
399  alps::SiteBasisDescriptor<I> const& b1 = basis_descriptors[0];
400  alps::SiteBasisDescriptor<I> const& b2 = basis_descriptors[0];
401 
402  V bond_terms = bondop.template templated_split<value_type>(b1,b2);
403  if (std::distance(bond_terms.begin(), bond_terms.end()) != 1) throw std::runtime_error("Can only measure BONDOPERATOR with a single term.");
404 
405  SiteOperator op1 = boost::get<1>(*bond_terms.begin());
406  SiteOperator op2 = boost::get<2>(*bond_terms.begin());
407 
408  opnames.push_back(simplify_name(op1));
409  opnames.push_back(simplify_name(op2));
410  op_types |= 1<<1; // flag that at least one bond term is in the list
411  } else {
412  opnames.push_back(*it);
413  op_types |= 1<<0; // flag that at least one site term is in the list
414  }
415  }
416 
417  if (op_types == 3) throw std::runtime_error("Can only have either site operators or bond operators.");
418 
419 
420  /// get matrices for the operators
421  for (std::vector<std::string>::const_iterator it2 = opnames.begin(); it2 != opnames.end(); ++it2)
422  {
423  enum {uknown, bosonic, fermionic} kind = uknown;
424  std::vector<op_t> tops(ntypes);
425  for (int type=0; type<ntypes; ++type) {
426  alps::SiteBasisDescriptor<I> const& b = basis_descriptors[type];
427  if (b.has_operator(*it2)) {
428  SiteOperator op = make_site_term(*it2, parms);
429  bool is_ferm = b.is_fermionic(simplify_name(op));
430  if (kind == uknown)
431  kind = is_ferm ? fermionic : bosonic;
432  else if ((is_ferm && kind==bosonic) || (!is_ferm && kind==fermionic))
433  throw std::runtime_error("Model is inconsitent. On some site the operator " + *it2 + "fermionic, on others is bosonic.");
434  tops[type] = this->get_operator(*it2, type);
435  }
436  }
437 
438  if (kind == fermionic) ++f_ops;
439  ret.push_back( std::make_pair(tops, (kind==fermionic)) );
440  }
441 
442  /// repeat last site term in case only one in the input
443  if (repeat_one && op_types == 1 && ret.size() == 1) {
444  ret.push_back(ret[0]);
445  if (ret[1].second) ++f_ops;
446  }
447  /// repeat last bond term (=two site terms) in case only one in the input
448  if (repeat_one && op_types == 2 && ret.size() == 2) {
449  ret.push_back(ret[0]);
450  ret.push_back(ret[1]);
451  if (ret[2].second) ++f_ops;
452  if (ret[3].second) ++f_ops;
453  }
454 
455  if (f_ops % 2 != 0)
456  throw std::runtime_error("Number of fermionic operators has to be even.");
457 
458  return std::make_pair(ret, op_types);
459  }
460 
461  void generate_terms()
462  {
463  this->terms_.clear();
464  this->terms_.reserve(expression_terms.size());
465 
466  alps::Parameters parms_with_defaults(parms);
467  parms_with_defaults.copy_undefined(model.model().default_parameters());
468 
469  typedef typename boost::container::flat_map<expression_type, value_type>::iterator coeff_iterator;
470  for(coeff_iterator it = expression_coeff.begin(); it != expression_coeff.end(); ++it)
471  it->second = alps::evaluate<value_type>(it->first, parms_with_defaults);
472 
473  typedef typename std::vector<expression_term>::const_iterator terms_iterator;
474  for(terms_iterator it = expression_terms.begin(); it != expression_terms.end(); ++it) {
475  value_type const& val = expression_coeff[it->coeff];
476  if ( alps::numeric::is_nonzero(val) ) {
477  value_term term;
478  term.is_fermionic = it->is_fermionic;
479  term.insert(term.end(), it->begin(), it->end());
480  term.coeff = val;
481  this->terms_.push_back(term);
482  }
483  }
484  }
485 
486 
487  alps::Parameters parms;
488  Lattice raw_lattice;
489  graph_type const& lattice;
490  alps::model_helper<I> model;
491  mutable table_ptr tag_handler;
492 
493  std::set<std::string> all_qn;
494  qn_map_type all_conserved_qn;
495  std::vector<symmetric_basis_descriptor<SymmGroup> > symm_basis;
496  std::vector<alps::SiteBasisDescriptor<I> > basis_descriptors;
497  std::vector<alps::site_basis<I> > site_bases;
498 
499  mutable opmap_type operators; // key=<name,type>
500  std::vector<expression_term> expression_terms;
501  boost::container::flat_map<expression_type, value_type> expression_coeff;
502 };
503 
504 // Initial states
505 template <class Matrix, class SymmGroup>
507 {
508  if ( p_["init_state"] == "local_quantumnumbers" ) {
509  int max_site_type = 0;
510  std::vector<int> site_types(lat.size(), 0);
511  for (int p = 0; p < lat.size(); ++p) {
512  site_types[p] = lat.get_prop<int>("type", p);
513  max_site_type = std::max(site_types[p], max_site_type);
514  }
515 
516  std::cout << "site_types: ";
517  std::copy(site_types.begin(), site_types.end(), std::ostream_iterator<int>(std::cout, " "));
518  std::cout << std::endl;
519 
520  std::vector<Index<SymmGroup> > phys_bases(symm_basis.size());
521  for (int type = 0; type < phys_bases.size(); ++type) {
522  phys_bases[type] = symm_basis[type].phys_dim();
523  maquis::cout << "phys["<< type <<"]: " << phys_bases[type] << std::endl;
524  }
525 
526  // TODO: avoid QN of size=1
527  std::map<std::string, std::vector<double> > initial_local_charges;
528  for(std::set<std::string>::const_iterator it = all_qn.begin(); it != all_qn.end(); ++it) {
529  const std::string pname = "initial_local_" + *it;
530  if (!p_.defined(pname))
531  throw std::runtime_error(pname + " required for local_quantumnumbers initial state.");
532  initial_local_charges[*it] = p_[pname].as<std::vector<double> >();
533  }
534 
535  std::vector<boost::tuple<charge, size_t> > state(lat.size());
536  for (size_t p=0; p<lat.size(); ++p) {
537  const int type = site_types[p];
538  alps::SiteBasisDescriptor<I> const& b = basis_descriptors[type];
539  alps::site_state<I> local_state;
540  for (size_t i=0; i<b.size(); ++i)
541  local_state.push_back( initial_local_charges[b[i].name()][p] );
542  state[p] = symm_basis[type].coords(site_bases[type].index(local_state));
543  }
544 
545  return initializer_ptr(new basis_mps_init_generic<Matrix, SymmGroup>(state, phys_bases, this->total_quantum_numbers(p_), site_types));
546  } else {
547  return base::initializer(lat, p_);
548  }
549 }
550 
551 
552 // Loading Measurements
553 template <class Matrix, class SymmGroup>
554 boost::ptr_vector<measurement<Matrix, SymmGroup> >
556 {
557  boost::ptr_vector<measurement<Matrix, SymmGroup> > meas;
558 
559  int ntypes = alps::maximum_vertex_type(lattice.graph())+1;
560 
561  std::vector<op_t> identitities(ntypes), fillings(ntypes);
562  for (int type=0; type<ntypes; ++type) {
563  identitities[type] = this->identity_matrix(type);
564  fillings[type] = this->filling_matrix(type);
565  }
566 
567  {
568  boost::regex average_expr("^MEASURE_AVERAGE\\[(.*)]$");
569  boost::regex locale_expr("^MEASURE_LOCAL\\[(.*)]$");
570  boost::smatch what;
571  for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
572  std::string lhs = it->key();
573  std::string obsname;
574 
575  enum {not_found, is_local, is_average} meas_found = not_found;
576  if (boost::regex_match(lhs, what, average_expr)) {
577  meas_found = is_average;
578  obsname = what.str(1);
579  }
580  if (boost::regex_match(lhs, what, locale_expr)) {
581  meas_found = is_local;
582  obsname = what.str(1);
583  }
584 
585  if (meas_found != not_found) {
586 
587  if (model.has_bond_operator(it->value())) {
588  BondOperator bondop = model.get_bond_operator(it->value());
589 
590  typedef std::vector<op_t> op_vec;
591  typedef std::vector<std::pair<op_vec, bool> > bond_element;
592  typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator,alps::SiteOperator > > V;
593 
594  std::vector<op_t> tops1(ntypes), tops2(ntypes);
595 
596  std::vector<bond_element> operators;
597  std::set<int> used1, used2;
598  for (int type1=0; type1<ntypes; ++type1)
599  for (int type2=0; type2<ntypes; ++type2) {
600  if (used1.find(type1) != used1.end() && used2.find(type2) != used2.end())
601  continue;
602 
603  alps::SiteBasisDescriptor<I> const& b1 = basis_descriptors[type1];
604  alps::SiteBasisDescriptor<I> const& b2 = basis_descriptors[type2];
605 
606  V ops = bondop.template templated_split<value_type>(b1,b2);
607  if (operators.size() < ops.size()) operators.resize(ops.size(), bond_element(2, std::make_pair(op_vec(ntypes), false)) );
608  int num_done = 0;
609  for (typename V::iterator tit=ops.begin(); tit!=ops.end();++tit) {
610  SiteOperator op1 = boost::get<1>(*tit);
611  SiteOperator op2 = boost::get<2>(*tit);
612 
613  if (!b1.has_operator(simplify_name(op1)) || !b2.has_operator(simplify_name(op2)))
614  continue;
615 
616  unsigned ii = std::distance(ops.begin(), tit);
617  {
618  operators[ii][0].second = b1.is_fermionic(simplify_name(op1));
619  op_t & m = operators[ii][0].first[type1];
620  if (operators[ii][0].second)
621  gemm(fillings[type1], this->get_operator(simplify_name(op1), type1), m); // Note inverse notation because of notation in operator.
622  else
623  m = this->get_operator(simplify_name(op1), type1);
624  m = boost::get<0>(*tit).value() * m;
625  }
626  {
627  operators[ii][1].second = b2.is_fermionic(simplify_name(op2));
628  op_t & m = operators[ii][1].first[type2];
629  m = this->get_operator(simplify_name(op2), type2);
630  }
631 
632  num_done += 1;
633  }
634 
635  if (num_done == ops.size()) { used1.insert(type1); used2.insert(type2); }
636  }
637 
638  if (meas_found == is_average)
639  meas.push_back( new measurements::average<Matrix, SymmGroup>(obsname, raw_lattice, identitities, fillings, operators) );
640  else
641  meas.push_back( new measurements::local<Matrix, SymmGroup>(obsname, raw_lattice, identitities, fillings, operators) );
642  } else {
643  std::vector<op_t> tops(ntypes);
644  for (int type=0; type<ntypes; ++type) {
645  alps::SiteBasisDescriptor<I> const& b = basis_descriptors[type];
646  if (b.has_operator(it->value())) {
647  SiteOperator op = make_site_term(it->value(), parms);
648  if (b.is_fermionic(simplify_name(op)))
649  throw std::runtime_error("Cannot measure local fermionic operators.");
650 
651  tops[type] = this->get_operator(it->value(), type);
652  }
653  }
654  if (meas_found == is_average)
655  meas.push_back( new measurements::average<Matrix, SymmGroup>(obsname, raw_lattice, identitities, fillings, tops) );
656  else
657  meas.push_back( new measurements::local<Matrix, SymmGroup>(obsname, raw_lattice, identitities, fillings, tops) );
658  }
659  }
660  }
661  }
662 
663  { // Example: MEASURE_LOCAL_AT[Custom correlation] = "bdag:b|(1,2),(3,4),(5,6)"
664  boost::regex expression("^MEASURE_LOCAL_AT\\[(.*)]$");
665  boost::smatch what;
666  for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
667  std::string lhs = it->key();
668  std::string value = it->value();
669  if (boost::regex_match(lhs, what, expression)) {
670  int f_ops = 0;
671 
672  std::string name = what.str(1);
673 
674  boost::char_separator<char> part_sep("|");
675  tokenizer part_tokens(value, part_sep);
676  std::vector<std::string> parts;
677  std::copy( part_tokens.begin(), part_tokens.end(), std::back_inserter(parts) );
678 
679  if (parts.size() != 2)
680  throw std::runtime_error("MEASURE_LOCAL_AT must contain a `|` delimiter.");
681 
682  /// parse operators
683  meas_operators_type operators;
684  boost::tie(operators, boost::tuples::ignore) = operators_for_meas(parts[0], false);
685 
686  /// parse positions
687  std::vector<std::vector<std::size_t> > positions;
688  boost::regex pos_re("\\(([^(^)]*)\\)");
689  boost::sregex_token_iterator it_pos(parts[1].begin(), parts[1].end(), pos_re, 1);
690  boost::sregex_token_iterator it_pos_end;
691  for (; it_pos != it_pos_end; ++it_pos)
692  {
693  boost::char_separator<char> int_sep(", ");
694  std::string raw = *it_pos;
695  tokenizer int_tokens(raw, int_sep);
696 
697  std::vector<std::size_t> pos;
698  BOOST_FOREACH(std::string t, int_tokens) {
699  pos.push_back(boost::lexical_cast<std::size_t, std::string>(t));
700  }
701  positions.push_back(pos);
702  }
703  if (f_ops % 2 != 0)
704  throw std::runtime_error("Number of fermionic operators has to be even.");
705 
706  meas.push_back( new measurements::local_at<Matrix, SymmGroup>(name, raw_lattice, positions, identitities, fillings, operators) );
707  }
708  }
709  }
710 
711  {
712  boost::regex expression("^MEASURE_MPS_BONDS\\[(.*)]$");
713  boost::smatch what;
714  for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
715  std::string lhs = it->key();
716  std::string value;
717 
718  if (boost::regex_match(lhs, what, expression)) {
719  throw std::runtime_error("MEASURE_MPS_BONDS not yet implemented in new version.");
720 // mterm_t term;
721 // term.name = what.str(1);
722 // term.type = mterm_t::MPSBonds;
723 //
724 // fill_meas_with_operators(term, it->value(), true);
725 // meas.add_term(term);
726  }
727  }
728  }
729 
730  {
731  boost::regex expression("^MEASURE_CORRELATIONS\\[(.*)]$");
732  boost::regex expression_half("^MEASURE_HALF_CORRELATIONS\\[(.*)]$");
733  boost::regex expression_nn("^MEASURE_NN_CORRELATIONS\\[(.*)]$");
734  boost::regex expression_halfnn("^MEASURE_HALF_NN_CORRELATIONS\\[(.*)]$");
735  boost::smatch what;
736  for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
737  std::string lhs = it->key();
738 
739  std::string name, value;
740  bool half_only=true, nearest_neighbors_only=false;
741  if (boost::regex_match(lhs, what, expression)) {
742  value = it->value();
743  name = what.str(1);
744  half_only = false;
745  nearest_neighbors_only = false;
746  }
747  if (boost::regex_match(lhs, what, expression_half)) {
748  value = it->value();
749  name = what.str(1);
750  half_only = true;
751  nearest_neighbors_only = false;
752  }
753  if (boost::regex_match(lhs, what, expression_nn)) {
754  value = it->value();
755  name = what.str(1);
756  half_only = false;
757  nearest_neighbors_only = true;
758  }
759  if (boost::regex_match(lhs, what, expression_halfnn)) {
760  value = it->value();
761  name = what.str(1);
762  half_only = true;
763  nearest_neighbors_only = true;
764  }
765  if (!name.empty()) {
766  /// split op1:op2:...@p1,p2,p3,... into {op1:op2:...}, {p1,p2,p3,...}
767  std::vector<std::string> value_split;
768  boost::split( value_split, value, boost::is_any_of("@"));
769 
770  meas_operators_type operators;
771  short ops_type;
772  boost::tie(operators, ops_type) = operators_for_meas(value_split[0], true);
773 
774  if (ops_type == 2) nearest_neighbors_only = true;
775 
776  /// parse positions p1,p2,p3,... (or `space`)
777  std::vector<std::size_t> positions;
778  if (value_split.size() > 1) {
779  boost::char_separator<char> pos_sep(", ");
780  tokenizer pos_tokens(value_split[1], pos_sep);
781  BOOST_FOREACH(std::string t, pos_tokens) {
782  positions.push_back(boost::lexical_cast<std::size_t, std::string>(t));
783  }
784  }
785 
786  meas.push_back( new measurements::correlations<Matrix, SymmGroup>(name, raw_lattice, identitities, fillings, operators,
787  half_only, nearest_neighbors_only,
788  positions) );
789  }
790  }
791  }
792 
793 
794  return meas;
795 }
796 
797 #endif
virtual op_t const & get_operator(std::string const &name, size_t type) const
Definition: model.h:77
base::op_t op_t
Definition: model.hpp:82
std::size_t size_t
Definition: model.h:60
boost::ptr_vector< measurement< Matrix, SymmGroup > > measurements_type
Definition: model.h:58
terms_type terms_
Definition: model.h:85
T::value_type type
Definition: traits.hpp:8
alps::graph_helper const & get_graph(Lattice const &lat_)
Definition: model.hpp:47
table_ptr operators_table() const
Definition: model.hpp:312
boost::ptr_vector< measurement< Matrix, SymmGroup > > measurements() const
Definition: model.hpp:555
definition of Model base class
::term_descriptor< expression_type > expression_term
Definition: model.hpp:80
base::table_type table_type
Definition: model.hpp:74
impl_ptr impl() const
Definition: lattice.h:98
SymmGroup::charge charge
Definition: model.hpp:94
block_matrix< Matrix, SymmGroup > identity_matrix(Index< SymmGroup > const &size)
size_type insert_block(Matrix const &, charge, charge)
tag_type identity_matrix_tag(size_t type) const
Definition: model.hpp:288
boost::shared_ptr< table_type > table_ptr
Definition: model.h:52
SymmGroup::charge total_quantum_numbers(BaseParameters &parms_) const
Definition: model.hpp:283
initializer_ptr initializer(Lattice const &lat, BaseParameters &p_) const
Definition: model.hpp:506
table_type::tag_type tag_type
Definition: model.h:53
base type for all models
Definition: model.h:47
std::vector< term_descriptor > terms_type
Definition: model.h:56
std::pair< std::string, int > opkey_type
Definition: model.hpp:90
ALPSModel(Lattice const &lattice_, const alps::Parameters &parms_)
Definition: model.hpp:97
base::terms_type terms_type
Definition: model.hpp:81
std::map< opkey_type, tag_type > opmap_type
Definition: model.hpp:91
tag_type get_operator_tag(std::string const &name, size_t type) const
Definition: model.hpp:298
Index< SymmGroup > const & phys_dim(size_t type) const
Definition: model.hpp:278
void update(BaseParameters const &p)
Definition: model.hpp:272
std::size_t locale_shared
base::term_descriptor value_term
Definition: model.hpp:78
opmap_type::const_iterator opmap_const_iterator
Definition: model.hpp:92
base::initializer_ptr initializer_ptr
Definition: model.hpp:84
const graph_type & alps_graph() const
Definition: lattice.hpp:114
base::tag_type tag_type
Definition: model.hpp:76
T get_prop(std::string property, pos_t site) const
Definition: lattice.h:103
::term_descriptor< typename Matrix::value_type > term_descriptor
Definition: model.h:55
bool has_block(charge r, charge c) const
alps::expression::Term< value_type > expression_type
Definition: model.hpp:79
base::table_ptr table_ptr
Definition: model.hpp:75
std::vector< std::pair< std::vector< op_t >, bool > > meas_operators_type
Definition: model.hpp:88
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
boost::shared_ptr< mps_initializer< Matrix, SymmGroup > > initializer_ptr
Definition: model.h:49
tag_type filling_matrix_tag(size_t type) const
Definition: model.hpp:293
base::size_t size_t
Definition: model.hpp:86
pimpl resolved Lattice
Definition: lattice.h:84
pos_t size() const
Definition: lattice.h:115
base::measurements_type measurements_type
Definition: model.hpp:83
include all Measurements