XACC
heterogeneous.hpp
1 /*******************************************************************************
2  * Copyright (c) 2019 UT-Battelle, LLC.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * and Eclipse Distribution License v1.0 which accompanies this
6  * distribution. The Eclipse Public License is available at
7  * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
8  *License is available at https://eclipse.org/org/documents/edl-v10.php
9  *
10  * Contributors:
11  * Alexander J. McCaskey - initial API and implementation
12  *******************************************************************************/
13 #ifndef XACC_HETEROGENEOUS_HPP_
14 #define XACC_HETEROGENEOUS_HPP_
15 
16 #include <map>
17 #include <stdexcept>
18 #include <vector>
19 #include <unordered_map>
20 #include <functional>
21 #include <iostream>
22 #include <experimental/type_traits>
23 
24 // mpark variant
25 #include "variant.hpp"
26 
27 #include "Utils.hpp"
28 #include <complex>
29 #include <any>
30 
31 namespace xacc {
32 
33 class HeterogeneousMap;
34 
35 template <class...> struct is_heterogeneous_map : std::false_type {};
36 
37 template <> struct is_heterogeneous_map<HeterogeneousMap> : std::true_type {};
38 
39 template <class...> struct type_list {};
40 
41 template <class... TYPES> struct visitor_base {
42  using types = xacc::type_list<TYPES...>;
43 };
44 
46 public:
47  HeterogeneousMap() = default;
48  HeterogeneousMap(const HeterogeneousMap &_other) { *this = _other; }
49  HeterogeneousMap(HeterogeneousMap &_other) { *this = _other; }
50 
51  HeterogeneousMap &operator=(const HeterogeneousMap &_other) {
52  clear();
53  items = _other.items;
54  return *this;
55  }
56 
57  template <typename T> void loop_pairs(T value) {
58  insert(value.first, value.second);
59  }
60 
61  template <typename First, typename... Rest>
62  void loop_pairs(First firstValue, Rest... rest) {
63  loop_pairs(firstValue);
64  loop_pairs(rest...);
65  }
66 
67  template <typename... TYPES,
68  typename = std::enable_if_t<!is_heterogeneous_map<
69  std::remove_cv_t<std::remove_reference_t<TYPES>>...>::value>>
70  HeterogeneousMap(TYPES &&... list) {
71  loop_pairs(list...);
72  }
73 
74  template <typename... Ts> void print(std::ostream &os) const {
75  _internal_print_visitor<Ts...> v(os);
76  visit(v);
77  }
78 
79  template <class T> void insert(const std::string key, const T &_t) {
80  if (items.count(key)) {
81  items.at(key) = _t;
82  } else {
83  items.insert({key, _t});
84  }
85  }
86 
87  template <typename T> const T get(const std::string key) const {
88  try {
89  return std::any_cast<T>(items.at(key));
90  } catch (std::exception &e) {
91  XACCLogger::instance()->error("HeterogeneousMap::get() error - Invalid type or key (" + key +
92  ").");
93  }
94  return T();
95  }
96 
97  template <class T> const T get_with_throw(const std::string key) const {
98  return std::any_cast<T>(items.at(key));
99  }
100 
101  bool stringExists(const std::string key) const {
102  if (keyExists<const char *>(key)) {
103  return true;
104  }
105  if (keyExists<std::string>(key)) {
106  return true;
107  }
108  return false;
109  }
110 
111  const std::string getString(const std::string key) const {
112  if (keyExists<const char *>(key)) {
113  return get<const char *>(key);
114  } else if (keyExists<std::string>(key)) {
115  return get<std::string>(key);
116  } else {
117  XACCLogger::instance()->error("No string-like value at provided key (" +
118  key + ").");
119  print_backtrace();
120  }
121  return "";
122  }
123 
124  template <typename T> bool pointerLikeExists(const std::string key) const {
125  if (keyExists<T *>(key)) {
126  return true;
127  } else if (keyExists<std::shared_ptr<T>>(key)) {
128  return true;
129  } else {
130  return false;
131  }
132  }
133  template <typename T> T *getPointerLike(const std::string key) const {
134  if (keyExists<T *>(key)) {
135  return get<T *>(key);
136  } else if (keyExists<std::shared_ptr<T>>(key)) {
137  return get<std::shared_ptr<T>>(key).get();
138  } else {
139  XACCLogger::instance()->error("No pointer-like value at provided key (" +
140  key + ").");
141  print_backtrace();
142  }
143  return nullptr;
144  }
145  void clear() { items.clear(); }
146 
147  template <class T> size_t number_of() const {
148  _internal_number_of_visitor<T> v;
149  visit(v);
150  return v.count;
151  }
152 
153  bool key_exists_any_type(const std::string key) const {
154  return items.count(key);
155  }
156 
157  template <typename T> bool keyExists(const std::string key) const {
158  if (items.count(key)) {
159  // we have the key, make sure it is the right type
160  try {
161  std::any_cast<T>(items.at(key));
162  } catch (std::exception &e) {
163  return false;
164  }
165  return true;
166  }
167  return false;
168  }
169 
170  size_t size() const { return items.size(); }
171 
172  ~HeterogeneousMap() { clear(); }
173 
174  template <class T> void visit(T &&visitor) const {
175  visit_impl(visitor, typename std::decay_t<T>::types{});
176  }
177 
178 private:
179  std::map<std::string, std::any> items;
180 
181  template <typename T>
182  class _internal_number_of_visitor : public visitor_base<T> {
183  public:
184  int count = 0;
185  void operator()(const std::string &key, const T &t) { count++; }
186  };
187 
188  template <typename... Ts>
189  class _internal_print_visitor : public visitor_base<Ts...> {
190  private:
191  std::ostream &ss;
192 
193  public:
194  _internal_print_visitor(std::ostream &s) : ss(s) {}
195 
196  template <typename T> void operator()(const std::string &key, const T &t) {
197  ss << key << ": " << t << "\n";
198  }
199  };
200 
201  template <class T, class HEAD, class... TAIL> struct try_visit {
202  template <class U> static void apply(T &visitor, U &&element) {
203  try {
204  visitor(element.first, std::any_cast<HEAD>(element.second));
205  } catch (...) {
206  try_visit<T, TAIL...>::apply(visitor, element);
207  }
208  }
209  };
210  template <class T, class HEAD> struct try_visit<T, HEAD> {
211  template <class U> static void apply(T &visitor, U &&element) {
212  try {
213  visitor(element.first, std::any_cast<HEAD>(element.second));
214  } catch (...) {
215  }
216  }
217  };
218  template <class T, class... U>
219  void visit_impl(T &&visitor, xacc::type_list<U...>) const {
220  for (auto &&element : items) {
221  try_visit<std::decay_t<T>, U...>::apply(visitor, element);
222  }
223  }
224 };
225 
226 // Make sure these basic types are always instantiatied for HeterogeneousMap
227 template const bool HeterogeneousMap::get<bool>(const std::string key) const;
228 template const int HeterogeneousMap::get<int>(const std::string key) const;
229 template const double
230 HeterogeneousMap::get<double>(const std::string key) const;
231 template const std::vector<std::complex<double>>
232 HeterogeneousMap::get<std::vector<std::complex<double>>>(
233  const std::string key) const;
234 template const std::vector<double>
235 HeterogeneousMap::get<std::vector<double>>(const std::string key) const;
236 template const std::vector<double>
237 HeterogeneousMap::get_with_throw<std::vector<double>>(
238  const std::string key) const;
239 
240 template <typename... Types> class Variant : public mpark::variant<Types...> {
241 
242 private:
243  std::string originalExpression = "";
244 
245  class ToStringVisitor {
246  public:
247  template <typename T> std::string operator()(const T &t) const {
248  std::stringstream ss;
249  ss << t;
250  return ss.str();
251  }
252  };
253 
254  class IsArithmeticVisitor {
255  public:
256  template <typename T> bool operator()(const T &t) const {
257  return std::is_arithmetic<T>::value;
258  }
259  };
260 
261  template <typename To, typename From> class CastVisitor {
262  public:
263  To operator()(const From &t) const { return (To)t; }
264  };
265 
266 public:
267  Variant() : mpark::variant<Types...>() {}
268  template <typename T>
269  Variant(T &element) : mpark::variant<Types...>(element) {}
270  template <typename T>
271  Variant(T &&element) : mpark::variant<Types...>(element) {}
272  Variant(const Variant &element)
273  : mpark::variant<Types...>(element),
274  originalExpression(element.originalExpression) {}
275 
276  template <typename T> T as() const {
277  try {
278  // First off just try to get it
279  return mpark::get<T>(*this);
280  } catch (std::exception &e) {
281  std::stringstream s;
282  s << "InstructionParameter::this->toString() = " << toString() << "\n";
283  s << "This InstructionParameter type id is " << this->which() << "\n";
284  XACCLogger::instance()->error("Cannot cast Variant: " + s.str());
285  print_backtrace();
286  exit(0);
287  }
288  return T();
289  }
290 
291  template <typename T> T as_no_error() const {
292  // First off just try to get it
293  return mpark::get<T>(*this);
294  }
295 
296  int which() const { return this->index(); }
297 
298  bool isNumeric() const {
299  IsArithmeticVisitor v;
300  return mpark::visit(v, *this);
301  }
302  void storeOriginalExpression(std::string expr) { originalExpression = expr; }
303  void storeOriginalExpression() { originalExpression = toString(); }
304  std::string getOriginalExpression() { return originalExpression; }
305  bool isVariable() const {
306  try {
307  mpark::get<std::string>(*this);
308  } catch (std::exception &e) {
309  return false;
310  }
311  return true;
312  }
313 
314  const std::string toString() const {
315  ToStringVisitor vis;
316  return mpark::visit(vis, *this);
317  }
318 
319  bool operator==(const Variant<Types...> &v) const {
320  return v.toString() == toString();
321  }
322 
323  bool operator!=(const Variant<Types...> &v) const { return !operator==(v); }
324 };
325 } // namespace xacc
326 #endif
Definition: Accelerator.hpp:25
Definition: heterogeneous.hpp:41
Definition: heterogeneous.hpp:39
Definition: heterogeneous.hpp:35
Definition: heterogeneous.hpp:45
Definition: heterogeneous.hpp:37
Definition: heterogeneous.hpp:240