//   in_value must either hold an object of value_type or a string that
  //   can be converted to value_type via iostreams.
  void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
  {
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95))
    using boost::put;
#endif

    key_type key = any_cast<key_type>(in_key);
    if (in_value.type() == typeid(value_type)) {
#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
      boost::put(property_map, key, any_cast<value_type>(in_value));
#else
      put(property_map, key, any_cast<value_type>(in_value));
#endif
    } else {
      //  if in_value is an empty string, put a default constructed value_type.
      std::string v = any_cast<std::string>(in_value);
      if (v.empty()) {
#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
        boost::put(property_map, key, value_type());
#else
        put(property_map, key, value_type());
#endif
      } else {
#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
        boost::put(property_map, key, detail::read_value<value_type>(v));
#else
        put(property_map, key, detail::read_value<value_type>(v));
#endif
      }
    }
  }
 void pop() {
   using boost::put;
   if (GRAEHL_D_ARY_TRACK_OUT_OF_HEAP) put(index_in_heap, data[0], (size_type)GRAEHL_D_ARY_HEAP_NULL_INDEX);
   size_type sz = data.size();
   if (sz == 1)
     data.pop_back();
   else {
     put(index_in_heap, data[0] = (MoveableValueRef)data.back(), 0);
     data.pop_back();
     preserve_heap_property_down();
     verify_heap();
   }
 }
  //   in_value must either hold an object of value_type or a string that
  //   can be converted to value_type via iostreams.
  void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
  {
    using boost::put;

    key_type key = any_cast<key_type>(in_key);
    if (in_value.type() == typeid(value_type)) {
      put(property_map_, key, any_cast<value_type>(in_value));
    } else {
      //  if in_value is an empty string, put a default constructed value_type.
      std::string v = any_cast<std::string>(in_value);
      if (v.empty()) {
        put(property_map_, key, value_type());
      } else {
        put(property_map_, key, detail::read_value<value_type>(v));
      }
    }
  }
  void clear() {
#if GRAEHL_D_ARY_TRACK_OUT_OF_HEAP
    using boost::put;
    for (typename Container::iterator i = data.begin(), e = data.end(); i != e; ++i)
      put(index_in_heap, *i, (size_type)GRAEHL_D_ARY_HEAP_NULL_INDEX);
#endif
    data.clear();
  }
  void push(MoveableValueRef v)
#endif
  {
    size_type index = data.size();
    if (index) {
#if GRAEHL_CPP11
      data.emplace_back();
#else
      data.push_back(Value());  // (hoping default construct is cheap, construct-copy inline)
#endif
      preserve_heap_property_up(GRAEHL_D_ARY_FORWARD_REF(v), index, get(distance, v));
      // we don't have to recopy v, or init index_in_heap
      verify_heap();
    } else {
      put(index_in_heap, v, 0);
#if GRAEHL_CPP11
      data.emplace_back(GRAEHL_D_ARY_FORWARD_REF(v));
#else
      data.push_back(v);  // (hoping default construct is cheap, construct-copy inline)
#endif
    }
  }
int test_main(int,char**) {

  // build property maps using associative_property_map

  std::map<std::string, int> string2int;
  std::map<double,std::string> double2string;
  boost::associative_property_map< std::map<std::string, int> >
    int_map(string2int);
  boost::associative_property_map< std::map<double, std::string> >
    dbl_map(double2string);


  // add key-value information
  string2int["one"] = 1;
  string2int["five"] = 5;
  
  double2string[5.3] = "five point three";
  double2string[3.14] = "pi";
 
 
  // build and populate dynamic interface
  boost::dynamic_properties properties;
  properties.property("int",int_map);
  properties.property("double",dbl_map);
  
  using boost::get;
  using boost::put;
  using boost::type;
  // Get tests
  {
    BOOST_CHECK(get("int",properties,std::string("one")) == "1");
#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
    BOOST_CHECK(boost::get<int>("int",properties,std::string("one")) == 1);
#endif
    BOOST_CHECK(get("int",properties,std::string("one"), type<int>()) == 1);
    BOOST_CHECK(get("double",properties,5.3) == "five point three");
  }

  // Put tests
  {
    put("int",properties,std::string("five"),6);
    BOOST_CHECK(get("int",properties,std::string("five")) == "6");
    put("int",properties,std::string("five"),std::string("5"));
#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
    BOOST_CHECK(get<int>("int",properties,std::string("five")) == 5);
#endif
    BOOST_CHECK(get("int",properties,std::string("five"),type<int>()) == 5);
    put("double",properties,3.14,std::string("3.14159"));
    BOOST_CHECK(get("double",properties,3.14) == "3.14159");
    put("double",properties,3.14,std::string("pi"));
#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
    BOOST_CHECK(get<std::string>("double",properties,3.14) == "pi");
#endif
    BOOST_CHECK(get("double",properties,3.14,type<std::string>()) == "pi");
  }

  // Nonexistent property
  {
    try {
      get("nope",properties,3.14);
      BOOST_ERROR("No exception thrown.");
    } catch (boost::dynamic_get_failure&) { }

    try {
      put("nada",properties,3.14,std::string("3.14159"));
      BOOST_ERROR("No exception thrown.");
    } catch (boost::property_not_found&) { }
  }

  // Nonexistent property gets generated
  {
    boost::dynamic_properties props(&string2string_gen);
    put("nada",props,std::string("3.14"),std::string("pi"));
    BOOST_CHECK(get("nada",props,std::string("3.14"))  == "pi");
  }

  return boost::exit_success;
}
 // from bottom of heap tree up, turn that subtree into a heap by adjusting the root down
 // for n=size, array elements indexed by floor(n/2) + 1, floor(n/2) + 2, ... , n are all leaves for the
 // tree, thus each is an one-element heap already
 // warning: this is many fewer instructions but, at some point (when heap doesn't fit in Lx cache) it will
 // become slower than repeated push().
 void set_index_in_heap(std::size_t i = 0) {
   for (std::size_t e = data.size(); i < e; ++i) {
     // cppcheck-suppress unusedScopedObject
     put(index_in_heap, data[i], i);
   }
 }
 void emplace_unsorted(V const& v) {
   Size i = data.size();
   data.push_back(v);
   put(index_in_heap, data.back(), i);
 }
 void emplace_unsorted(Args&&... args) {
   Size i = data.size();
   data.emplace_back(std::forward<Args>(args)...);
   put(index_in_heap, data.back(), i);
 }
 void add_unsorted(V const& v) {
   put(index_in_heap, v, data.size());  // allows contains() and heapify() to function properly
   data.push_back(v);
 }
