Qrack  9.0
General classical-emulating-quantum development framework
qengineshard.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // QEngineShard is the atomic qubit unit of the QUnit mapper. "PhaseShard" optimizations are basically just a very
6 // specific "gate fusion" type optimization, where multiple gates are composed into single product gates before
7 // application to the state vector, to reduce the total number of gates that need to be applied. Rather than handling
8 // this as a "QFusion" layer optimization, which will typically sit BETWEEN a base QEngine set of "shards" and a QUnit
9 // that owns them, this particular gate fusion optimization can be avoid representational entanglement in QUnit in the
10 // first place, which QFusion would not help with. Alternatively, another QFusion would have to be in place ABOVE the
11 // QUnit layer, (with QEngine "below,") for this to work. Additionally, QFusion is designed to handle more general gate
12 // fusion, not specifically controlled phase gates, which are entirely commuting among each other and possibly a
13 // jumping-off point for further general "Fourier basis" optimizations which should probably reside in QUnit, analogous
14 // to the |+>/|-> basis changes QUnit takes advantage of for "H" gates.
15 //
16 // Licensed under the GNU Lesser General Public License V3.
17 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
18 // for details.
19 
20 #pragma once
21 
22 #include "qinterface.hpp"
23 
24 #define IS_ARG_0(c) IS_SAME(c, ONE_CMPLX)
25 #define IS_ARG_PI(c) IS_OPPOSITE(c, ONE_CMPLX)
26 
27 namespace Qrack {
28 
31 struct PhaseShard {
34  bool isInvert;
35 
39  , isInvert(false)
40  {
41  }
42 };
43 
44 class QEngineShard;
46 typedef std::shared_ptr<PhaseShard> PhaseShardPtr;
47 typedef std::map<QEngineShardPtr, PhaseShardPtr> ShardToPhaseMap;
48 
50 class QEngineShard {
51 protected:
53  typedef void (QEngineShard::*OptimizeFn)();
55  typedef void (QEngineShard::*AddAnglesFn)(QEngineShardPtr control, complex cmplxDiff, complex cmplxSame);
56 
57 public:
65  // Shards which this shard controls
67  // Shards which this shard (anti-)controls
69  // Shards of which this shard is a target
71  // Shards of which this shard is an (anti-controlled) target
73  // For FindShardIndex
74  bool found;
75 
76 protected:
77  // We'd rather not have these getters at all, but we need their function pointers.
82 
83 public:
85  : unit(NULL)
86  , mapped(0)
87  , isProbDirty(false)
88  , isPhaseDirty(false)
89  , amp0(ONE_CMPLX)
90  , amp1(ZERO_CMPLX)
92  , controlsShards()
94  , targetOfShards()
96  , found(false)
97  {
98  }
99 
100  QEngineShard(const bool& set, const complex rand_phase = ONE_CMPLX)
101  : unit(NULL)
102  , mapped(0)
103  , isProbDirty(false)
104  , isPhaseDirty(false)
105  , pauliBasis(PauliZ)
106  , controlsShards()
108  , targetOfShards()
110  , found(false)
111  {
112  amp0 = set ? ZERO_CMPLX : rand_phase;
113  amp1 = set ? rand_phase : ZERO_CMPLX;
114  }
115 
116  // Dirty state constructor:
118  : unit(u)
119  , mapped(mapping)
120  , isProbDirty(true)
121  , isPhaseDirty(true)
122  , amp0(ONE_CMPLX)
123  , amp1(ZERO_CMPLX)
124  , pauliBasis(PauliZ)
125  , controlsShards()
127  , targetOfShards()
129  , found(false)
130  {
131  }
132 
133  void MakeDirty()
134  {
135  isProbDirty = true;
136  isPhaseDirty = true;
137  }
138 
139  bool ClampAmps();
140  void DumpMultiBit();
141 
142 protected:
143  void RemoveBuffer(QEngineShardPtr p, ShardToPhaseMap& localMap, GetBufferFn remoteMapGet);
144 
145 public:
149  {
151  }
153  {
155  }
156 
157 protected:
158  void DumpBuffer(OptimizeFn optimizeFn, ShardToPhaseMap& localMap, AddRemoveFn remoteFn);
159  void DumpSamePhaseBuffer(OptimizeFn optimizeFn, ShardToPhaseMap& localMap, AddRemoveFn remoteFn);
160 
161 public:
164  {
166  }
168  {
170  }
172  {
174  }
175 
176 protected:
177  void AddBuffer(QEngineShardPtr p, ShardToPhaseMap& localMap, GetBufferFn remoteFn);
178 
179 public:
183  {
185  }
187  {
189  }
190 
191 protected:
192  void AddAngles(QEngineShardPtr control, complex cmplxDiff, complex cmplxSame, AddRemoveFn localFn,
193  ShardToPhaseMap& localMap, AddRemoveFn remoteFn);
194 
195 public:
196  void AddPhaseAngles(QEngineShardPtr control, complex topLeft, complex bottomRight)
197  {
198  AddAngles(control, topLeft, bottomRight, &QEngineShard::MakePhaseControlledBy, targetOfShards,
200  }
201  void AddAntiPhaseAngles(QEngineShardPtr control, complex bottomRight, complex topLeft)
202  {
205  }
206  void AddInversionAngles(QEngineShardPtr control, complex topRight, complex bottomLeft)
207  {
208  MakePhaseControlledBy(control);
209  targetOfShards[control]->isInvert = !targetOfShards[control]->isInvert;
210  std::swap(targetOfShards[control]->cmplxDiff, targetOfShards[control]->cmplxSame);
211  AddPhaseAngles(control, topRight, bottomLeft);
212  }
213  void AddAntiInversionAngles(QEngineShardPtr control, complex bottomLeft, complex topRight)
214  {
215  MakePhaseAntiControlledBy(control);
216  antiTargetOfShards[control]->isInvert = !antiTargetOfShards[control]->isInvert;
217  std::swap(antiTargetOfShards[control]->cmplxDiff, antiTargetOfShards[control]->cmplxSame);
218  AddAntiPhaseAngles(control, bottomLeft, topRight);
219  }
220 
221 protected:
222  void OptimizeBuffer(ShardToPhaseMap& localMap, GetBufferFn remoteMapGet, AddAnglesFn phaseFn, bool makeThisControl);
223 
224 public:
226  {
228  }
230  {
232  }
234  {
237  }
239  {
242  }
243 
244  void OptimizeBothTargets();
245 
246 protected:
247  void CombineBuffers(GetBufferFn targetMapGet, GetBufferFn controlMapGet, AddAnglesFn angleFn);
248 
249 public:
252  {
257  }
258 
259  void SwapTargetAnti(QEngineShardPtr control);
260  void FlipPhaseAnti();
261  void CommutePhase(complex topLeft, complex bottomRight);
262 
263 protected:
264  void RemoveIdentityBuffers(ShardToPhaseMap& localMap, GetBufferFn remoteMapGet);
265  void RemovePhaseBuffers(ShardToPhaseMap& localMap, GetBufferFn remoteMapGet);
266 
267 public:
268  void CommuteH();
269 
271  {
276  }
277 
278  bool IsInvertControl();
279  bool IsInvertTarget();
280 
281 protected:
283 
284 public:
286  {
287  // Upon measurement, buffered phase can sometimes be totally ignored.
288  // If we clear phase before applying buffered inversions, we can optimize application as CNOT.
293  }
294 
295  bitLenInt GetQubitCount() { return unit ? unit->GetQubitCount() : 1U; };
297  {
298  if (!isProbDirty || !unit) {
299  return (real1_f)norm(amp1);
300  }
301 
302  return unit->Prob(mapped);
303  }
304  bool isClifford()
305  {
306  return (unit && unit->isClifford(mapped)) ||
307  (!unit &&
308  ((norm(amp0) <= FP_NORM_EPSILON) || (norm(amp1) <= FP_NORM_EPSILON) ||
309  (norm(amp0 - amp1) <= FP_NORM_EPSILON) || (norm(amp0 + amp1) <= FP_NORM_EPSILON) ||
310  (norm(amp0 - I_CMPLX * amp1) <= FP_NORM_EPSILON) ||
311  (norm(amp0 + I_CMPLX * amp1) <= FP_NORM_EPSILON)));
312  };
313 };
314 
316 protected:
317  std::vector<QEngineShard> shards;
318  std::vector<bitLenInt> swapMap;
319 
320 public:
322  {
323  // Intentionally left blank
324  }
325 
327  : shards(size)
328  , swapMap(size)
329  {
330  for (bitLenInt i = 0U; i < size; ++i) {
331  swapMap[i] = i;
332  }
333  }
334 
335  typedef std::vector<QEngineShard>::iterator iterator;
336 
337  QEngineShard& operator[](const bitLenInt& i) { return shards[swapMap[i]]; }
338 
339  iterator begin() { return shards.begin(); }
340 
341  iterator end() { return shards.end(); }
342 
343  bitLenInt size() { return shards.size(); }
344 
345  void push_back(const QEngineShard& shard)
346  {
347  shards.push_back(shard);
348  swapMap.push_back(swapMap.size());
349  }
350 
351  void insert(bitLenInt start, QEngineShardMap& toInsert)
352  {
353  bitLenInt oSize = size();
354 
355  shards.insert(shards.end(), toInsert.shards.begin(), toInsert.shards.end());
356  swapMap.insert(swapMap.begin() + start, toInsert.swapMap.begin(), toInsert.swapMap.end());
357 
358  for (bitLenInt lcv = 0U; lcv < toInsert.size(); ++lcv) {
359  swapMap[(size_t)start + lcv] += oSize;
360  }
361  }
362 
364  {
365  for (bitLenInt index = begin; index < end; ++index) {
366  bitLenInt offset = swapMap[index];
367  shards.erase(shards.begin() + offset);
368 
369  for (bitLenInt lcv = 0U; lcv < (bitLenInt)swapMap.size(); ++lcv) {
370  if (swapMap[lcv] >= offset) {
371  --(swapMap[lcv]);
372  }
373  }
374  }
375 
376  swapMap.erase(swapMap.begin() + begin, swapMap.begin() + end);
377  }
378 
379  void swap(bitLenInt qubit1, bitLenInt qubit2) { std::swap(swapMap[qubit1], swapMap[qubit2]); }
380 };
381 } // namespace Qrack
Definition: qengineshard.hpp:315
std::vector< bitLenInt > swapMap
Definition: qengineshard.hpp:318
std::vector< QEngineShard >::iterator iterator
Definition: qengineshard.hpp:335
std::vector< QEngineShard > shards
Definition: qengineshard.hpp:317
void push_back(const QEngineShard &shard)
Definition: qengineshard.hpp:345
bitLenInt size()
Definition: qengineshard.hpp:343
QEngineShardMap()
Definition: qengineshard.hpp:321
QEngineShardMap(const bitLenInt &size)
Definition: qengineshard.hpp:326
void swap(bitLenInt qubit1, bitLenInt qubit2)
Definition: qengineshard.hpp:379
void erase(bitLenInt begin, bitLenInt end)
Definition: qengineshard.hpp:363
void insert(bitLenInt start, QEngineShardMap &toInsert)
Definition: qengineshard.hpp:351
iterator begin()
Definition: qengineshard.hpp:339
iterator end()
Definition: qengineshard.hpp:341
QEngineShard & operator[](const bitLenInt &i)
Definition: qengineshard.hpp:337
Associates a QInterface object with a set of bits.
Definition: qengineshard.hpp:50
void CombineGates()
If this bit is both control and target of another bit, try to combine the operations into one gate.
Definition: qengineshard.hpp:251
void AddPhaseAngles(QEngineShardPtr control, complex topLeft, complex bottomRight)
Definition: qengineshard.hpp:196
void AddBuffer(QEngineShardPtr p, ShardToPhaseMap &localMap, GetBufferFn remoteFn)
Definition: qengineshard.cpp:113
void OptimizeBothTargets()
Definition: qengineshard.cpp:168
void DumpControlOf()
Definition: qengineshard.hpp:162
QEngineShard(QInterfacePtr u, const bitLenInt &mapping)
Definition: qengineshard.hpp:117
ShardToPhaseMap & GetAntiControlsShards()
Definition: qengineshard.hpp:79
void DumpMultiBit()
Definition: qengineshard.cpp:51
void MakePhaseControlledBy(QEngineShardPtr p)
Definition: qengineshard.hpp:180
complex amp0
Definition: qengineshard.hpp:62
ShardToPhaseMap & GetControlsShards()
Definition: qengineshard.hpp:78
void FlipPhaseAnti()
Definition: qengineshard.cpp:258
void RemoveIdentityBuffers(ShardToPhaseMap &localMap, GetBufferFn remoteMapGet)
Definition: qengineshard.cpp:304
void OptimizeAntiTargets()
Definition: qengineshard.hpp:238
void CommutePhase(complex topLeft, complex bottomRight)
Definition: qengineshard.cpp:281
void AddAngles(QEngineShardPtr control, complex cmplxDiff, complex cmplxSame, AddRemoveFn localFn, ShardToPhaseMap &localMap, AddRemoveFn remoteFn)
Definition: qengineshard.cpp:122
bool ClampAmps()
Definition: qengineshard.cpp:29
bitLenInt mapped
Definition: qengineshard.hpp:59
void(QEngineShard::* OptimizeFn)()
Definition: qengineshard.hpp:53
void OptimizeAntiControls()
Definition: qengineshard.hpp:233
ShardToPhaseMap antiTargetOfShards
Definition: qengineshard.hpp:72
void RemovePhaseBuffers(ShardToPhaseMap &localMap, GetBufferFn remoteMapGet)
Definition: qengineshard.cpp:324
void(QEngineShard::* AddAnglesFn)(QEngineShardPtr control, complex cmplxDiff, complex cmplxSame)
Definition: qengineshard.hpp:55
void AddAntiPhaseAngles(QEngineShardPtr control, complex bottomRight, complex topLeft)
Definition: qengineshard.hpp:201
bool isProbDirty
Definition: qengineshard.hpp:60
ShardToPhaseMap targetOfShards
Definition: qengineshard.hpp:70
void RemoveControl(QEngineShardPtr p)
Definition: qengineshard.hpp:146
bitLenInt GetQubitCount()
Definition: qengineshard.hpp:295
void DumpAntiControlOf()
Definition: qengineshard.hpp:163
bool isClifford()
Definition: qengineshard.hpp:304
QEngineShard()
Definition: qengineshard.hpp:84
QInterfacePtr unit
Definition: qengineshard.hpp:58
void MakePhaseAntiControlledBy(QEngineShardPtr p)
Definition: qengineshard.hpp:182
void RemoveTarget(QEngineShardPtr p)
Definition: qengineshard.hpp:147
void RemoveAntiTarget(QEngineShardPtr p)
Definition: qengineshard.hpp:152
void RemoveBuffer(QEngineShardPtr p, ShardToPhaseMap &localMap, GetBufferFn remoteMapGet)
Definition: qengineshard.cpp:75
void MakePhaseAntiControlOf(QEngineShardPtr p)
Definition: qengineshard.hpp:186
ShardToPhaseMap & GetAntiTargetOfShards()
Definition: qengineshard.hpp:81
void OptimizeBuffer(ShardToPhaseMap &localMap, GetBufferFn remoteMapGet, AddAnglesFn phaseFn, bool makeThisControl)
Definition: qengineshard.cpp:144
void ClearInvertPhase()
Definition: qengineshard.hpp:285
real1_f Prob()
Definition: qengineshard.hpp:296
void AddAntiInversionAngles(QEngineShardPtr control, complex bottomLeft, complex topRight)
Definition: qengineshard.hpp:213
ShardToPhaseMap & GetTargetOfShards()
Definition: qengineshard.hpp:80
void DumpPhaseBuffers()
Definition: qengineshard.hpp:270
ShardToPhaseMap controlsShards
Definition: qengineshard.hpp:66
Pauli pauliBasis
Definition: qengineshard.hpp:64
void DumpBuffer(OptimizeFn optimizeFn, ShardToPhaseMap &localMap, AddRemoveFn remoteFn)
Definition: qengineshard.cpp:84
ShardToPhaseMap &(QEngineShard::* GetBufferFn)()
Definition: qengineshard.hpp:52
void(QEngineShard::* AddRemoveFn)(QEngineShardPtr)
Definition: qengineshard.hpp:54
void MakePhaseControlOf(QEngineShardPtr p)
Definition: qengineshard.hpp:181
void SwapTargetAnti(QEngineShardPtr control)
Definition: qengineshard.cpp:239
void OptimizeTargets()
Definition: qengineshard.hpp:229
complex amp1
Definition: qengineshard.hpp:63
void DumpSamePhaseAntiControlOf()
Definition: qengineshard.hpp:171
bool found
Definition: qengineshard.hpp:74
void MakeDirty()
Definition: qengineshard.hpp:133
QEngineShard(const bool &set, const complex rand_phase=ONE_CMPLX)
Definition: qengineshard.hpp:100
void AddInversionAngles(QEngineShardPtr control, complex topRight, complex bottomLeft)
Definition: qengineshard.hpp:206
bool IsInvertTarget()
Definition: qengineshard.cpp:402
void RemoveAntiControl(QEngineShardPtr p)
Definition: qengineshard.hpp:148
void DumpSamePhaseControlOf()
Definition: qengineshard.hpp:167
ShardToPhaseMap antiControlsShards
Definition: qengineshard.hpp:68
bool IsInvertControl()
Definition: qengineshard.cpp:385
void ClearMapInvertPhase(ShardToPhaseMap &shards)
Definition: qengineshard.cpp:419
bool isPhaseDirty
Definition: qengineshard.hpp:61
void DumpSamePhaseBuffer(OptimizeFn optimizeFn, ShardToPhaseMap &localMap, AddRemoveFn remoteFn)
Definition: qengineshard.cpp:94
void CombineBuffers(GetBufferFn targetMapGet, GetBufferFn controlMapGet, AddAnglesFn angleFn)
Definition: qengineshard.cpp:211
void CommuteH()
Definition: qengineshard.cpp:343
void OptimizeControls()
Definition: qengineshard.hpp:225
Definition: complex16x2simd.hpp:25
std::complex< half_float::half > complex
Definition: qrack_types.hpp:62
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:28
std::shared_ptr< PhaseShard > PhaseShardPtr
Definition: qengineshard.hpp:46
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:243
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:101
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:239
float real1_f
Definition: qrack_types.hpp:64
QRACK_CONST complex I_CMPLX
Definition: qrack_types.hpp:241
std::map< QEngineShardPtr, PhaseShardPtr > ShardToPhaseMap
Definition: qengineshard.hpp:47
Pauli
Enumerated list of Pauli bases.
Definition: qinterface.hpp:34
@ PauliZ
Pauli Z operator. Corresponds to Q# constant "PauliZ.".
Definition: qinterface.hpp:42
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:240
QEngineShard * QEngineShardPtr
Definition: qengineshard.hpp:44
std::map< QInterface *, std::map< uintq, bitLenInt > > shards
Definition: pinvoke_api.cpp:262
MICROSOFT_QUANTUM_DECL void U(_In_ uintq sid, _In_ uintq q, _In_ double theta, _In_ double phi, _In_ double lambda)
(External API) 3-parameter unitary gate
Definition: pinvoke_api.cpp:1362
#define bitLenInt
Definition: qrack_types.hpp:44
Caches controlled gate phase between shards, (as a case of "gate fusion" optimization particularly us...
Definition: qengineshard.hpp:31
complex cmplxSame
Definition: qengineshard.hpp:33
PhaseShard()
Definition: qengineshard.hpp:36
bool isInvert
Definition: qengineshard.hpp:34
complex cmplxDiff
Definition: qengineshard.hpp:32