-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathvalidation.cpp
More file actions
4113 lines (2914 loc) · 188 KB
/
validation.cpp
File metadata and controls
4113 lines (2914 loc) · 188 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/** @file
* Validation of user inputs which check all preconditions of the API
* functions are satisfied, and otherwise throws a user-readable error.
*
* @author Tyson Jones
* @author Richard Meister (patched v3 mem-leak and MSVC build)
* @author Kshitij Chhabra (patched v3 overflow bug)
*/
#include "quest/include/modes.h"
#include "quest/include/types.h"
#include "quest/include/precision.h"
#include "quest/include/environment.h"
#include "quest/include/qureg.h"
#include "quest/include/matrices.h"
#include "quest/include/paulis.h"
#include "quest/include/channels.h"
#include "quest/src/core/validation.hpp"
#include "quest/src/core/errors.hpp"
#include "quest/src/core/bitwise.hpp"
#include "quest/src/core/memory.hpp"
#include "quest/src/core/utilities.hpp"
#include "quest/src/core/parser.hpp"
#include "quest/src/core/printer.hpp"
#include "quest/src/comm/comm_config.hpp"
#include "quest/src/comm/comm_routines.hpp"
#include "quest/src/cpu/cpu_config.hpp"
#include "quest/src/gpu/gpu_config.hpp"
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
using std::string;
using std::vector;
/**
* @todo
* Invalid input error messages are currently limited to containing only integer
* variables, whereas the ability to embed floats and strings would be useful.
*/
/*
* INVALID INPUT ERROR MESSAGES
* which can contain variables with syntax ${VAR1} ${VAR2}, substituted at error-throw with
* runtime parameters via assertThat(..., {{"${VAR1}",1}, {"${VAR2}",2}}, ...)
*/
namespace report {
/*
* ENVIRONMENT CREATION
*/
string QUEST_ENV_ALREADY_INIT =
"The QuEST environment has already been initialised. This can only be performed once during program execution.";
string QUEST_ENV_ALREADY_FINAL =
"The QuEST environment has already been finalised, and can thereafter never be re-initialised since this leads to undefined MPI behaviour.";
string INVALID_OPTION_FOR_ENV_IS_DISTRIB =
"Argument 'useDistrib' must be 1 or 0 to respectively indicate whether or not to distribute the new environment, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string INVALID_OPTION_FOR_ENV_IS_GPU_ACCEL =
"Argument 'useGpuAccel' must be 1 or 0 to respectively indicate whether or not to GPU-accelerate the new environment, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string INVALID_OPTION_FOR_ENV_IS_MULTITHREAD =
"Argument 'useMultithread' must be 1 or 0 to respectively indicate whether or not to enable multithreading in the new environment, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string CANNOT_MULTITHREAD_ENV_WITHOUT_OPENMP_COMPILATION =
"Cannot create a multithreaded environment because the QuEST source was not compiled with OpenMP enabled.";
string CANNOT_DISTRIB_ENV_WITHOUT_MPI_COMMPILATION =
"Cannot create a distributed environment because the QuEST source was not compiled with MPI enabled.";
string CANNOT_GPU_ACCEL_ENV_WITH_GPU_COMPILATION =
"Cannot create a GPU-accelerated environment because the QuEST source was not compiled with GPU acceleration.";
string CANNOT_GPU_ACCEL_ENV_WITH_NO_AVAILABLE_GPUS =
"Cannot create a GPU-accelerated environment because there are no GPUs available.";
string CANNOT_DISTRIB_ENV_BETWEEN_NON_POW_2_NODES =
"Cannot distribute QuEST between ${NUM_NODES} nodes; must use a power-of-2 number of nodes.";
string MULTIPLE_NODES_BOUND_TO_SAME_GPU =
"Multiple MPI processes (nodes) were bound to the same GPU which is detrimental to performance and almost never intended. Please re-deploy QuEST with no more MPI processes than there are total GPUs. Alternatively, recompile QuEST with macro PERMIT_NODES_TO_SHARE_GPU=1.";
string CUQUANTUM_DEPLOYED_ON_BELOW_CC_GPU =
"Cannot use cuQuantum on a GPU with compute-capability ${OUR_CC}; a compute-capability of ${MIN_CC} or above is required. Recompile with cuQuantum disabled to fall-back to using Thrust and custom kernels.";
string CUQUANTUM_DEPLOYED_ON_GPU_WITHOUT_MEM_POOLS =
"Cannot use cuQuantum since your GPU does not support memory pools. Recompile with cuQuantum disabled to fall-back to using Thrust and custom kernels.";
/*
* EXISTING QUESTENV
*/
string QUEST_ENV_NOT_INIT =
"The QuEST environment is not initialised. Please first call initQuESTEnv() or initCustomQuESTEnv().";
/*
* DEBUG UTILITIES
*/
string INVALID_NEW_EPSILON =
"Invalid new epsilon value (${NEW_EPS}). Must specifiy a positive number, or zero to disable numerical validation (as if the epsilon is infinity).";
string INVALID_NUM_REPORTED_SCALARS =
"Invalid parameter (${NUM_ITEMS}). Must specify a positive number of scalars to be reported, or 0 to indicate that all scalars should be reported.";
string INVALID_NUM_REPORTED_SIG_FIGS =
"Invalid number of significant figures (${NUM_SIG_FIGS}). Cannot be less than one.";
string INVALID_NUM_RANDOM_SEEDS =
"Invalid number of random seeds (${NUM_SEEDS}). Must specify one or more. In distributed settings, only the root node needs to pass a valid number of seeds (other node arguments are ignored).";
string INVALID_NUM_REPORTED_NEWLINES =
"Invalid number of trailing newlines (${NUM_NEWLINES}). Cannot generally be less than zero, and must not be zero when calling multi-line reporting functions like reportQureg().";
string INSUFFICIENT_NUM_REPORTED_NEWLINES =
"The number of trailing newlines (set by setNumReportedNewlines()) is zero which is not permitted when calling multi-line reporters.";
/*
* QUREG CREATION
*/
string NON_POSITIVE_NUM_QUBITS_IN_CREATE_QUREG =
"Cannot create Qureg of ${NUM_QUBITS} qubits; must contain one or more qubits.";
string NEW_STATEVEC_QUREG_NUM_AMPS_WOULD_EXCEED_QINDEX =
"Cannot create Qureg of ${NUM_QUBITS} qubits: the statevector would contain more amplitudes (2^${NUM_QUBITS}) than the maximum which can be addressed by the qindex type (2^${MAX_QUBITS}). See reportQuESTEnv().";
string NEW_DENSMATR_QUREG_NUM_AMPS_WOULD_EXCEED_QINDEX =
"Cannot create density Qureg of ${NUM_QUBITS} qubits: the density matrix would contain more amplitudes (4^${NUM_QUBITS}) than can be addressed by the qindex type (4^${MAX_QUBITS}). See reportQuESTEnv().";
string NEW_STATEVEC_QUREG_LOCAL_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create Qureg of ${NUM_QUBITS} qubits distributed over ${NUM_NODES} nodes because the size (in bytes) of the necessary global memory would overflow size_t. In this deployment, the maximum number of qubits in a statevector Qureg is ${MAX_QUBITS}. See reportQuESTEnv().";
string NEW_DENSMATR_QUREG_LOCAL_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create density Qureg of ${NUM_QUBITS} qubits distributed over ${NUM_NODES} nodes because the size (in bytes) of the necessary global memory would overflow size_t. In this deployment, the maximum number of qubits in a density-matrix Qureg is ${MAX_QUBITS}. See reportQuESTEnv().";
string NEW_DISTRIB_STATEVEC_QUREG_HAS_TOO_FEW_AMPS =
"Cannot create a distributed Qureg of only ${NUM_QUBITS} qubits between ${NUM_NODES} nodes, because each node would contain fewer than one amplitude of the statevector. The minimum size in this deployment is ${MIN_QUBITS} qubits; see reportQuESTEnv(). Consider disabling distribution for this Qureg.";
string NEW_DISTRIB_DENSMATR_QUREG_HAS_TOO_FEW_AMPS =
"Cannot create a distributed density Qureg of only ${NUM_QUBITS} qubits between ${NUM_NODES} nodes, because each node would contain fewer than a column's worth of amplitudes of the density matrix. The minimum size in this deployment is ${MIN_QUBITS} qubits; see reportQuESTEnv(). Consider disabling distribution for this Qureg.";
string INVALID_OPTION_FOR_QUREG_IS_DENSMATR =
"Argument 'isDensityMatrix' must be 1 or 0 to respectively indicate whether the Qureg should be instantiated as a potentially-mixed density matrix or a strictly-pure state-vector.";
string INVALID_OPTION_FOR_QUREG_IS_DISTRIB =
"Argument 'useDistrib' must be 1 or 0 to respectively indicate whether or not to distribute the new Qureg, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string INVALID_OPTION_FOR_QUREG_IS_GPU_ACCEL =
"Argument 'useGpuAccel' must be 1 or 0 to respetively indicate whether or not to GPU-accelerate the new Qureg, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string INVALID_OPTION_FOR_QUREG_IS_MULTITHREAD =
"Argument 'useMultithread' must be 1 or 0 to respectively indicate whether or not to use multithreading when processing the new Qureg, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string NEW_DISTRIB_QUREG_IN_NON_DISTRIB_ENV =
"Cannot distribute a Qureg when in a non-distributed QuEST environment.";
string NEW_GPU_QUREG_IN_NON_GPU_ACCEL_ENV =
"Cannot allocate a Qureg to a GPU when in a non-GPU-accelerated QuEST environment.";
string NEW_MULTITHREAD_QUREG_IN_NON_MULTITHREAD_ENV =
"Cannot enable multithreaded processing of a Qureg created in a non-multithreaded QuEST environment.";
string NEW_QUREG_CANNOT_FIT_INTO_NON_DISTRIB_CPU_MEM =
"The non-distributed Qureg (isDensity=${IS_DENS}) of ${NUM_QUBITS} qubits would be too large (${QCOMP_BYTES} * ${EXP_BASE}^${NUM_QUBITS} bytes) to fit into a single node's RAM (${RAM_SIZE} bytes). See reportQuESTEnv(), and consider using distribution.";
string NEW_QUREG_CANNOT_FIT_INTO_POTENTIALLY_DISTRIB_CPU_MEM =
"The distributed Qureg (isDensity=${IS_DENS}) of ${NUM_QUBITS} qubits, together with its commnication buffer, would be too large (2 * ${QCOMP_BYTES} * ${EXP_BASE}^${NUM_QUBITS} bytes) to fit into the combined RAM of all ${NUM_NODES} nodes (${NUM_NODES} * ${RAM_SIZE} bytes). See reportQuESTEnv().";
string NEW_QUREG_CANNOT_FIT_INTO_NON_DISTRIB_CURRENT_GPU_MEM =
"The non-distributed GPU-accelerated Qureg (isDensity=${IS_DENS}) of ${NUM_QUBITS} qubits would be too large (${QCOMP_BYTES} * ${EXP_BASE}^${NUM_QUBITS} bytes) to fit into a single node's available GPU memory (currently ${MIN_VRAM_AVAIL} bytes free). Consider additionally using distribution, or disabling GPU-acceleration (though this may greatly increase runtime).";
string NEW_QUREG_CANNOT_FIT_INTO_POTENTIALLY_DISTRIB_CURRENT_GPU_MEM =
"The distributed GPU-accelerated Qureg (isDensity=${IS_DENS}) of ${NUM_QUBITS} qubits, together with its commnication buffer, is too large; one or more of the ${NUM_GPUS} GPUs has insufficient available memory (only ${MIN_VRAM_AVAIL} bytes) to store its Qureg partition (${QCOMP_BYTES} * 2^${LOG2_NUM_AMPS} bytes) bytes. Consider disabling GPU-acceleration.";
string NEW_QUREG_CPU_AMPS_ALLOC_FAILED =
"Allocation of memory to store the CPU amplitudes failed.";
string NEW_QUREG_GPU_AMPS_ALLOC_FAILED =
"Allocation of memory to store the GPU amplitudes failed.";
string NEW_QUREG_CPU_COMM_BUFFER_ALLOC_FAILED =
"Allocation of memory for the distributed CPU communication buffer failed.";
string NEW_QUREG_GPU_COMM_BUFFER_ALLOC_FAILED =
"Allocation of memory for the distributed GPU communication buffer failed.";
/*
* EXISTING QUREG
*/
string INVALID_QUREG_FIELDS =
"Received an invalid Qureg, which had invalid or incompatible fields isDensityMatrix=${DENS_MATR}, numQubits=${NUM_QUBITS}, numAmps=${NUM_AMPS}. It is likely this Qureg was not initialised with createQureg().";
string QUREG_NOT_DENSITY_MATRIX =
"Expected a density matrix Qureg but received a statevector.";
string QUREG_NOT_STATE_VECTOR =
"Expected a statevector Qureg but received a density matrix.";
/*
* MUTABLE OBJECT FLAGS
*/
string NEW_HEAP_FLAG_ALLOC_FAILED =
"Attempted allocation of a heap flag (such as 'isApproxUnitary') miraculously failed, despite being a mere ${NUM_BYTES} bytes. This is unfathomably unlikely - go and have your fortune read at once!";
string INVALID_HEAP_FLAG_PTR =
"A flag (such as 'isApproxUnitary') bound to the given operator data structure (e.g. matrix, superoperator, Kraus map) was a NULL pointer, instead of an expected pointer to persistent heap memory. This may imply the structure was not created by its proper function (e.g. createCompMatr()).";
string INVALID_HEAP_FLAG_VALUE =
"A flag (such as 'isApproxUnitary') bound to the given operator data structure (e.g. matrix, superoperator, Kraus map) had an invalid value of ${BAD_FLAG}. Allowed values are '0', '1', and (except for 'wasGpuSynced') '${UNKNOWN_FLAG}', though these flags should not be modified directly by the user. It is likely the structure was not created by its proper function (e.g. createCompMatr()).";
/*
* MATRIX CREATION
*/
string INVALID_OPTION_FOR_MATRIX_IS_DISTRIB =
"Argument 'useDistrib' must be 1 or 0 to respectively indicate whether or not to distribute the new FullStateDiagMatr, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string INVALID_OPTION_FOR_MATRIX_IS_GPU_ACCEL =
"Argument 'useGpuAccel' must be 1 or 0 to respetively indicate whether or not to GPU-accelerate the new FullStateDiagMatr, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string INVALID_OPTION_FOR_MATRIX_IS_MULTITHREAD =
"Argument 'useMultithread' must be 1 or 0 to respectively indicate whether or not to use multithreading when initialising the new FullStateDiagMatr, or ${AUTO_DEPLOYMENT_FLAG} to let QuEST choose automatically.";
string NEW_DISTRIB_MATRIX_IN_NON_DISTRIB_ENV =
"Cannot distribute a FullStateDiagMatr when in a non-distributed QuEST environment.";
string NEW_GPU_MATRIX_IN_NON_GPU_ACCEL_ENV =
"Cannot allocate a FullStateDiagMatr to a GPU when in a non-GPU-accelerated QuEST environment.";
string NEW_MULTITHREAD_MATRIX_IN_NON_MULTITHREAD_ENV =
"Cannot enable multithreaded processing of a FullStateDiagMatr created in a non-multithreaded QuEST environment.";
string NEW_MATRIX_NUM_QUBITS_NOT_POSITIVE =
"Cannot create a matrix which acts upon ${NUM_QUBITS} qubits; must target one or more qubits.";
string NEW_DIAG_MATR_NUM_ELEMS_WOULD_EXCEED_QINDEX =
"Cannot create a diagonal matrix of ${NUM_QUBITS} qubits: the matrix would contain more elements (2^${NUM_QUBITS}) than the maximum which can be addressed by the qindex type (2^${MAX_QUBITS}).";
string NEW_COMP_MATR_NUM_ELEMS_WOULD_EXCEED_QINDEX =
"Cannot create a dense matrix of ${NUM_QUBITS} qubits: the matrix would contain more elements (4^${NUM_QUBITS}) than the maximum which can be addressed by the qindex type (4^${MAX_QUBITS}).";
string NEW_LOCAL_COMP_MATR_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create a local, dense matrix of ${NUM_QUBITS} qubits because the size (in bytes) of the necessary memory would overflow size_t. In this deployment, the maximum number of qubits in such a matrix is ${MAX_QUBITS}.";
string NEW_LOCAL_DIAG_MATR_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create a local, diagonal matrix of ${NUM_QUBITS} qubits because the size (in bytes) of the necessary memory would overflow size_t. In this deployment, the maximum number of qubits in such a matrix is ${MAX_QUBITS}.";
string NEW_DISTRIB_DIAG_MATR_LOCAL_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create a diagonal matrix of ${NUM_QUBITS} qubits distributed over ${NUM_NODES} nodes because the size (in bytes) of the necessary global memory would overflow size_t. In this deployment, the maximum number of qubits in such a matrix is ${MAX_QUBITS}.";
string NEW_DISTRIB_DIAG_MATR_HAS_TOO_FEW_AMPS =
"Cannot create a diagonal matrix of ${NUM_QUBITS} qubits distributed between ${NUM_NODES} nodes because each node would contain fewer than one element. The minimum number of qubits in such a matrix is ${MIN_QUBITS}. Consider disabling distribution for this matrix.";
string NEW_LOCAL_COMP_MATR_CANNOT_FIT_INTO_CPU_MEM =
"Cannot create a local, dense matrix of ${NUM_QUBITS} qubits because the necessary memory (${QCOMP_BYTES} * 4^${NUM_QUBITS} bytes) exceeds the available RAM of ${RAM_SIZE} bytes.";
string NEW_LOCAL_DIAG_MATR_CANNOT_FIT_INTO_CPU_MEM =
"Cannot create a local, diagonal matrix of ${NUM_QUBITS} qubits because the necessary memory (${QCOMP_BYTES} * 2^${NUM_QUBITS} bytes) exceeds the available RAM of ${RAM_SIZE} bytes.";
string NEW_DISTRIB_DIAG_MATR_CANNOT_FIT_INTO_CPU_MEM =
"Cannot create a diagonal matrix of ${NUM_QUBITS} qubits distributed between ${NUM_NODES} because the necessary memory per node (${QCOMP_BYTES} * 2^${NUM_QB_MINUS_LOG_NODES} bytes) exceeds the local available RAM of ${RAM_SIZE} bytes.";
string NEW_LOCAL_COMP_MATR_CANNOT_FIT_INTO_GPU_MEM =
"Cannot create a local, GPU-accelerated, dense matrix of ${NUM_QUBITS} qubits because the necessary memory (${QCOMP_BYTES} * 4^${NUM_QUBITS} bytes) exceeds the available GPU memory of ${VRAM_SIZE} bytes.";
string NEW_LOCAL_DIAG_MATR_CANNOT_FIT_INTO_GPU_MEM =
"Cannot create a local, GPU-accelerated, diagonal matrix of ${NUM_QUBITS} qubits because the necessary memory (${QCOMP_BYTES} * 2^${NUM_QUBITS} bytes) exceeds the available GPU memory of ${VRAM_SIZE} bytes.";
string NEW_DISTRIB_DIAG_MATR_CANNOT_FIT_INTO_GPU_MEM =
"Cannot create a GPU-accelerated, diagonal matrix of ${NUM_QUBITS} qubits distributed between ${NUM_NODES} because the necessary memory per node (${QCOMP_BYTES} * 2^${NUM_QB_MINUS_LOG_NODES} bytes) exceeds the local available GPU memory of ${VRAM_SIZE} bytes.";
string NEW_MATRIX_CPU_ELEMS_ALLOC_FAILED =
"Attempted allocation of the matrix memory (a total of ${NUM_BYTES} bytes in RAM) failed.";
string NEW_MATRIX_GPU_ELEMS_ALLOC_FAILED =
"Attempted allocation of the matrix's GPU memory (${NUM_BYTES} bytes in VRAM) failed.";
/*
* MATRIX INITIALISATION
*/
string COMP_MATR_NEW_ELEMS_WRONG_NUM_ROWS =
"Incompatible number of rows (${NUM_GIVEN_ROWS}) of elements given to overwrite a ${NUM_QUBITS}-qubit CompMatr, which expects ${NUM_EXPECTED_ROWS} rows.";
string COMP_MATR_NEW_ELEMS_WRONG_ROW_DIM =
"One or more rows contained an incompatible number of elements (${NUM_GIVEN_ELEMS}). The ${NUM_QUBITS}-qubit CompMatr expects a square ${EXPECTED_DIM}x${EXPECTED_DIM} matrix.";
string DIAG_MATR_WRONG_NUM_NEW_ELEMS =
"Incompatible number of elements (${NUM_GIVEN_ELEMS}) assigned to a ${NUM_QUBITS}-qubit DiagMatr, which expects ${NUM_EXPECTED_ELEMS} elements.";
string DIAG_MATR_NEW_ELEMS_NULL_PTR =
"The given list of new elements was a null pointer.";
string DENSE_MATR_NEW_ELEMS_OUTER_NULL_PTR =
"The given matrix of new elements was a null pointer.";
string DENSE_MATR_NEW_ELEMS_INNER_NULL_PTR =
"The given matrix of new elements contained a null pointer, suggesting an issue with initialising one or more rows.";
string FULL_STATE_DIAG_MATR_NEW_ELEMS_INVALID_START_INDEX =
"Invalid start index (${START_IND}), which must be non-negative and smaller than the total number of diagonal elements in the matrix (${MATR_NUM_ELEMS}).";
string FULL_STATE_DIAG_MATR_NEW_ELEMS_NUM_IS_NON_POSITIVE =
"Invalid number of new elements (${NUM_ELEMS}). Must be greater than zero.";
string FULL_STATE_DIAG_MATR_NEW_ELEMS_NUM_EXCEEDS_MAX_NUM =
"The given number of new elements (${NEW_NUM_ELEMS}) exceeds the total number of diagonal elements in the matrix (${MATR_NUM_ELEMS}).";
string FULL_STATE_DIAG_MATR_NEW_ELEMS_EXCEEDS_END_INDEX =
"The specified range of elements to set (at indices ${START_IND} to ${END_IND_EXCL} exclusive) exceeds the bounds of the diagonal matrix (of ${MATR_NUM_ELEMS} total elements).";
string MATR_NUM_QUBITS_MISMATCHES_INLINE_SETTER =
"The declared number of qubits (${NUM_SETTER_QUBITS}) differs from the number of qubits of the matrix (${NUM_MATRIX_QUBITS}).";
string MATR_NUM_ELEMS_MISMATCHES_VEC_LENGTH_IN_INLINE_SETTER =
"The declared number of passed elements (${NUM_ELEMS}) differs from the length of the given list (${VEC_LENGTH}).";
string MULTI_VAR_FUNC_INVALID_NUM_VARS =
"Invalid number of variables or dimensions (${NUM_VARS}). Must be a positive integer.";
string MULTI_VAR_FUNC_INVALID_NUM_QUBITS_PER_VAR =
"The variable/dimension at index ${VAR_IND} was constituted by an invalid number of qubits (${VAR_QUBITS}). Each must correspond to 1 or more qubits.";
string MULTI_VAR_FUNC_MISMATCHING_NUM_QUBITS =
"The total number of qubits constituting all variables/dimensions (${NUM_VAR_QUBITS}) does not match the number of qubits in the matrix (${NUM_MATR_QUBITS}).";
string MULTI_VAR_FUNC_INVALID_ARE_SIGNED_FLAG =
"Invalid value for the 'areSigned' flag (${ARE_SIGNED}), which must instead be 1 or 0 to indicate whether or not to interpret the variable sub-register basis states as signed integers (encoded with two's complement).";
string NESTED_VECTOR_MATRIX_HAS_INCONSISTENT_NUM_COLUMNS =
"The given matrix (a nested list of vectors) had an inconsistent number of columns. The first row had ${FIRST_LEN} columns, while the row at index ${OUTLIER_IND} had ${OUTLIER_LEN} columns.";
/*
* EXISTING MATRIX
*/
string INVALID_COMP_MATR_1_FIELDS =
"Invalid CompMatr1. Targeted ${NUM_QUBITS} qubits (instead of 1) and had a dimension of ${NUM_ROWS}x${NUM_ROWS} (instead of 2x2). It is likely this matrix was not initialised with getCompMatr1().";
string INVALID_COMP_MATR_2_FIELDS =
"Invalid CompMatr2. Targeted ${NUM_QUBITS} qubits (instead of 2) and had a dimension of ${NUM_ROWS}x${NUM_ROWS} (instead of 4x4). It is likely this matrix was not initialised with getCompMatr2().";
string INVALID_COMP_MATR_FIELDS =
"Invalid CompMatr. Targeted ${NUM_QUBITS} qubits and had a dimension of ${NUM_ROWS}x${NUM_ROWS}. It is likely this matrix was not created with createCompMatr().";
string INVALID_DIAG_MATR_1_FIELDS =
"Invalid DiagMatr1. Targeted ${NUM_QUBITS} qubits (instead of 1) and had a dimension of ${NUM_ROWS}x${NUM_ROWS} (instead of 2x2). It is likely this matrix was not initialised with getDiagMatr1().";
string INVALID_DIAG_MATR_2_FIELDS =
"Invalid DiagMatr2. Targeted ${NUM_QUBITS} qubits (instead of 2) and had a dimension of ${NUM_ROWS}x${NUM_ROWS} (instead of 4x4). It is likely this matrix was not initialised with getDiagMatr2().";
string INVALID_DIAG_MATR_FIELDS =
"Invalid DiagMatr. Targeted ${NUM_QUBITS} qubits and had a dimension of ${NUM_ROWS}x${NUM_ROWS}. It is likely this matrix was not created with createDiagMatr().";
string INVALID_FULL_STATE_DIAG_MATR_FIELDS =
"Invalid FullStateDiagMatr. Targeted ${NUM_QUBITS} qubits and had a dimension of ${NUM_ROWS}x${NUM_ROWS}. It is likely this matrix was not created with createFullStateDiagMatr().";
string FULL_STATE_DIAG_MATR_GPU_ACCEL_IN_NON_GPU_ENV =
"Invalid FullStateDiagMatr. Was marked as GPU-accelerated in a non-GPU-accelerated environment, which is impossible. It is likely this matrix was manually modified and/or corrupted.";
string COMP_MATR_NOT_SYNCED_TO_GPU =
"The CompMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncCompMatr() after manually modifying elements, or overwrite all elements with setCompMatr() which automatically synchronises.";
string DIAG_MATR_NOT_SYNCED_TO_GPU =
"The DiagMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncDiagMatr() after manually modifying elements, or overwrite all elements with setDiagMatr() which automatically synchronises.";
string FULL_STATE_DIAG_MATR_NOT_SYNCED_TO_GPU =
"The FullStateDiagMatr has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncFullStateDiagMatr() after manually modifying elements, or overwrite elements in batch with setFullStateDiagMatr() which automatically synchronises.";
string MATRIX_SIZE_MISMATCHES_NUM_TARGETS =
"The given matrix has an inconsistent size (${MATRIX_NUM_QUBITS}) with the specified number of target qubits (${NUM_TARGS}).";
string MATRIX_NOT_UNITARY =
"The given matrix was not (approximately) unitary.";
string UNITARY_DIAG_MATR_EXPONENT_NOT_APPROX_REAL =
"The given exponent was not approximately real (i.e. the imaginary component exceeded epsilon) such that the given diagonal matrix raised to the exponent was no longer approximately unitary. Consider changing the validation epsilon.";
string MATRIX_NOT_HERMITIAN =
"The given matrix was not (approximately) Hermitian.";
string DIAG_MATR_APPROX_ZERO_WHILE_EXPONENT_REAL_AND_NEGATIVE =
"The given exponent was (real and) negative while one or more elements of the diagonal matrix had magnitudes near (within epsilon) to zero, which would cause divergences or divison-by-zero errors.";
string HERMITIAN_DIAG_MATR_NEGATIVE_WHILE_EXPONENT_NOT_INTEGER =
"The given exponent was a non-integer while one or more real components of the given Hermitian diagonal matrix were negative. The exponentiated matrix would ergo contain complex elements which violate Hermiticity. This validation is strict and not affected by the validation epsilon since it is necessary to avoid NaN output from a strictly-real pow() function, used for its improved numerical accuracy over complex pow().";
string INVALID_MATRIX_CPU_ELEMS_PTR =
"The given matrix's outer CPU heap-memory pointer was NULL. This may imply the matrix was prior destroyed and its pointers were manually cleared.";
string MATRIX_GPU_ELEMS_PTR_UNEXPECTEDLY_NULL =
"The given matrix's GPU memory pointer was unexpectedly NULL. This may imply the matrix was prior destroyed and its pointer was manually cleared.";
string MATRIX_GPU_ELEMS_PTR_UNEXPECTEDLY_NOT_NULL =
"The given matrix's GPU memory pointer was non-NULL, implying an allocation, despite the QuEST environment being non-GPU-accelerated. This implies the matrix fields were manually modified and corrupted.";
string FULL_STATE_DIAG_MATR_MISMATCHES_QUREG_DIM =
"The given FullStateDiagMatr operates upon a different number of qubits (${NUM_MATR_QUBITS}) than exists in the Qureg (${NUM_QUREG_QUBITS}).";
string FULL_STATE_DIAG_MATR_IS_DISTRIB_BUT_QUREG_ISNT =
"The given FullStateDiagMatr is distributed but the Qureg is not, which is forbidden. Consider disabling distribution for this matrix via createCustomFullStateDiagMatr().";
/*
* SUPEROPERATOR CREATION
*/
string NEW_SUPER_OP_NUM_QUBITS_NOT_POSITIVE =
"Cannot create a superoperator of ${NUM_QUBITS} qubits. The operator must act upon one or more qubits.";
string NEW_SUPER_OP_NUM_ELEMS_WOULD_EXCEED_QINDEX =
"Cannot create a superoperator of ${NUM_QUBITS} qubits because the matrix would contain a total of 16^${NUM_QUBITS} elements which exceeds the maximum representable index of 'qindex' (permitting up to ${MAX_QUBITS} qubits).";
string NEW_SUPER_OP_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create a superoperator of ${NUM_QUBITS} qubits because the total required memory (${QCOMP_BYTES} * 16^${NUM_QUBITS} bytes) exceeds the maximum representable by size_t. In this deployment, the maximum number of qubits in such a superoperator is ${MAX_QUBITS}";
string NEW_SUPER_OP_CANNOT_FIT_INTO_CPU_MEM =
"Cannot create a superoperator of ${NUM_QUBITS} qubits because the total memory required (${QCOMP_BYTES} * 16^${NUM_QUBITS} bytes) exceeds that available (${RAM_SIZE} bytes).";
string NEW_SUPER_OP_CANNOT_FIT_INTO_GPU_MEM =
"Cannot create a GPU-accelerated superoperator of ${NUM_QUBITS} qubits because the total memory required (${QCOMP_BYTES} * 16^${NUM_QUBITS} bytes) exceeds the available GPU memory (${VRAM_SIZE} bytes).";
string NEW_SUPER_OP_CPU_ELEMS_ALLOC_FAILED =
"Attempted allocation of memory for the superoperator matrix (a total of ${NUM_BYTES} bytes in RAM) failed.";
string NEW_SUPER_OP_GPU_ELEMS_ALLOC_FAILED =
"Attempted allocation of GPU memory (a total of ${NUM_BYTES} in VRAM) for the superoperator matrix failed.";
string NEW_INLINE_SUPER_OP_MATRIX_WRONG_NUM_ROWS =
"The specified number of qubits (${NUM_DECLARED_QUBITS}) in the superoperator is inconsistent with the number of rows in the given matrix (expected ${NUM_DECLARED_ROWS}, received ${GIVEN_DIM}).";
string NEW_INLINE_SUPER_OP_MATRIX_WRONG_NUM_COLS =
"The specified number of qubits (${NUM_DECLARED_QUBITS}) in the superoperator is inconsistent with the number of columns in one or more rows of the given matrix (expected ${NUM_DECLARED_ROWS} columns, received ${GIVEN_DIM}).";
/*
* SUPEROPERATOR INITIALISATION
*/
string SUPER_OP_NEW_MATRIX_ELEMS_WRONG_NUM_ROWS =
"Incompatible number of rows (${GIVEN_DIM}) of elements given to overwrite a ${NUM_QUBITS}-qubit SuperOp, which expects ${EXPECTED_DIM} rows.";
string SUPER_OP_NEW_MATRIX_ELEMS_WRONG_NUM_COLS =
"Incompatible number of columns (${GIVEN_DIM}) in one or more rows of a matrix given to overwrite a ${NUM_QUBITS}-qubit SuperOp, which expects ${EXPECTED_DIM} rows.";
string SUPER_OP_FIELDS_MISMATCH_PARAMS =
"The specified number of qubits (${NUM_PASSED_QUBITS}) differs from the number in the SuperOp (${NUM_OP_QUBITS}).";
/*
* EXISTING SUPEROPERATOR
*/
string INVALID_SUPER_OP_FIELDS =
"The given SuperOp had invalid fields (${NUM_QUBITS} qubits and ${NUM_ROWS} rows), suggesting it was not initialised with createSuperOp().";
string INVALID_SUPER_OP_CPU_MEM_PTR =
"The given SuperOp's pointer to its CPU memory was NULL. This may imply the superoperator was already destroyed and had its memory pointers manually overwritten by the user.";
string INVALID_SUPER_OP_GPU_MEM_PTR =
"The given SuperOp's pointer to its GPU memory was NULL. This may imply the superoperator was already destroyed and had its memory pointers manually overwritten by the user.";
string SUPER_OP_NOT_SYNCED_TO_GPU =
"The SuperOp has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncSuperOp() after manually modifying the superoperator elements, or overwrite all elements with setSuperOp() which will automatically syncrhonise.";
string SUPER_OP_SIZE_MISMATCHES_NUM_TARGETS =
"The SuperOp dimension (${OP_QUBITS} qubits) is inconsistent with the specified number of target qubits (${NUM_TARGS}).";
/*
* KRAUS MAP CREATION
*/
string NEW_KRAUS_MAP_NUM_QUBITS_NOT_POSITIVE =
"Cannot create a Kraus map which acts upon ${NUM_QUBITS} qubits; must target one or more qubits.";
string KRAUS_MAP_MATRICES_TOTAL_ELEMS_WOULD_EXCEED_QINDEX =
"Cannot create a KrausMap with the given number of Kraus operators. The total number of elements between the ${NUM_MATRICES} given ${NUM_QUBITS}-qubit matrices would exceed the maximum number representing by the qindex type. At most, ${MAX_NUM_MATRICES} matrices of that size may be specified.";
string KRAUS_MAP_MATRICES_TOTAL_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create a KrausMap with the given number of Kraus operators. The total memory to store ${NUM_MATRICES} ${NUM_QUBITS}-qubit matrices exceeds that representable by the size_t type. At most, ${MAX_NUM_MATRICES} matrices of that size may be specified.";
string NEW_KRAUS_MAPS_SUPER_OP_NUM_ELEMS_WOULD_EXCEED_QINDEX =
"Cannot create a Kraus map of ${NUM_QUBITS} qubits because the corresponding superoperator would contain more elements (16^${NUM_QUBITS}) than the maximum which can be addressed by the qindex type (16^${MAX_QUBITS}).";
string NEW_KRAUS_MAPS_SUPER_OP_MEM_WOULD_EXCEED_SIZEOF =
"Cannot create a Kraus map of ${NUM_QUBITS} qubits because the size (in bytes) of the necessary memory for its corresponding superoperator (${QCOMP_BYTES} * 16^${NUM_QUBITS} bytes) would overflow size_t. In this deployment, the maximum number of qubits in a Kraus map is ${MAX_QUBITS}.";
string NEW_KRAUS_MAPS_SUPER_OP_CANNOT_FIT_INTO_CPU_MEM =
"Cannot create a Kraus map of ${NUM_QUBITS} qubits because the total memory required by its corresponding superoperator (${QCOMP_BYTES} * 16^${NUM_QUBITS} bytes) exceeds the available memory (${RAM_SIZE} bytes).";
string NEW_KRAUS_MAPS_SUPER_OP_CANNOT_FIT_INTO_GPU_MEM =
"Cannot create a GPU-accelerated Kraus map of ${NUM_QUBITS} qubits because the total memory required by its corresponding superoperator (${QCOMP_BYTES} * 16^${NUM_QUBITS} bytes) exceeds the available GPU memory (${VRAM_SIZE} bytes).";
string NEW_KRAUS_MAPS_SUPER_OP_CPU_ELEMS_ALLOC_FAILED =
"Attempted allocation of memory for the Kraus map's correspondng superoperator matrix (a total of ${NUM_BYTES} bytes in RAM) failed.";
string NEW_KRAUS_MAPS_SUPER_OP_GPU_ELEMS_ALLOC_FAILED =
"Attempted allocation of GPU memory (a total of ${NUM_BYTES} bytes in VRAM) for the Kraus map's corresponding superoperator matrix failed.";
string NEW_KRAUS_MAP_CPU_MATRICES_ALLOC_FAILED =
"Failed to allocate memory (a total of ${NUM_BYTES} bytes) for the KrausMap's ${NUM_MATRICES} ${NUM_QUBITS}-qubit Kraus operator matrices.";
string NEW_INLINE_KRAUS_MAP_INCOMPATIBLE_NUM_NEW_MATRICES =
"Specified ${NUM_EXPECTED} Kraus operators, but passed ${NUM_GIVEN} matrices.";
string NEW_INLINE_KRAUS_MAP_MATRIX_WRONG_NUM_ROWS =
"Specified ${NUM_QUBITS} qubits, but one or more passed matrices have ${NUM_GIVEN_ROWS} rows instead of the expected ${NUM_EXPECTED_ROWS}.";
string NEW_INLINE_KRAUS_MAP_MATRIX_WRONG_NUM_COLS =
"The number of given columns (${NUM_GIVEN_COLS}) in one or more matrices was inconsistent with the specified number of qubits (${NUM_QUBITS}). Every Kraus operator must be specified as a ${NUM_EXPECTED_COLS}x${NUM_EXPECTED_COLS} matrix.";
/*
* KRAUS MAP INITIALISATION
*/
string KRAUS_MAP_NUM_GIVEN_NEW_MATRICES_NOT_POSITIVE =
"Cannot create a Kraus map from ${NUM_MATRICES} matrices; must be given a strictly positive number of matrices.";
string KRAUS_MAP_INCOMPATIBLE_NUM_NEW_MATRICES =
"Passed a number of matrices (${NUM_GIVEN}) which is inconsistent with the number of Kraus operators defined in the map (${NUM_EXPECTED}).";
string KRAUS_MAP_NEW_MATRIX_ELEMS_WRONG_NUM_ROWS =
"One or more of the given matrices had a matrix dimension (${NUM_GIVEN_ROWS} rows) incompatible with the given Kraus map of ${NUM_QUBITS} qubits, which expects matrices with ${NUM_EXPECTED_ROWS} rows.";
string KRAUS_MAP_NEW_MATRIX_ELEMS_WRONG_ROW_DIM =
"One or more of the given matrices had a matrix dimension (${NUM_GIVEN_COLS} columns) incompatible with the given Kraus map of ${NUM_QUBITS} qubits, which expects matrices with ${NUM_EXPECTED_COLS} columns.";
string KRAUS_MAP_FIELDS_MISMATCH_PARAMS =
"The specified number of Kraus operators (${NUM_PASSED_OPS}) and qubits (${NUM_PASSED_QUBITS}) differs from the number in the KrausMap (respectively ${NUM_MAP_OPS} and ${NUM_MAP_QUBITS}).";
/*
* EXISTING KRAUS MAP
*/
string INVALID_KRAUS_MAP_FIELDS =
"Invalid KrausMap. One or more of its fields are invalid or inconsistent; it consists of ${NUM_MATRICES} Kraus operators, each upon ${NUM_QUBITS} qubits, with matrices of dimension ${NUM_ROWS}x${NUM_ROWS}. It is likely this Kraus map was not created with createKrausMap().";
string INVALID_KRAUS_MAPS_SUPER_OP_FIELDS =
"The given KrausMap's superoperator had invalid fields (${NUM_QUBITS} qubits and ${NUM_ROWS} rows), suggesting the map was not initialised with createKrausMap().";
string INVALID_KRAUS_MAP_SUPER_OP_NUM_QUBITS =
"Invalid KrausMap. The ${MAP_QUBITS}-qubit KrausMap's superoperator had an incompatible dimension of ${SUPER_OP_QUBITS}. This suggests the Kraus map was not created using createKrausMap(), or was not initialised with setKrausMap().";
string INVALID_KRAUS_MAP_IS_CPTP_PTR =
"The 'isApproxCPTP' field of the given KrausMap was a NULL pointer, instead of the expected pointer to persistent heap memory. This suggests the KrausMap was already destroyed and had its fields overwritten by the user.";
string INVALID_KRAUS_MAP_IS_CPTP_FLAG =
"The 'isApproxCPTP' field of the given Kraus map had invalid value ${BAD_FLAG}, suggesting it was manually modified. Valid values are 0, 1 and ${UNKNOWN_FLAG} (to indicate that unitarity is not yet known, deferring evaluation) although this need never be modified by the user.";
string INVALID_KRAUS_MAPS_SUPER_OP_CPU_MEM_PTR =
"The given KrausMap's superoperator had a NULL pointer where its CPU memory address was expected. This may imply the Kraus map was already destroyed and had its memory pointers manually overwritten by the user.";
string INVALID_KRAUS_MAPS_SUPER_OP_GPU_MEM_PTR =
"The given KrausMap's superoperator had a NULL pointer where its GPU memory address was expected. This may imply the Kraus map was already destroyed and had its memory pointers manually overwritten by the user.";
string INVALID_KRAUS_MAP_MATRIX_LIST_MEM_PTR =
"The KrausMap's list of Kraus operator matrices was unexpectedly a NULL pointer. This might imply the map was already destroyed and had its CPU memory pointers manually overwritten by the user.";
string KRAUS_MAP_NOT_SYNCED_TO_GPU =
"The KrausMap has yet not been synchronised with its persistent GPU memory, so potential changes to its elements are being ignored. Please call syncKrausMap() after manually modifying the superoperator elements, or overwrite all elements with setKrausMap() which will automatically syncrhonise.";
string KRAUS_MAP_NOT_CPTP =
"The KrausMap was not (approximately) completely positive and trace preserving (CPTP).";
string KRAUS_MAP_SIZE_MISMATCHES_TARGETS =
"The KrausMap has a size (${KRAUS_QUBITS} qubits) inconsistent with the specified number of target qubits (${TARG_QUBITS}).";
/*
* PAULI STRING CREATION
*/
string NEW_PAULI_STR_NON_POSITIVE_NUM_PAULIS =
"Invalid number of Paulis (${NUM_PAULIS}). The Pauli string must contain at least one Pauli operator, which is permittedly identity.";
string NEW_PAULI_STR_NUM_PAULIS_EXCEEDS_TYPE =
"Cannot make a Pauli string of ${NUM_PAULIS} Paulis since this exceeds the maximum of ${MAX_PAULIS} imposed by the typing of PauliStr's fields.";
/// @todo replace BAD_CHAR ascii code with actual character, once tokenSubs is generalised to any-type
string NEW_PAULI_STR_UNRECOGNISED_PAULI_CHAR =
"Given an unrecognised Pauli character (ASCII code ${BAD_CHAR}) at index ${CHAR_IND}. Each character must be one of I X Y Z (or lower case), or equivalently 0 1 2 3'.";
string NEW_PAULI_STR_INVALID_PAULI_CODE =
"Given an invalid Pauli code (${BAD_CODE}) at index ${CODE_IND}. Each code must be one of 0 1 2 3, corresponding respectively to I X Y Z.";
string NEW_PAULI_STR_TERMINATION_CHAR_TOO_EARLY =
"The given string contained fewer characters (${TERM_IND}) than the specified number of Pauli operators (${NUM_PAULIS}).";
string NEW_PAULI_STR_INVALID_INDEX =
"Invalid index (${BAD_IND}). Pauli indices must be non-negative and cannot equal nor exceed the maximum number of representable Pauli operators (${MAX_PAULIS}).";
string NEW_PAULI_STR_DUPLICATED_INDEX =
"The Pauli indices contained a duplicate. Indices must be unique.";
string NEW_PAULI_STR_DIFFERENT_NUM_CHARS_AND_INDICES =
"Given a different number of Pauli operators (${NUM_PAULIS}) and their qubit indices (${NUM_INDS}).";
/*
* EXISTING PAULI STRING
*/
string PAULI_STR_TARGETS_EXCEED_QUREG =
"The highest-index non-identity Pauli operator (index ${MAX_TARG}) in the given PauliStr exceeds the maximum target of the ${QUREG_QUBITS}-qubit Qureg.";
string PAULI_STR_OVERLAPS_CONTROLS =
"A control qubit overlaps a non-identity Pauli operator in the given PauliStr.";
/*
* PAULI STRING SUM CREATION
*/
string NEW_PAULI_STR_SUM_NON_POSITIVE_NUM_STRINGS =
"Cannot create a sum with ${NUM_TERMS} terms. The number of terms must be a positive integer.";
string NEW_PAULI_STR_SUM_DIFFERENT_NUM_STRINGS_AND_COEFFS =
"Given a different number of Pauli strings (${NUM_STRS}) and coefficients ${NUM_COEFFS}.";
string NEW_PAULI_STR_SUM_STRINGS_ALLOC_FAILED =
"Attempted allocation of the PauliStrSum's ${NUM_TERMS}-term array of Pauli strings (${NUM_BYTES} bytes total) unexpectedly failed.";
string NEW_PAULI_STR_SUM_COEFFS_ALLOC_FAILED =
"Attempted allocation of the PauliStrSum's ${NUM_TERMS}-term array of coefficients (${NUM_BYTES} bytes total) unexpectedly failed.";
/*
* PAULI STRING SUM PARSING
*/
string PARSED_PAULI_STR_SUM_UNINTERPRETABLE_LINE =
"Could not interpret line ${LINE_NUMBER} as a coefficient followed by a sequence of Pauli operators.";
string PARSED_PAULI_STR_SUM_INCONSISTENT_NUM_PAULIS_IN_LINE =
"Line ${LINE_NUMBER} specified ${NUM_LINE_PAULIS} Pauli operators which is inconsistent with the number of Paulis of the previous lines (${NUM_PAULIS}).";
string PARSED_PAULI_STR_SUM_COEFF_IS_INVALID =
"The coefficient of line ${LINE_NUMBER} could not be converted to a qcomp, possibly due to it exceeding the valid numerical range.";
string PARSED_STRING_IS_EMPTY =
"The given string was empty (contained only whitespace characters) and could not be parsed.";
/*
* EXISTING PAULI STRING SUM
*/
string INVALID_PAULI_STR_SUM_FIELDS =
"The given PauliStrSum had invalid fields (.numTerms=${NUM_TERMS}), which is likely a result from not being correctly initialised by createPauliStrSum().";
string INVALID_PAULI_STR_HEAP_PTR =
"One or more of the PauliStrumSum's heap pointers was unexpectedly NULL. This might imply the PauliStrSum was already destroyed and had its pointers manually overwritten by the user.";
string PAULI_STR_SUM_NOT_HERMITIAN =
"The given PauliStrSum is not Hermitian.";
string PAULI_STR_SUM_NOT_ALL_I_Z =
"The given PauliStrSum contained X and/or Y operators and is ergo not diagonal, so cannot be used to initialise the given FullStateDiagMatr.";
string PAULI_STR_SUM_EXCEEDS_QUREG_NUM_QUBITS =
"The given PauliStrSum includes non-identity upon a qubit of index ${MAX_IND} and so is only compatible with Quregs of at least ${NUM_PSS_QUBITS} qubits. It cannot act upon, nor initialise, the given ${NUM_QUREG_QUBITS}-qubit Qureg.";
string PAULI_STR_SUM_EXCEEDS_MATR_NUM_QUBITS =
"The given PauliStrSum includes non-identity upon a qubit of index ${MAX_IND} and so is only compatible with FullStateDiagMatr containing at least ${NUM_PSS_QUBITS}. It cannot initialise the given ${NUM_MATR_QUBITS}-qubit FullStateDiagMatr.";
/*
* BASIS STATE INDICES
*/
string INVALID_BASIS_STATE_INDEX =
"Basis state index ${STATE_IND} is invalid for the given ${NUM_QB} qubit Qureg. Index must be greater than or equal to zero, and cannot equal nor exceed the number of unique classical states (2^${NUM_QB} = ${NUM_STATES}).";
string INVALID_BASIS_STATE_ROW_OR_COL =
"The row and column indices (${ROW_IND}, ${COL_IND}) are invalid for the given ${NUM_QB} qubit Qureg. Both indices must be greater than or equal to zero, and neither can equal nor exceed the number of unique classical states (2^${NUM_QB} = ${NUM_STATES}).";
string INVALID_STARTING_BASIS_STATE_INDEX =
"The starting basis state index ${START_IND} is invalid for the given ${NUM_QB} qubit Qureg. Index must be greater than or equal to zero, and cannot equal nor exceed the number of unique classical states (2^${NUM_QB} = ${MAX_IND_EXCL}).";
string INVALID_NUM_BASIS_STATE_INDICES =
"The specified number of amplitudes or basis states (${NUM_INDS}) is invalid for the given ${NUM_QB} qubit Qureg, which contains ${MAX_NUM_INDS_INCL} amplitudes.";
string INVALID_ENDING_BASIS_STATE_INDEX =
"The combination of the starting basis state index (${START_IND}) and the number of amplitudes (${NUM_INDS}) implies an end index of ${END_IND_EXCL} (exclusive) which is invalid for the ${NUM_QB}-qubit ${MAX_IND_EXCL}-amplitude Qureg.";
string INVALID_STARTING_BASIS_ROW_OR_COL =
"Either or both of the starting row and column (${START_ROW} and ${START_COL} respectively) are invalid for the given ${NUM_QB} qubit Qureg. Both indices must be greater than or equal to zero, and cannot exceed equal nor exceed the density matrix dimension of 2^${NUM_QB} = ${MAX_IND_EXCL}.";
string INVALID_NUM_BASIS_ROWS_OR_COLS =
"Either or both of the number of rows and columns (${NUM_ROWS} and ${NUM_COLS} respectively) are invalid for the given ${NUM_QB} qubit Qureg, which has a dimension of ${MAX_NUM_INCL}.";
string INVALID_ENDING_BASIS_ROW_OR_COL =
"The combination of starting (row, column) = (${START_ROW}, ${START_COL}) and number of rows and columns (${NUM_ROWS} and ${NUM_COLS} respectively) implies final (row, column) = (${END_ROW_EXCL}, ${END_COL_EXCL}), which is invalid for the given ${NUM_QB}-qubit ${MAX_END_INCL}-dimension density matrix.";
string INVALID_STARTING_LOCAL_AMP_INDEX =
"The starting local amplitude index ${START_IND} is invalid for the given ${NUM_QB}-qubit ${NUM_AMPS_TOTAL}-amplitude Qureg, distributed as ${MAX_IND_EXCL} amplitudes in each of ${NUM_NODES} nodes. Valid local indices are between 0 (inclusive) and ${MAX_IND_EXCL} (exclusive).";
string INVALID_NUM_LOCAL_AMP_INDICES =
"The specified number of local amplitudes (${NUM_INDS}) to synchronise is invalid for the given ${NUM_QB}-qubit ${NUM_AMPS_TOTAL}-amplitude Qureg, distributed as ${MAX_IND_EXCL} amplitudes in each of ${NUM_NODES} nodes. A valid number of amplitudes is between 0 (inclusive) and ${MAX_IND_EXCL} (inclusive).";
string INVALID_ENDING_LOCAL_AMP_INDEX =
"The combination of the starting local amplitude index (${START_IND}) and the number of amplitudes (${NUM_INDS}) implies an end local index of ${END_IND_EXCL} (exclusive) which is invalid for the ${NUM_QB}-qubit ${NUM_AMPS_TOTAL}-amplitude Qureg distributed over ${NUM_NODES} nodes. Valid end indices must be less than the nmber of local amplitudes, i.e. ${MAX_IND_EXCL}.";
/*
* QUBIT INDICES
*/
string NEGATIVE_OR_ZERO_NUM_TARGETS =
"The specified number of target qubits (${NUM_QUBITS}) is invalid. Must specify one or more targets.";
string NUM_TARGETS_EXCEEDS_QUREG_SIZE =
"The specified number of target qubits (${NUM_QUBITS}) exceeds the number of qubits in the Qureg (${QUREG_QUBITS}).";
string TARGET_LIST_WAS_NULL_PTR =
"Received a NULL pointer where a list of target qubits was expected. It is only valid to pass NULL or nullptr for control qubit lists.";
string INVALID_TARGET_QUBIT =
"Invalid target qubit (${QUBIT_IND}). Must be greater than or equal to zero, and less than the number of qubits in the Qureg (${NUM_QUBITS}).";
string DUPLICATE_TARGET_QUBITS =
"The given target qubits contained duplicates. All qubits must be unique.";
string NEGATIVE_NUM_CONTROLS =
"The specified number of control qubits (${NUM_QUBITS}) is invalid. Must specify zero or more controls.";
string NUM_CONTROLS_EXCEEDS_QUREG_SIZE =
"The specified number of control qubits (${NUM_QUBITS}) exceeds the number of qubits in the Qureg (${QUREG_QUBITS}).";
string NON_EMPTY_CONTROL_LIST_WAS_NULL_PTR =
"Received a NULL pointer for a list of control qubits which was declared to have a non-zero length.";
string INVALID_CONTROL_QUBIT =
"Invalid control qubit (${QUBIT_IND}). Must be greater than or equal to zero, and less than the number of qubits in the Qureg (${NUM_QUBITS}).";
string DUPLICATE_CONTROL_QUBITS =
"The control qubits contained duplicates. All qubits must be unique.";
string CONTROLS_OVERLAP_TARGETS =
"A qubit appeared among both the control and target qubits, which cannot overlap.";
string INVALID_CONTROL_STATE =
"The control qubit at index ${INDEX} has an invalid control-state of ${STATE}. Valid states are 0 and 1.";
string DIFFERENT_NUM_CTRLS_AND_STATES =
"A differing number of control qubits (${NUM_CTRLS}) and control states (${NUM_STATES}) was given.";
/*
* MEASUREMENT PARAMETERS
*/
string ONE_QUBIT_MEASUREMENT_OUTCOME_INVALID =
"The given qubit measurement outcome (${OUTCOME}) is invalid. Valid outcomes are 0 and 1.";
string ONE_QUBIT_MEASUREMENT_OUTCOME_IMPOSSIBLY_UNLIKELY =
"The specified measurement outcome (${OUTCOME}) is impossibly unlikely (i.e. has probability less than epsilon), so the post-measurement state cannot be reliably renormalised.";
string MANY_QUBIT_MEASUREMENTS_OUTCOME_INVALID =
"The given qubit measurement outcome (${OUTCOME}) at index ${INDEX} is invalid. Valid outcomes are 0 and 1.";
string MANY_QUBIT_MEASUREMENT_OUTCOME_IMPOSSIBLY_UNLIKELY =
"The specified multi-qubit measurement outcome (with binary value ${OUTCOME_VALUE}) is impossibly unlikely (i.e. has probability less than epsilon), so the post-measurement state cannot be reliably renormalised.";
string OUTCOME_PROBS_DO_NOT_SUM_TO_ONE =
"The state was unnormalised such that the probabilities of possible outcomes did not sum to one, and ergo cannot be meaningfully sampled.";
string GPU_CANNOT_FIT_TEMP_MEASUREMENT_OUTCOME_PROBS =
"The GPU has less available memory (${MEM_AVAIL} bytes) than that needed (${MEM_NEEDED} bytes) to temporarily store the ${NUM_OUTCOMES} outcome probabilities of the specified ${NUM_QUBITS} qubits.";
string MEASUREMENT_OUTCOMES_MISMATCH_NUM_TARGETS =
"The given number of measurement outcomes (${NUM_OUTCOMES}) is inconsistent with the given number of qubits (${NUM_QUBITS}).";
/*
* MISC GATE PARAMETERS
*/
string ROTATION_AXIS_VECTOR_IS_ZERO =
"The rotation axis vector was all zero, or within epsilion magnitude to the zero vector.";
string CANNOT_FIT_MIXED_STATEVEC_AMPS_INTO_SINGLE_NODE =
"Cannot perform this ${NUM_TARGS}-target operation upon a ${NUM_QUREG_QUBITS}-qubit statevector distributed between ${NUM_NODES} nodes, since each node's communication buffer (with capacity for ${NUM_QUREG_AMPS_PER_NODE} amps) cannot simultaneously store the ${NUM_TARG_AMPS} mixed remote amplitudes.";
string CANNOT_FIT_MIXED_DENSMATR_AMPS_INTO_SINGLE_NODE =
"Cannot perform this ${NUM_TARGS}-target operation upon a ${NUM_QUREG_QUBITS}-qubit density-matrix distributed between ${NUM_NODES} nodes, since each node's communication buffer (with capacity for ${NUM_QUREG_AMPS_PER_NODE} amps) cannot simultaneously store the ${NUM_TARG_AMPS} mixed remote amplitudes.";
string INVALID_TROTTER_ORDER =
"Invalid Trotter order (${ORDER}). The order parameter must be positive and even, or unity.";
string INVALID_TROTTER_REPS =
"Invalid number of Trotter repetitions (${REPS}). The number of repetitions must be positive.";
/*
* CHANNEL PARAMETERS
*/
string INVALID_PROBABILITY =
"The given probability is invalid, and must instead be between 0 and 1 (both inclusive).";
string ONE_QUBIT_DEPHASING_PROB_EXCEEDS_MAXIMAL_MIXING =
"The given one-qubit dephasing probability exceeds that which induces maximal mixing, i.e. 1/2.";
string TWO_QUBIT_DEPHASING_PROB_EXCEEDS_MAXIMAL_MIXING =
"The given two-qubit dephasing probability exceeds that which induces maximal mixing, i.e. 3/4.";
string ONE_QUBIT_DEPOLARISING_PROB_EXCEEDS_MAXIMAL_MIXING =
"The given one-qubit depolarising probability exceeds that which induces maximal mixing, i.e. 3/4.";
string TWO_QUBIT_DEPOLARISING_PROB_EXCEEDS_MAXIMAL_MIXING =
"The given two-qubit depolarising probability exceeds that which induces maximal mixing, i.e. 15/16.";
string ONE_QUBIT_PAULI_CHANNEL_TOTAL_PROBS_EXCEED_ONE =
"The given Pauli error probabilities combine to exceed one.";
string ONE_QUBIT_PAULI_CHANNEL_PROBS_EXCEED_MAXIMAL_MIXING =
"The given Pauli error probabilities exceed that which induce maximal mixing. That is, the probability of any particular X, Y or Z error exceeds that of I (no error).";
/*
* QUREG COMBINATION
*/
string MIXED_QUREG_NOT_DENSITY_MATRIX =
"The first Qureg, which will undergo mixing, must be a density matrix.";
string MIXED_QUREGS_HAVE_DIFFERENT_NUM_QUBITS =
"The given Quregs contain an inconsistent number of qubits (${NUM_A} and ${NUM_B}) and cannot be mixed.";
string MIXED_DENSITY_MATRICES_ARE_DIFFERENTLY_DISTRIBUED =
"The given density matrix Quregs are differently distributed and cannot be mixed.";
string MIXED_DENSITY_MATRIX_LOCAL_BUT_STATEVEC_DISTRIBUTED =
"The given density matrix was local, but the statevector was distributed; this configuration is unsupported (and is ridiculous!).";
string SUPERPOSED_QUREGS_ARE_NOT_ALL_STATEVECTORS =
"Cannot superpose a density matrix. All quregs must be statevectors.";
string SUPERPOSED_QUREGS_HAVE_INCONSISTENT_NUM_QUBITS =
"Cannot superpose Quregs with differing numbers of qubits.";
string SUPERPOSED_QUREGS_HAVE_INCONSISTENT_GPU_DEPLOYMENT =
"Cannot superpose Quregs with inconsistent GPU deployments. All or no Quregs must be GPU-accelerated.";
string SUPERPOSED_QUREGS_HAVE_INCONSISTENT_DISTRIBUTION =
"Cannot superpose Quregs which are inconsistently distributed. All or no Quregs must be distributed.";
string INIT_PURE_STATE_IS_DENSMATR =
"The pure-state Qureg (the second argument) must be a statevector, not a density matrix.";
string INIT_QUREG_HAS_DIFFERENT_NUM_QUBITS_TO_PURE_STATE =
"The pure-state Qureg (the second argument) contained a differing number of qubits (${NUM_PURE_QUBITS}) as the modified Qureg (the first argument) which contained ${NUM_QUREG_QUBITS} qubits.";
string INIT_DENSMATR_LOCAL_BUT_PURE_STATE_DISTRIBUTED =
"The pure-state Qureg cannot be distributed if the larger density-matrix Qureg is not.";
string INIT_STATEVEC_DIFFERING_GPU_DEPLOYMENT_TO_PURE_STATE =
"When the modified Qureg (the first argument) is a statevector, it must have the same GPU deployment as the pure-state Qureg (the second argument).";
string INIT_STATEVEC_DIFFERING_DISTRIBUTION_TO_PURE_STATE =
"When the modified Qureg (the first argument) is a statevector, it must be identically distributed to the pure-state Qureg (the second argument).";
string CLONED_QUREGS_DIFFER_IN_NUM_QUBITS =
"The cloned Qureg has a different number of qubits (${NUM_COPY_QUBITS}) than the target Qureg (${NUM_TARGET_QUBITS}).";
string CLONED_QUREGS_INCONSISTENT_TYPES =
"The cloned and target Quregs must both be statevectors, or both be density matrices.";
string CLONED_QUREGS_HAVE_DIFFERENT_DISTRIBUTIONS =
"The cloned and target Quregs cannot be differently distributed.";
string CLONED_STATEVECS_HAVE_DIFFERENT_GPU_DEPLOYMENTS =
"The cloned and target Quregs (when both are statevectors) must have the same GPU deployment.";
string PRODUCTED_QUREGS_HAVE_DIFFERENT_NUM_QUBITS =
"The given Quregs contained differing numbers of qubits (${NUM_A} and ${NUM_B} qubits respectively) and are incompatible.";
string PRODUCTED_SAME_TYPE_QUREGS_HAVE_DIFFERING_GPU_ACCELS =
"The given Quregs were both statevectors or both density matrices but had differing GPU-accelerations. This is an illegal (and nonsensical) configuration which would invoke unexpectedly poor performance. Consider enabling GPU-aceleration for both registers.";
string PRODUCTED_STATEVEC_DISTRIB_BUT_DENSMATR_LOCAL =
"The given statevector Qureg was distributed while the larger density matrix Qureg was not. This is an illegal (and nonsensical) configuration. Consider distributing the density matrix.";
string QUREG_IS_INCOMPATIBLE_WITH_WORKSPACE =
"The primary Qureg is incompatible with the given workspace Qureg. The Quregs must have the same dimensions and be identically distributed and GPU-accelerated.";
string CALC_FIDELITY_OF_DENSITY_MATRICES_NOT_YET_SUPPORTED =
"Quregs cannot both be density matrices. Calculation of the fidelity between two mixed states is not currently supported.";
string CALC_FIDELITY_NOT_APPROX_REAL =
"The calculated fidelity between the given statevector and density matrix was not approximately real (the imaginary component was beyond epsilon), suggesting the density matrix was unnormalised and/or not Hermitian. Use calcInnerProduct() to find the unnormalised fidelity.";
string CALC_BURES_DISTANCE_MAG_EXCEEDED_ONE =
"The calculation of the Bures distance between statevectors failed, because the magnitude of their inner-product exceeded one (suggesting a complex distance), indicating one or both Quregs were unnormalised.";
string CALC_PURIFIED_DISTANCE_NOT_APPROX_REAL =
"The fidelity between the given statevector and density matrix was not approximately real (suggesting a complex purified distance), indicating the density matrix was unnormalised and/or not Hermitian.";
string CALC_PURIFIED_DISTANCE_REAL_EXCEEDED_ONE =
"The fidelity between the given statevector and density matrix exceed one (suggesting a complex purified distance), indicating either or both Quregs were unnormalised.";
/*
* QUREG MODIFICATION
*/
string QUREG_RENORM_PROB_IS_ZERO =
"Could not renormalise the Qureg because the current total probability is zero, or within epsilon to zero.";
string INVALID_NUM_INIT_PURE_STATES =
"The specified number of random pure states to mix (${NUM_STATES}) is invalid. Must specify 1 or more states.";
/*
* EXPECTATION VALUES