Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Simulators/Core/Configuration.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#ifndef _SIMULATOR_CONFIGURATION_H_
13#define _SIMULATOR_CONFIGURATION_H_
14
15#include <stdexcept>
16#include <string>
17#include <unordered_map>
18
19#include "../Interfaces/State.h"
21#include <charconv>
22#include <stdexcept>
23
24namespace Simulators
25{
26
28{
29 public:
35 Configuration() = default;
36
42 virtual ~Configuration() = default;
43
49 Configuration(const Configuration &) = default;
50
57
64
71
80 static int ParseGpuDevice(const std::string &value)
81 {
82 int device = -1;
83 const auto result = std::from_chars(value.data(), value.data() + value.size(), device);
84 if (result.ec != std::errc() || result.ptr != value.data() + value.size() || device < 0)
85 throw std::invalid_argument("gpu_device must be a nonnegative integer");
86 return device;
87 }
88
89 // Keep mutually exclusive GPU SVD flags consistent before they are replayed
90 // from an unordered map into a new simulator (including network clones/jobs).
91 static std::string GpuSvdSettingGroup(const std::string &key)
92 {
93 for (const char *group : {"matrix_product_state_use_gesvd", "matrix_product_operator_use_gesvd", "tensor_network_use_gesvd"})
94 {
95 const size_t length = std::char_traits<char>::length(group);
96 if (key == group)
97 return group;
98 if (key.size() == length + 1 && key.compare(0, length, group) == 0 && (key.back() == 'j' || key.back() == 'p' || key.back() == 'r'))
99 return group;
100 }
101 return {};
102 }
103
104 static bool ParseGpuSvdFlag(const std::string &value)
105 {
106 if (value == "true" || value == "1")
107 return true;
108 if (value == "false" || value == "0")
109 return false;
110 throw std::invalid_argument("GPU SVD flags must be true, false, 1 or 0");
111 }
112
113 static bool ParsePrecision(const std::string &key, const std::string &value)
114 {
115 if (key == "precision")
116 {
117 if (value == "double")
118 return true;
119 if (value == "single")
120 return false;
121 throw std::invalid_argument("precision must be single or double");
122 }
123 if (value == "true" || value == "1")
124 return true;
125 if (value == "false" || value == "0")
126 return false;
127 throw std::invalid_argument("use_double_precision must be true, false, 1 or 0");
128 }
129
130 void SetConfiguration(const std::string &key, const std::string &value)
131 {
132 if (key == RoutingConfig::kStrategy)
136 else if (key == RoutingConfig::kTruncationWeight)
138 if (key == "precision" || key == "use_double_precision")
139 {
140 const bool useDouble = ParsePrecision(key, value);
141 configMap["precision"] = useDouble ? "double" : "single";
142 configMap["use_double_precision"] = useDouble ? "1" : "0";
143 return;
144 }
145 if (key == "gpu_device")
146 ParseGpuDevice(value);
147 const auto svdGroup = GpuSvdSettingGroup(key);
148 if (!svdGroup.empty())
149 {
150 const bool enabled = ParseGpuSvdFlag(value);
151 configMap[key] = enabled ? "true" : "false";
152 if (enabled)
153 {
154 for (const char *algorithm : {"", "j", "p", "r"})
155 {
156 const auto otherKey = svdGroup + algorithm;
157 const auto other = configMap.find(otherKey);
158 // Do not introduce unused optional settings on older plugins, or
159 // invalidate iterators while an existing map is being replayed.
160 if (otherKey != key && other != configMap.end())
161 other->second = "false";
162 }
163 }
164 return;
165 }
166 if ((key == "matrix_product_state_truncation_mode" || key == "matrix_product_operator_truncation_mode") && value != "relative_max" &&
167 value != "discarded_weight")
168 throw std::invalid_argument("Invalid truncation mode: expected relative_max or "
169 "discarded_weight");
170
171 // specially handled, ignore it
172 if (IgnoredSetting(key))
173 return;
174 configMap[key] = value;
175 }
176
177 void SetConfiguration(const std::string &key, long long int value)
178 {
179 // specially handled, ignore it
180 if (IgnoredSetting(key))
181 return;
182 SetConfiguration(key, std::to_string(value));
183 }
184
185 void SetConfiguration(const std::string &key, double value)
186 {
187 // specially handled, ignore it
188 if (IgnoredSetting(key))
189 return;
190 SetConfiguration(key, std::to_string(value));
191 }
192
201 bool IsSet(const std::string &key) const
202 {
203 return configMap.find(key) != configMap.end();
204 }
205
214 std::string GetConfiguration(const std::string &key) const
215 {
216 auto it = configMap.find(key);
217 if (it != configMap.end())
218 {
219 return it->second;
220 }
221 return "";
222 }
223
224 long long int GetConfigurationAsInt(const std::string &key) const
225 {
226 auto it = configMap.find(key);
227 if (it != configMap.end())
228 {
229 return std::stoll(it->second);
230 }
231 return 0;
232 }
233
234 // For size_t-valued settings: the signed and double getters cannot represent
235 // the whole range, and a value near SIZE_MAX misconverts through double.
236 unsigned long long int GetConfigurationAsUnsigned(const std::string &key) const
237 {
238 auto it = configMap.find(key);
239 if (it != configMap.end())
240 {
241 return std::stoull(it->second);
242 }
243 return 0;
244 }
245
246 double GetConfigurationAsDouble(const std::string &key) const
247 {
248 auto it = configMap.find(key);
249 if (it != configMap.end())
250 {
251 return std::stod(it->second);
252 }
253 return 0.0;
254 }
255
256 static bool CanBeAppliedOnInitializedSimulator(const std::string &key)
257 {
258 if (key == "gpu_device" || key == "method" || key == "use_double_precision" || key == "precision" || key == "max_parallel_threads" ||
259 key == "parallel_state_update" || key == "statevector_parallel_threshold")
260 return false;
261
262 return true;
263 }
264
265 static bool IgnoredSetting(const std::string &key)
266 {
267 if (key == "max_simulators" || key == "method")
268 return true;
269
270 return false;
271 }
272
273 void ApplyConfigurationToSimulator(const std::shared_ptr<Simulators::IState> &simulator) const
274 {
275 for (const auto &[key, value] : configMap)
276 {
277 if (key == "gate_fusion" && simulator->GetType() != SimulatorType::kQCSim && simulator->GetType() != SimulatorType::kCompositeQCSim &&
278 !IsGpuSimulator(simulator->GetType()))
279 continue;
280
281 // Networks retain GPU placement when an optimizer selects a CPU backend.
282 // Replay it only to GPU simulators; Aer rejects this plugin-specific key.
283 if (key == "gpu_device" && !IsGpuSimulator(simulator->GetType()))
284 continue;
285
286 // Route the seed through SetSeed, whose contract is to seed EVERY random
287 // stream the simulator owns -- including the auxiliary one used for
288 // measurement-time readout error. Its default implementation still
289 // records the value with Configure, so this subsumes the plain call.
290 if (key == "seed")
291 {
292 try
293 {
294 simulator->SetSeed(std::stoull(value));
295 continue;
296 }
297 catch (const std::exception &)
298 {
299 // Not a number: fall through and let the simulator reject it.
300 }
301 }
302
303 simulator->Configure(key.c_str(), value.c_str());
304 }
305 }
306
307 void ApplyConfigurationFromSimulator(const std::shared_ptr<Simulators::IState> &simulator)
308 {
309 if (!simulator)
310 return;
311 ApplyConfigurationFromMap(simulator->GetConfigMap());
312 }
313
314 void ApplyConfigurationFromMap(const std::unordered_map<std::string, std::string> &config)
315 {
316 for (const auto &[key, value] : config)
317 SetConfiguration(key, value);
318 }
319
320 const std::unordered_map<std::string, std::string> &GetConfigMap() const
321 {
322 return configMap;
323 }
324
325 bool WasApplied(const std::string &key, const std::string &value) const
326 {
327 auto it = configMap.find(key);
328 if (it != configMap.end())
329 return it->second == value;
330
331 return false;
332 }
333
334 private:
335 std::unordered_map<std::string, std::string> configMap;
336};
337
338} // namespace Simulators
339
340#endif
static std::string GpuSvdSettingGroup(const std::string &key)
bool IsSet(const std::string &key) const
Check if a configuration value is set.
static int ParseGpuDevice(const std::string &value)
Set a configuration value.
static bool ParsePrecision(const std::string &key, const std::string &value)
Configuration(const Configuration &)=default
The copy constructor.
Configuration & operator=(const Configuration &)=default
The copy assignment operator.
static bool CanBeAppliedOnInitializedSimulator(const std::string &key)
bool WasApplied(const std::string &key, const std::string &value) const
static bool ParseGpuSvdFlag(const std::string &value)
const std::unordered_map< std::string, std::string > & GetConfigMap() const
void ApplyConfigurationFromSimulator(const std::shared_ptr< Simulators::IState > &simulator)
void ApplyConfigurationFromMap(const std::unordered_map< std::string, std::string > &config)
void SetConfiguration(const std::string &key, double value)
double GetConfigurationAsDouble(const std::string &key) const
void SetConfiguration(const std::string &key, const std::string &value)
Configuration(Configuration &&)=default
The move constructor.
void ApplyConfigurationToSimulator(const std::shared_ptr< Simulators::IState > &simulator) const
unsigned long long int GetConfigurationAsUnsigned(const std::string &key) const
long long int GetConfigurationAsInt(const std::string &key) const
static bool IgnoredSetting(const std::string &key)
Configuration & operator=(Configuration &&)=default
The move assignment operator.
Configuration()=default
The constructor.
virtual ~Configuration()=default
The destructor.
void SetConfiguration(const std::string &key, long long int value)
std::string GetConfiguration(const std::string &key) const
Get a configuration value.
constexpr const char * kLegacyCap
constexpr const char * kTruncationWeight
constexpr const char * kVirtualBonds
double ParseWeight(const std::string &value)
bool ParseFlag(const std::string &value)
constexpr const char * kStrategy
Strategy ParseStrategy(const std::string &value)
Bounded online routing based on current physical bond dimensions.
@ kCompositeQCSim
composite qcsim simulator type
Definition State.h:87
@ kQCSim
qcsim simulator type
Definition State.h:83
bool IsGpuSimulator(SimulatorType type)
Definition State.h:99