namespace dlib {
template <int bits>
struct gate_traits<w_gate<bits> >
{
static const long num_bits = bits;
static const long dims = dlib::qc_helpers::exp_2_n<num_bits>::value;
}; }
template <int bits>
class w_gate : public gate_exp<w_gate<bits> >
{
/*!
This is the W gate from the Grover algorithm
!*/
public:
w_gate() : gate_exp<w_gate>(*this) {}
static const long num_bits = gate_traits<w_gate>::num_bits;
static const long dims = gate_traits<w_gate>::dims;
const qc_scalar_type operator() (long r, long c) const{
qc_scalar_type res = 2.0/dims;
if (r != c)
return res;
else
return res - 1.0;
}
template <typename exp>
qc_scalar_type compute_state_element (
const matrix_exp<exp>& reg,
long row_idx
) const{
qc_scalar_type temp = sum(reg)*2.0/dims;
// compute this value: temp = temp - reg(row_idx)*2.0/dims + reg(row_idx)*(2.0/dims - 1.0)
temp = temp - reg(row_idx);
return temp;
}
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
int main()
{
// seed the random number generator
rnd.set_seed(cast_to_string(time(0)));
// Pick out some of the gates we will be using below
using namespace dlib::quantum_gates;
const gate<1> h = quantum_gates::hadamard();
const gate<1> z = quantum_gates::z();
const gate<1> x = quantum_gates::x();
const gate<1> i = quantum_gates::noop();
quantum_register reg;
// We will be doing the 12 qubit version of Grover's search algorithm.
const int bits=12;
reg.set_num_bits(bits);
// set the quantum register to its initial state
(i,i, i,i,i,i,i, i,i,i,i,x).apply_gate_to(reg);
// Print out the starting bits
cout << "starting bits: ";
for (int i = reg.num_bits()-1; i >= 0; --i)
cout << reg.probability_of_bit(i);
cout << endl;
// Now apply the Hadamard gate to all the input bits
(h,h, h,h,h,h,h, h,h,h,h,h).apply_gate_to(reg);
// Print out the status
cout << "after Hadamard gate: ";
for (int i = reg.num_bits()-1; i >= 0; --i)
cout << reg.probability_of_bit(i) << " ";
cout << endl;
// Here we do the grover iteration
for (int j = 0; j < 35; ++j)
{
(uf_gate<bits>()).apply_gate_to(reg);
(w_gate<bits-1>(),i).apply_gate_to(reg);
cout << j << " probability: bit 1 = "<< reg.probability_of_bit(1) << ", bit 9 = "<< reg.probability_of_bit(9) << endl;
}
cout << endl;
// Print out the final probability of measuring a 1 for each of the bits
for (int i = reg.num_bits()-1; i >= 1; --i)
cout << "probability for bit "<< i << " = "<< reg.probability_of_bit(i) << endl;
cout << endl;
cout << "The value we want grover's search to find is 257 which means we should measure a bit pattern of 00100000001"<< endl;
cout << "Measured bits: ";
// finally, measure all the bits and print out what they are.
for (int i = reg.num_bits()-1; i >= 1; --i)
cout << reg.measure_bit(i,rnd);
cout << endl;
// Now let's test out the Shor 9 bit encoding
cout << "\n\n\n\nNow let's try playing around with Shor's 9bit error correcting code"<< endl;
// Reset the quantum register to contain a single bit
reg.set_num_bits(1);
// Set the state of this single qubit to some random mixture of the two computational bases
reg.state_vector()(0) = qc_scalar_type(rnd.get_random_double(),rnd.get_random_double());
reg.state_vector()(1) = qc_scalar_type(rnd.get_random_double(),rnd.get_random_double());
// Make sure the state of the quantum register is a unit vector
reg.state_vector() /= sqrt(sum(norm(reg.state_vector())));
cout << "state: "<< trans(reg.state_vector());