Merge branch 'master' of git@git.tuebingen.mpg.de:libdai
[libdai.git] / include / dai / properties.h
1 /* Copyright (C) 2006-2008 Joris Mooij [j dot mooij at science dot ru dot nl]
2 Radboud University Nijmegen, The Netherlands
3
4 This file is part of libDAI.
5
6 libDAI is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 libDAI is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with libDAI; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #ifndef __defined_libdai_properties_h
23 #define __defined_libdai_properties_h
24
25
26 #include <iostream>
27 #include <sstream>
28 #include <boost/any.hpp>
29 #include <map>
30 #include <cassert>
31 #include <typeinfo>
32 #include <dai/exceptions.h>
33
34
35 namespace dai {
36
37
38 typedef std::string PropertyKey;
39 typedef boost::any PropertyValue;
40 typedef std::pair<PropertyKey, PropertyValue> Property;
41
42
43 /// Sends a Property object to an output stream
44 std::ostream& operator<< (std::ostream & os, const Property & p);
45
46
47 /// The PropertySet class represents a set of properties
48 class PropertySet : public std::map<PropertyKey, PropertyValue> {
49 public:
50 /// Gets a property
51 const PropertyValue & Get(const PropertyKey &key) const {
52 PropertySet::const_iterator x = find(key);
53 #ifdef DAI_DEBUG
54 if( x == this->end() )
55 std::cerr << "PropertySet::Get cannot find property " << key << std::endl;
56 #endif
57 assert( x != this->end() );
58 return x->second;
59 }
60
61 /// Sets a property
62 PropertySet & Set(const PropertyKey &key, const PropertyValue &val) { this->operator[](key) = val; return *this; }
63
64 /// Gets a property, casted as ValueType
65 template<typename ValueType>
66 ValueType GetAs(const PropertyKey &key) const {
67 try {
68 return boost::any_cast<ValueType>(Get(key));
69 } catch( const boost::bad_any_cast & ) {
70 std::cerr << "Cannot cast property " << key << " to ";
71 std::cerr << typeid(ValueType).name() << std::endl;
72 return boost::any_cast<ValueType>(Get(key));
73 }
74 }
75
76 /// Converts a property from string to ValueType, if necessary
77 template<typename ValueType>
78 void ConvertTo(const PropertyKey &key) {
79 PropertyValue val = Get(key);
80 if( val.type() != typeid(ValueType) ) {
81 assert( val.type() == typeid(std::string) );
82
83 std::stringstream ss;
84 ss << GetAs<std::string>(key);
85 ValueType result;
86 ss >> result;
87
88 Set(key, result);
89 }
90 }
91
92 /// Converts a property from string to ValueType (if necessary)
93 template<typename ValueType>
94 ValueType getStringAs(const PropertyKey &key) const {
95 PropertyValue val = Get(key);
96 if( val.type() == typeid(std::string) ) {
97 std::stringstream ss;
98 ss << GetAs<std::string>(key);
99 ValueType result;
100 ss >> result;
101 return result;
102 } else if( val.type() == typeid(ValueType) ) {
103 return boost::any_cast<ValueType>(val);
104 } else {
105 DAI_THROW(IMPOSSIBLE_TYPECAST);
106 return ValueType();
107 }
108 }
109
110 /// Converts a property from ValueType to string (if necessary)
111 template<typename ValueType>
112 PropertySet & setAsString(const PropertyKey &key, ValueType &val) {
113 if( val.type() == typeid(std::string) ) {
114 return Set(key, val);
115 } else {
116 std::stringstream ss (std::stringstream::out);
117 ss << val;
118 return Set(key, ss.str());
119 }
120 }
121
122 /// Shorthand for (temporarily) adding properties, e.g. PropertySet p()("method","BP")("verbose",1)("tol",1e-9)
123 PropertySet operator()(const PropertyKey &key, const PropertyValue &val) const { PropertySet copy = *this; return copy.Set(key,val); }
124
125 /// Check if a property with given key exists
126 bool hasKey(const PropertyKey &key) const { PropertySet::const_iterator x = find(key); return (x != this->end()); }
127
128 /// Sends a PropertySet object to an output stream
129 friend std::ostream& operator<< (std::ostream & os, const PropertySet & ps);
130
131 /// Reads a PropertySet object from an input stream
132 friend std::istream& operator >> (std::istream& is, PropertySet & ps);
133 };
134
135
136 } // end of namespace dai
137
138
139 #endif