1+ // Copyright (c) Microsoft Corporation.
2+ // Licensed under the MIT License.
3+
4+ #define CATCH_CONFIG_MAIN
5+ #include < catch.hpp>
6+
7+ #include " SparseSimulator.h"
8+ #include " capi.hpp"
9+ #include " capi.cpp" // yes really
10+ #include " factory.hpp"
11+ #include " factory.cpp"
12+ #include " TestHelpers.hpp"
13+
14+ #include < cmath>
15+ #include < iostream>
16+ #include < cstdint>
17+
18+ using namespace Microsoft ::Quantum::SPARSESIMULATOR;
19+ using namespace SparseSimulatorTestHelpers ;
20+
21+ #ifndef M_PI
22+ #define M_PI 3.14159265358979323846
23+ #endif
24+
25+
26+ template <size_t num_qubits>
27+ void MultiExpReferenceTest (
28+ std::function<void (unsigned )> qubit_prep,
29+ std::function<void(unsigned )> qubit_clear
30+ ) {
31+ const qubit_label_type<num_qubits> zero (0 );
32+ logical_qubit_id* qubits = new logical_qubit_id[3 ];
33+ qubits[0 ] = 0 ;
34+ qubits[1 ] = 1 ;
35+ qubits[2 ] = 2 ;
36+ int * Paulis = new int [3 ];
37+ for (int intPaulis = 0 ; intPaulis < 4 * 4 * 4 ; intPaulis++) {
38+ Paulis[0 ] = intPaulis % 4 ;
39+ Paulis[1 ] = (intPaulis / 4 ) % 4 ;
40+ Paulis[2 ] = intPaulis / 16 ;
41+
42+ for (double angle = 0.0 ; angle < M_PI / 2.0 ; angle += 0.1 ) {
43+ unsigned sim = init_cpp (32 );
44+ qubit_prep (sim);
45+
46+ std::vector<amplitude> vector_rep (8 , 0.0 );
47+ for (unsigned i = 0 ; i < 8 ; i++) {
48+ vector_rep[i] = getSimulator (sim)->probe (std::bitset<3 >(i).to_string ());
49+ }
50+ // New simulator Exp
51+ Exp_cpp (sim, 3 , Paulis, angle, qubits);
52+ // Old simulator Exp
53+ std::vector<Gates::Basis> actualPaulis = { (Gates::Basis)Paulis[0 ],(Gates::Basis)Paulis[1 ], (Gates::Basis)Paulis[2 ] };
54+ apply_exp (vector_rep, actualPaulis, angle, std::vector<unsigned >{ 0 , 1 , 2 });
55+ for (unsigned i = 0 ; i < 8 ; i++) {
56+ amplitude result = getSimulator (sim)->probe (std::bitset<3 >(i).to_string ());
57+ assert_amplitude_equality (vector_rep[i], result);
58+ }
59+ Exp_cpp (sim, 3 , Paulis, -angle, qubits);
60+ qubit_clear (sim);
61+ }
62+ }
63+ }
64+
65+ TEST_CASE (" initializationTest" ) {
66+ unsigned sim = init_cpp (32 );
67+ }
68+
69+ TEST_CASE (" AllocationTest" ) {
70+ unsigned sim = init_cpp (32 );
71+ allocateQubit_cpp (sim, 0 );
72+ releaseQubit_cpp (sim, 0 );
73+ }
74+ TEST_CASE (" AllocateRebuildTest" ) {
75+ unsigned sim = init_cpp (64 );
76+ for (int i = 0 ; i < 1024 ; i++) {
77+ allocateQubit_cpp (sim, i);
78+ getSimulator (sim)->X (i);
79+ getSimulator (sim)->update_state ();
80+ }
81+ for (int i = 0 ; i < 1024 ; i++) {
82+ getSimulator (sim)->X (i);
83+ releaseQubit_cpp (sim, i);
84+ }
85+ }
86+
87+ TEST_CASE (" XTest" ) {
88+ unsigned sim = init_cpp (32 );
89+ allocateQubit_cpp (sim, 0 );
90+ X_cpp (sim, 0 );
91+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
92+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 , 0.0 );
93+ X_cpp (sim, 0 );
94+ releaseQubit_cpp (sim, 0 );
95+ }
96+ TEST_CASE (" ZTest" ) {
97+ unsigned sim = init_cpp (32 );
98+ allocateQubit_cpp (sim, 0 );
99+ Z_cpp (sim, 0 );
100+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 1.0 , 0.0 );
101+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 0.0 , 0.0 );
102+ Z_cpp (sim, 0 );
103+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 1.0 , 0.0 );
104+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 0.0 , 0.0 );
105+ X_cpp (sim, 0 );
106+ Z_cpp (sim, 0 );
107+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
108+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), -1.0 , 0.0 );
109+ Z_cpp (sim, 0 );
110+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
111+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 , 0.0 );
112+ X_cpp (sim, 0 );
113+ releaseQubit_cpp (sim, 0 );
114+ }
115+ TEST_CASE (" HTest" ) {
116+ unsigned sim = init_cpp (32 );
117+ allocateQubit_cpp (sim, 0 );
118+ H_cpp (sim, 0 );
119+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 1.0 / sqrt (2.0 ), 0.0 );
120+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 / sqrt (2.0 ), 0.0 );
121+ H_cpp (sim, 0 );
122+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 1.0 , 0.0 );
123+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 0.0 , 0.0 );
124+ X_cpp (sim, 0 );
125+ H_cpp (sim, 0 );
126+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 1.0 / sqrt (2.0 ), 0.0 );
127+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), -1.0 / sqrt (2.0 ), 0.0 );
128+ H_cpp (sim, 0 );
129+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
130+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 , 0.0 );
131+ X_cpp (sim, 0 );
132+ releaseQubit_cpp (sim, 0 );
133+ }
134+
135+ TEST_CASE (" TGateTest" ) {
136+ unsigned sim = init_cpp (32 );
137+ allocateQubit_cpp (sim, 0 );
138+ T_cpp (sim, 0 );
139+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 1.0 , 0.0 );
140+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 0.0 , 0.0 );
141+ X_cpp (sim, 0 );
142+ T_cpp (sim, 0 );
143+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
144+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 / sqrt (2.0 ), 1.0 / sqrt (2.0 ));
145+ T_cpp (sim, 0 );
146+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
147+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 0.0 , 1.0 );
148+ T_cpp (sim, 0 );
149+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
150+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), -1.0 / sqrt (2.0 ), 1.0 / sqrt (2.0 ));
151+ T_cpp (sim, 0 );
152+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
153+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), -1.0 , 0.0 );
154+ T_cpp (sim, 0 );
155+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
156+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), -1.0 / sqrt (2.0 ), -1.0 / sqrt (2.0 ));
157+ T_cpp (sim, 0 );
158+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
159+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 0.0 , -1.0 );
160+ T_cpp (sim, 0 );
161+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
162+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 / sqrt (2.0 ), -1.0 / sqrt (2.0 ));
163+ T_cpp (sim, 0 );
164+ assert_amplitude_equality (getSimulator (sim)->probe (" 0" ), 0.0 , 0.0 );
165+ assert_amplitude_equality (getSimulator (sim)->probe (" 1" ), 1.0 , 0.0 );
166+ X_cpp (sim, 0 );
167+ releaseQubit_cpp (sim, 0 );
168+ }
169+
170+ TEST_CASE (" HCancellationTest" )
171+ {
172+ int n_qubits = 16 ;
173+ unsigned sim = init_cpp (n_qubits);
174+ size_t buckets = 0 ;
175+ for (int i = 0 ; i < n_qubits; i++) {
176+ allocateQubit_cpp (sim, i);
177+ H_cpp (sim, i);
178+ }
179+ for (int i = n_qubits - 1 ; i >= 0 ; i--) {
180+ H_cpp (sim, i);
181+ // If the H do not cancel out, release will fail in an opaque way
182+ releaseQubit_cpp (sim, i);
183+ }
184+ }
185+
186+ TEST_CASE (" HXZCommutationTest" )
187+ {
188+ const int n_qubits = 16 ;
189+ unsigned sim = init_cpp (n_qubits);
190+ for (int i = 0 ; i < n_qubits; i++) {
191+ allocateQubit_cpp (sim, i);
192+ H_cpp (sim, i);
193+ }
194+ std::bitset<n_qubits> one_state = 0 ;
195+ for (int i = 0 ; i < n_qubits - 1 ; i += 2 ) {
196+ Z_cpp (sim, i);
197+ X_cpp (sim, i+1 );
198+ one_state.set (i);
199+ }
200+ for (int i = n_qubits - 1 ; i >= 0 ; i--) {
201+ H_cpp (sim, i);
202+ }
203+ for (std::uint64_t i = 0 ; i < (std::uint64_t {1 } << n_qubits); i++) {
204+ amplitude state = getSimulator (sim)->probe (std::bitset<n_qubits>(i).to_string ());
205+ if (i == one_state.to_ulong ()) {
206+ assert_amplitude_equality (state, 1.0 , 0.0 );
207+ }
208+ else {
209+ assert_amplitude_equality (state, 0.0 , 0.0 );
210+ }
211+ }
212+ }
213+
214+ TEST_CASE (" ResetTest" )
215+ {
216+ const int n_qubits = 16 ;
217+ unsigned sim = init_cpp (n_qubits);
218+ allocateQubit_cpp (sim, 0 );
219+ Reset_cpp (sim, 0 );
220+ amplitude state = getSimulator (sim)->probe (" 0" );
221+ assert_amplitude_equality (state, 1.0 , 0.0 );
222+ X_cpp (sim, 0 );
223+ Reset_cpp (sim, 0 );
224+ state = getSimulator (sim)->probe (" 0" );
225+ // No qubit exists; should have amplitude 0
226+ assert_amplitude_equality (state, 1.0 , 0.0 );
227+ allocateQubit_cpp (sim, 1 );
228+ X_cpp (sim, 0 );
229+ logical_qubit_id* controls = new logical_qubit_id{ 0 };
230+ MCX_cpp (sim, 1 , controls, 1 );
231+ Reset_cpp (sim, 0 );
232+ state = getSimulator (sim)->probe (" 00" );
233+ assert_amplitude_equality (state, 0.0 , 0.0 );
234+ state = getSimulator (sim)->probe (" 10" );
235+ assert_amplitude_equality (state, 1.0 , 0.0 );
236+ Reset_cpp (sim, 1 );
237+ state = getSimulator (sim)->probe (" 00" );
238+ assert_amplitude_equality (state, 1.0 , 0.0 );
239+ state = getSimulator (sim)->probe (" 10" );
240+ assert_amplitude_equality (state, 0.0 , 0.0 );
241+ releaseQubit_cpp (sim, 1 );
242+ releaseQubit_cpp (sim, 0 );
243+ }
244+
245+ TEST_CASE (" MultiExpWithHTest" ) {
246+ const int num_qubits = 32 ;
247+ auto qubit_prep = [](unsigned sim ) {
248+ H_cpp (sim, 0 );
249+ H_cpp (sim, 1 );
250+ H_cpp (sim, 2 );
251+ };
252+ auto qubit_clear = [](unsigned sim) {
253+ H_cpp (sim, 2 );
254+ releaseQubit_cpp (sim, 2 );
255+ H_cpp (sim, 1 );
256+ releaseQubit_cpp (sim, 1 );
257+ H_cpp (sim, 0 );
258+ releaseQubit_cpp (sim, 0 );
259+ };
260+ MultiExpReferenceTest<num_qubits>(qubit_prep, qubit_clear);
261+ }
262+
263+ TEST_CASE (" MultiExpBasisTest" ) {
264+ const int num_qubits = 32 ;
265+ auto qubit_prep = [](unsigned sim, int index) {
266+ if ((index & 1 ) == 0 ) { X_cpp (sim, 0 ); }
267+ if ((index & 2 ) == 0 ) { X_cpp (sim, 1 ); }
268+ if ((index & 4 ) == 0 ) { X_cpp (sim, 2 ); }
269+ };
270+ auto qubit_clear = [](unsigned sim, int index) {
271+ if ((index & 1 ) == 0 ) { X_cpp (sim, 0 ); }
272+ releaseQubit_cpp (sim, 0 );
273+ if ((index & 2 ) == 0 ) { X_cpp (sim, 1 ); }
274+ releaseQubit_cpp (sim, 1 );
275+ if ((index & 4 ) == 0 ) { X_cpp (sim, 2 ); }
276+ releaseQubit_cpp (sim, 2 );
277+ };
278+ for (int i = 0 ; i < 8 ; i++) {
279+ MultiExpReferenceTest<num_qubits>([=](unsigned sim) {qubit_prep (sim, i); }, [=](unsigned sim) {qubit_clear (sim, i); });
280+ }
281+ }
282+
283+ TEST_CASE (" R1Test" ) {
284+ const int num_qubits = 32 ;
285+ amplitude result0;
286+ amplitude result1;
287+ for (double angle = 0.0 ; angle < M_PI / 2.0 ; angle += 0.1 ) {
288+ unsigned sim = init_cpp (num_qubits);
289+ H_cpp (sim, 0 );
290+ R1_cpp (sim, angle, 0 );
291+ result0 = getSimulator (sim)->probe (" 0" );
292+ result1 = getSimulator (sim)->probe (" 1" );
293+ assert_amplitude_equality (result0, 1.0 / sqrt (2.0 ));
294+ assert_amplitude_equality (result1, amplitude (cos (angle), sin (angle))/sqrt (2.0 ));
295+ R1_cpp (sim, -angle, 0 );
296+ result0 = getSimulator (sim)->probe (" 0" );
297+ result1 = getSimulator (sim)->probe (" 1" );
298+ assert_amplitude_equality (result0, 1.0 / sqrt (2.0 ));
299+ assert_amplitude_equality (result1, 1.0 / sqrt (2.0 ));
300+ H_cpp (sim, 0 );
301+ releaseQubit_cpp (sim, 0 );
302+ destroy_cpp (sim);
303+ }
304+ }
0 commit comments