mirror of https://github.com/intel/intel-qs.git
150 lines
4.5 KiB
C++
150 lines
4.5 KiB
C++
//------------------------------------------------------------------------------
|
|
// Copyright (C) 2017 Intel Corporation
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "../include/qureg.hpp"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
qhipster::mpi::Environment env(argc, argv);
|
|
if (env.IsUsefulRank() == false) return 0;
|
|
unsigned myrank = env.GetStateRank();
|
|
|
|
#pragma omp parallel
|
|
#pragma omp master
|
|
{
|
|
int nthreads = omp_get_num_threads();
|
|
fprintf(stdout, "OMP number of threads = %d \n", nthreads);
|
|
}
|
|
|
|
|
|
/// --- PARAMETERS ------------------------------------------- ///
|
|
int num_qubits = 8;
|
|
int num_gates = 1;
|
|
/// ---------------------------------------------------------- ///
|
|
std::size_t tmp_size = 0;
|
|
if(argc != 2)
|
|
{
|
|
fprintf(stderr, "usage: %s <num_qubits> \n", argv[0]);
|
|
exit(1);
|
|
}
|
|
else
|
|
{
|
|
int _qubits = atoi(argv[1]);
|
|
|
|
if ((_qubits <= 0) || (_qubits > 1000000)) {
|
|
fprintf(stderr, "<num_qubits> was (%d) which is invalid or negative.\n", _qubits);
|
|
exit(1);
|
|
}
|
|
|
|
num_qubits = (unsigned)_qubits;
|
|
}
|
|
|
|
TM2x2<ComplexDP> G;
|
|
G(0, 0) = {0.592056606032915, 0.459533060553574};
|
|
G(0, 1) = {-0.314948020757856, -0.582328159830658};
|
|
G(1, 0) = {0.658235557641767, 0.070882241549507};
|
|
G(1, 1) = {0.649564427121402, 0.373855203932477};
|
|
|
|
|
|
/// --- RUN SINGLE-QUBIT GATES ------------------------------- ///
|
|
|
|
// Initialize the qubit register in state |A>, then apply the custom one-qubit gate G
|
|
// to each qubit sequentially.
|
|
|
|
QubitRegister<ComplexDP> psi_A(num_qubits, "base", 0);
|
|
// QubitRegister<ComplexDP> psi_A(num_qubits, "rand", -1);
|
|
|
|
// with specialization
|
|
psi_A.TurnOnSpecialize();
|
|
for(int pos = 0; pos < num_qubits; pos++)
|
|
{
|
|
if (myrank == 0) printf(" ---------------------------------- \n");
|
|
psi_A.EnableStatistics();
|
|
psi_A.Apply1QubitGate(pos, G);
|
|
psi_A.GetStatistics();
|
|
psi_A.DisableStatistics();
|
|
}
|
|
|
|
/// --- RUN SINGLE-QUBIT GATES ------------------------------- ///
|
|
|
|
// Initialize two quantum states: |B> and |C>=|B>.
|
|
// Then generate random pairs of control-target qubits.
|
|
// Apply both controlled-gates and one-qubit gates sequentially, first on |B> and
|
|
// then on |C>. The gates on |C> have the specialization 'on'.
|
|
// Verify that the final state |B> and |C> are equivalent.
|
|
|
|
std::vector<std::pair<unsigned, unsigned>> qpair;
|
|
std::default_random_engine generator;
|
|
std::uniform_int_distribution<int> qubit1(0, num_qubits - 1);
|
|
std::uniform_int_distribution<int> qubit2(0, num_qubits - 1);
|
|
unsigned i = 0;
|
|
while (i < 20)
|
|
{
|
|
unsigned q1 = qubit1(generator);
|
|
unsigned q2 = qubit2(generator);
|
|
if (q1 != q2)
|
|
{
|
|
qpair.push_back(std::make_pair(q1, q2));
|
|
i++;
|
|
}
|
|
}
|
|
|
|
qhipster::RandomNumberGenerator<double> rnd_generator;
|
|
rnd_generator.SetSeedStreamPtrs(7777);
|
|
QubitRegister<ComplexDP> psi_B(num_qubits, "base", 0 );
|
|
psi_B.SetRngPtr(&rnd_generator);
|
|
psi_B.Initialize("rand",1);
|
|
|
|
QubitRegister<ComplexDP> psi_C(psi_B);
|
|
|
|
{
|
|
// no specialization
|
|
psi_B.EnableStatistics();
|
|
for (auto &p : qpair) {
|
|
psi_B.ApplyControlled1QubitGate(p.first, p.second, G);
|
|
}
|
|
|
|
for(int pos = 0; pos < num_qubits; pos++) {
|
|
psi_B.Apply1QubitGate(pos, G);
|
|
}
|
|
psi_B.GetStatistics();
|
|
}
|
|
|
|
{
|
|
// with specialization
|
|
psi_C.TurnOnSpecialize();
|
|
psi_C.EnableStatistics();
|
|
for (auto &p : qpair) {
|
|
psi_C.ApplyControlled1QubitGate(p.first, p.second, G);
|
|
}
|
|
|
|
for(int pos = 0; pos < num_qubits; pos++) {
|
|
psi_C.Apply1QubitGate(pos, G);
|
|
}
|
|
psi_C.GetStatistics();
|
|
}
|
|
|
|
double e = psi_C.MaxAbsDiff(psi_B);
|
|
if (myrank == 0)
|
|
printf("Max abs difference between the entries of |B> and |C>:\n e = %lf\n", e);
|
|
|
|
}
|