int main() {
    using boost::get;
    using boost::put;
    using alps::graph::canonical_properties;

    typedef unsigned int lc_type;
    
    typedef boost::property<alps::edge_type_t,alps::type_type> edge_props;

    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,boost::no_property,edge_props> graph_type;
    typedef alps::graph_helper<>::vertex_iterator vertex_iterator;
    typedef alps::graph_helper<>::edge_iterator edge_iterator;

    alps::Parameters parm;
    unsigned int side_length = 40;
    
    std::ifstream in("../../lib/xml/lattices.xml");
    parm["LATTICE"] = "coupled ladders";
    parm["L"] = side_length;

    parm["L"] = side_length;
    alps::graph_helper<> lattice(in,parm);
    
    graph_type lattice_graph(num_vertices(lattice.graph()));
    boost::graph_traits<alps::graph_helper<>::graph_type>::edge_iterator it, et;
    for(boost::tie(it, et) = edges(lattice.graph()); it != et; ++it)
    {
        boost::graph_traits<graph_type>::edge_descriptor  e = add_edge(source(*it, lattice.graph()), target(*it, lattice.graph()), lattice_graph).first;
        if(get(alps::edge_type_t(),lattice.graph(),*it) == 1)
            put(alps::edge_type_t(), lattice_graph, e, 1);
        else
            put(alps::edge_type_t(), lattice_graph, e, 0);
    }
    
    std::vector<std::pair<graph_type,lc_type> > g;
    boost::graph_traits<graph_type>::edge_descriptor e;

    // edge color 0 ...
    // edge color 1 ___
    
    //  0...1
    g.push_back(std::make_pair(graph_type(), 3));
    e = add_edge(0, 1, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //  0___1
    g.push_back(std::make_pair(graph_type(), 1));
    e = add_edge(0, 1, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    
    //  0...1
    //  |   |
    //  2...3
    //
    g.push_back(std::make_pair(graph_type(), 1));
    e = add_edge(0, 1, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(1, 3, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(3, 2, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(2, 0, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    
    //
    //  0...1
    //  :   :
    //  2...3
    //
    g.push_back(std::make_pair(graph_type(), 1));
    e = add_edge(0, 1, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(1, 3, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(3, 2, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(2, 0, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //
    //  0...1
    //  .   |
    //  2___3
    //
    g.push_back(std::make_pair(graph_type(), 0));
    e = add_edge(0, 1, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(1, 3, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(3, 2, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(2, 0, g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);

    //
    //  1...0...2
    //
    g.push_back(std::make_pair(graph_type(),6));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);

    //
    //  1...0___2
    //
    g.push_back(std::make_pair(graph_type(),6));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    
    //
    //  1___0___2
    //
    g.push_back(std::make_pair(graph_type(),0));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    
    //
    //  1___0___2...3
    //
    g.push_back(std::make_pair(graph_type(),0));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(2, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //
    //  3___1...0___2
    //
    g.push_back(std::make_pair(graph_type(),3));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    
    //
    //  3...1___0...2
    //
    g.push_back(std::make_pair(graph_type(),9));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //
    //  3...1...0___2
    //
    g.push_back(std::make_pair(graph_type(),12));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //          4
    //          :
    //  3___1...0___2
    //
    g.push_back(std::make_pair(graph_type(),12));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(0, 4,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //          4
    //          :
    //  3...1...0___2
    //
    g.push_back(std::make_pair(graph_type(),24));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 4,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //      4
    //      :
    //  3...1...0___2
    //
    g.push_back(std::make_pair(graph_type(),6));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(1, 4,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);    
    
    //
    //  3...1...0___2...4
    //
    g.push_back(std::make_pair(graph_type(),36));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(2, 4,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //
    //  3___1...0...2...4
    //
    g.push_back(std::make_pair(graph_type(),24));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(2, 4,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    
    //
    //  3___1...0___2...4
    //
    g.push_back(std::make_pair(graph_type(),14));
    e = add_edge(0, 1,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);
    e = add_edge(0, 2,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(1, 3,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 1);
    e = add_edge(2, 4,g.back().first).first;
    put(alps::edge_type_t(), g.back().first, e, 0);

    int success = 0;
    for(std::vector<std::pair<graph_type, lc_type> >::iterator it= g.begin(); it != g.end(); ++it)
    {
        lc_type lc = alps::graph::lattice_constant(
              it->first
            , lattice_graph
            , lattice.lattice()
            , alps::cell(std::vector<int>(2,side_length/2),lattice.lattice()) //side_length * side_length / 2 + side_length / 2 - 1
        );
        if ( lc != it->second)
        {
            std::cerr<<"ERROR: lattice constant does not match!"<<std::endl;
            std::cerr<<"Graph:"<<std::distance(g.begin(),it)<<" Calculated: "<<lc<<"\tReference: "<<it->second<<std::endl<<std::endl;
            success = -1;
        }
    }
    return success;
}