summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/quantum_computing
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/quantum_computing')
-rw-r--r--ml/dlib/dlib/quantum_computing/quantum_computing.h863
-rw-r--r--ml/dlib/dlib/quantum_computing/quantum_computing_abstract.h590
2 files changed, 0 insertions, 1453 deletions
diff --git a/ml/dlib/dlib/quantum_computing/quantum_computing.h b/ml/dlib/dlib/quantum_computing/quantum_computing.h
deleted file mode 100644
index afa2e40e7..000000000
--- a/ml/dlib/dlib/quantum_computing/quantum_computing.h
+++ /dev/null
@@ -1,863 +0,0 @@
-// Copyright (C) 2008 Davis E. King (davis@dlib.net)
-// License: Boost Software License See LICENSE.txt for the full license.
-#ifndef DLIB_QUANTUM_COMPUTINg_1_
-#define DLIB_QUANTUM_COMPUTINg_1_
-
-#include <complex>
-#include <cmath>
-#include "../matrix.h"
-#include "../rand.h"
-#include "../enable_if.h"
-#include "../algs.h"
-#include "quantum_computing_abstract.h"
-
-namespace dlib
-{
-
- template <typename T>
- struct gate_traits {};
-
- namespace qc_helpers
- {
-
- // ------------------------------------------------------------------------------------
-
- // This is a template to compute the value of 2^n at compile time
- template <long n>
- struct exp_2_n
- {
- COMPILE_TIME_ASSERT(0 <= n && n <= 30);
- static const long value = exp_2_n<n-1>::value*2;
- };
-
- template <>
- struct exp_2_n<0>
- {
- static const long value = 1;
- };
-
- // ------------------------------------------------------------------------------------
-
- }
-
- typedef std::complex<double> qc_scalar_type;
-
-// ----------------------------------------------------------------------------------------
-
- class quantum_register
- {
- public:
-
- quantum_register()
- {
- set_num_bits(1);
- }
-
- int num_bits (
- ) const
- {
- return num_bits_in_register;
- }
-
- void set_num_bits (
- int num_bits
- )
- {
- // make sure requires clause is not broken
- DLIB_CASSERT(1 <= num_bits && num_bits <= 30,
- "\tvoid quantum_register::set_num_bits()"
- << "\n\tinvalid arguments to this function"
- << "\n\tnum_bits: " << num_bits
- << "\n\tthis: " << this
- );
-
- num_bits_in_register = num_bits;
-
- unsigned long size = 1;
- for (int i = 0; i < num_bits; ++i)
- size *= 2;
-
- state.set_size(size);
-
- zero_all_bits();
- }
-
- void zero_all_bits()
- {
- set_all_elements(state,0);
- state(0) = 1;
- }
-
- void append (
- const quantum_register& reg
- )
- {
- num_bits_in_register += reg.num_bits_in_register;
- state = tensor_product(state, reg.state);
- }
-
- template <typename rand_type>
- bool measure_bit (
- int bit,
- rand_type& rnd
- )
- {
- // make sure requires clause is not broken
- DLIB_CASSERT(0 <= bit && bit < num_bits(),
- "\tbool quantum_register::measure_bit()"
- << "\n\tinvalid arguments to this function"
- << "\n\tbit: " << bit
- << "\n\tnum_bits(): " << num_bits()
- << "\n\tthis: " << this
- );
-
- const bool value = (rnd.get_random_double() < probability_of_bit(bit));
-
- // Next we set all the states where this bit doesn't have the given value to 0
-
- // But first make a mask that selects our bit
- unsigned long mask = 1;
- for (int i = 0; i < bit; ++i)
- mask <<= 1;
-
- // loop over all the elements in the state vector and zero out those that
- // conflict with the measurement we just made.
- for (long r = 0; r < state.nr(); ++r)
- {
- const unsigned long field = r;
- // if this state indicates that the bit should be set and it isn't
- if ((field & mask) && !value)
- {
- state(r) = 0;
- }
- // else if this state indicates that the bit should not be set and it is
- else if (!(field & mask) && value)
- {
- state(r) = 0;
- }
- }
-
- // normalize the state
- state = state/(std::sqrt(sum(norm(state))));
-
- return value;
- }
-
- template <typename rand_type>
- bool measure_and_remove_bit (
- int bit,
- rand_type& rnd
- )
- {
- // make sure requires clause is not broken
- DLIB_CASSERT(0 <= bit && bit < num_bits() && num_bits() > 0,
- "\tbool quantum_register::measure_and_remove_bit()"
- << "\n\tinvalid arguments to this function"
- << "\n\tbit: " << bit
- << "\n\tnum_bits(): " << num_bits()
- << "\n\tthis: " << this
- );
-
-
- const bool value = (rnd.get_random_double() < probability_of_bit(bit));
- quantum_register temp;
- temp.set_num_bits(num_bits()-1);
-
-
- // Next we set all the states where this bit doesn't have the given value to 0
-
- // But first make a mask that selects our bit
- unsigned long mask = 1;
- for (int i = 0; i < bit; ++i)
- mask <<= 1;
-
- long count = 0;
- for (long r = 0; r < state.nr(); ++r)
- {
- const unsigned long field = r;
- // if this basis vector is one that matches the measured state then keep it
- if (((field & mask) != 0) == value)
- {
- temp.state(count) = state(r);
- ++count;
- }
- }
-
- // normalize the state
- temp.state = temp.state/std::sqrt(sum(norm(temp.state)));
-
- temp.swap(*this);
-
- return value;
- }
-
- double probability_of_bit (
- int bit
- ) const
- {
- // make sure requires clause is not broken
- DLIB_CASSERT(0 <= bit && bit < num_bits(),
- "\tdouble quantum_register::probability_of_bit()"
- << "\n\tinvalid arguments to this function"
- << "\n\tbit: " << bit
- << "\n\tnum_bits(): " << num_bits()
- << "\n\tthis: " << this
- );
-
-
- // make a mask that selects our bit
- unsigned long mask = 1;
- for (int i = 0; i < bit; ++i)
- mask <<= 1;
-
- // now find the total probability of all the states that have the given bit set
- double prob = 0;
- for (long r = 0; r < state.nr(); ++r)
- {
- const unsigned long field = r;
- if (field & mask)
- {
- prob += std::norm(state(r));
- }
- }
-
-
- return prob;
- }
-
- const matrix<qc_scalar_type,0,1>& state_vector() const { return state; }
- matrix<qc_scalar_type,0,1>& state_vector() { return state; }
-
- void swap (
- quantum_register& item
- )
- {
- exchange(num_bits_in_register, item.num_bits_in_register);
- state.swap(item.state);
- }
-
- private:
-
- int num_bits_in_register;
- matrix<qc_scalar_type,0,1> state;
- };
-
- inline void swap (
- quantum_register& a,
- quantum_register& b
- ) { a.swap(b); }
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T>
- class gate_exp
- {
- public:
- static const long num_bits = gate_traits<T>::num_bits;
- static const long dims = gate_traits<T>::dims;
-
- gate_exp(T& exp_) : exp(exp_) {}
-
- const qc_scalar_type operator() (long r, long c) const { return exp(r,c); }
-
- const matrix<qc_scalar_type> mat (
- ) const
- {
- matrix<qc_scalar_type,dims,dims> m;
- for (long r = 0; r < m.nr(); ++r)
- {
- for (long c = 0; c < m.nc(); ++c)
- {
- m(r,c) = exp(r,c);
- }
- }
- return m;
- }
-
- void apply_gate_to (quantum_register& reg) const
- {
- // make sure requires clause is not broken
- DLIB_CASSERT(reg.num_bits() == num_bits,
- "\tvoid gate_exp::apply_gate_to()"
- << "\n\tinvalid arguments to this function"
- << "\n\treg.num_bits(): " << reg.num_bits()
- << "\n\tnum_bits: " << num_bits
- << "\n\tthis: " << this
- );
-
-
- quantum_register temp(reg);
-
-
- // check if any of the elements of the register are 1 and if so then
- // we don't have to do the full matrix multiply. Or check if only a small number are non-zero.
- long non_zero_elements = 0;
- for (long r = 0; r < dims; ++r)
- {
- if (reg.state_vector()(r) != qc_scalar_type(0))
- ++non_zero_elements;
-
- reg.state_vector()(r) = 0;
- }
-
-
- if (non_zero_elements > 3)
- {
- // do a full matrix multiply to compute the output state
- for (long r = 0; r < dims; ++r)
- {
- reg.state_vector()(r) = compute_state_element(temp.state_vector(),r);
- }
- }
- else
- {
- // do a matrix multiply but only use the columns in the gate matrix
- // that correspond to the non-zero register elements
- for (long r = 0; r < dims; ++r)
- {
- if (temp.state_vector()(r) != qc_scalar_type(0))
- {
- for (long i = 0; i < dims; ++i)
- {
- reg.state_vector()(i) += temp.state_vector()(r)*exp(i,r);
- }
- }
- }
- }
- }
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(reg.nr() == dims && reg.nc() == 1 &&
- 0 <= row_idx && row_idx < dims,
- "\tqc_scalar_type gate_exp::compute_state_element(reg,row_idx)"
- << "\n\tinvalid arguments to this function"
- << "\n\treg.nr(): " << reg.nr()
- << "\n\treg.nc(): " << reg.nc()
- << "\n\tdims: " << dims
- << "\n\trow_idx: " << row_idx
- << "\n\tthis: " << this
- );
-
-
- return this->exp.compute_state_element(reg,row_idx);
- }
-
- const T& ref() const { return exp; }
-
- private:
- T& exp;
- };
-
-// ----------------------------------------------------------------------------------------
-
-
- template <typename T, typename U>
- class composite_gate;
-
- template <typename T, typename U>
- struct gate_traits<composite_gate<T,U> >
- {
- static const long num_bits = T::num_bits + U::num_bits;
- static const long dims = qc_helpers::exp_2_n<num_bits>::value;
- };
-
- template <typename T, typename U>
- class composite_gate : public gate_exp<composite_gate<T,U> >
- {
- public:
-
- typedef T lhs_type;
- typedef U rhs_type;
-
- composite_gate(const composite_gate& g) : gate_exp<composite_gate>(*this), lhs(g.lhs), rhs(g.rhs) {}
-
- composite_gate(
- const gate_exp<T>& lhs_,
- const gate_exp<U>& rhs_
- ) : gate_exp<composite_gate>(*this), lhs(lhs_.ref()), rhs(rhs_.ref()) {}
-
-
-
- static const long num_bits = gate_traits<composite_gate>::num_bits;
- static const long dims = gate_traits<composite_gate>::dims;
-
- const qc_scalar_type operator() (long r, long c) const { return lhs(r/U::dims,c/U::dims)*rhs(r%U::dims, c%U::dims); }
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(reg.nr() == dims && reg.nc() == 1 &&
- 0 <= row_idx && row_idx < dims,
- "\tqc_scalar_type composite_gate::compute_state_element(reg,row_idx)"
- << "\n\tinvalid arguments to this function"
- << "\n\treg.nr(): " << reg.nr()
- << "\n\treg.nc(): " << reg.nc()
- << "\n\tdims: " << dims
- << "\n\trow_idx: " << row_idx
- << "\n\tthis: " << this
- );
-
-
- qc_scalar_type result = 0;
- for (long c = 0; c < T::dims; ++c)
- {
- if (lhs(row_idx/U::dims,c) != qc_scalar_type(0))
- {
- result += lhs(row_idx/U::dims,c) * rhs.compute_state_element(subm(reg,c*U::dims,0,U::dims,1), row_idx%U::dims);
- }
- }
-
- return result;
- }
-
-
- const T lhs;
- const U rhs;
- };
-
-// ----------------------------------------------------------------------------------------
-
- template <long bits>
- class gate;
- template <long bits>
- struct gate_traits<gate<bits> >
- {
- static const long num_bits = bits;
- static const long dims = qc_helpers::exp_2_n<num_bits>::value;
- };
-
-// ----------------------------------------------------------------------------------------
-
- template <long bits>
- class gate : public gate_exp<gate<bits> >
- {
- public:
- gate() : gate_exp<gate>(*this) { set_all_elements(data,0); }
- gate(const gate& g) :gate_exp<gate>(*this), data(g.data) {}
-
- template <typename T>
- explicit gate(const gate_exp<T>& g) : gate_exp<gate>(*this)
- {
- COMPILE_TIME_ASSERT(T::num_bits == num_bits);
- for (long r = 0; r < dims; ++r)
- {
- for (long c = 0; c < dims; ++c)
- {
- data(r,c) = g(r,c);
- }
- }
- }
-
- static const long num_bits = gate_traits<gate>::num_bits;
- static const long dims = gate_traits<gate>::dims;
-
- const qc_scalar_type& operator() (long r, long c) const { return data(r,c); }
- qc_scalar_type& operator() (long r, long c) { return data(r,c); }
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(reg.nr() == dims && reg.nc() == 1 &&
- 0 <= row_idx && row_idx < dims,
- "\tqc_scalar_type gate::compute_state_element(reg,row_idx)"
- << "\n\tinvalid arguments to this function"
- << "\n\treg.nr(): " << reg.nr()
- << "\n\treg.nc(): " << reg.nc()
- << "\n\tdims: " << dims
- << "\n\trow_idx: " << row_idx
- << "\n\tthis: " << this
- );
-
-
- return (data*reg)(row_idx);
- }
-
- private:
-
- matrix<qc_scalar_type,dims,dims> data;
- };
-
-// ----------------------------------------------------------------------------------------
-
- namespace qc_helpers
- {
- // This is the maximum number of bits used for cached sub-matrices in composite_gate expressions
- const int qc_block_chunking_size = 8;
-
- template <typename T>
- struct is_composite_gate { const static bool value = false; };
- template <typename T, typename U>
- struct is_composite_gate<composite_gate<T,U> > { const static bool value = true; };
-
-
- // These overloads all deal with intelligently composing chains of composite_gate expressions
- // such that the resulting expression has the form:
- // (gate_exp,(gate_exp,(gate_exp,(gate_exp()))))
- // and each gate_exp contains a cached gate matrix for a gate of at most qc_block_chunking_size bits.
- // This facilitates the optimizations in the compute_state_element() function.
- template <typename T, typename U, typename V, typename enabled = void>
- struct combine_gates;
-
- // This is a base case of this recursive template. It takes care of converting small composite_gates into
- // cached gate objects.
- template <typename T, typename U, typename V>
- struct combine_gates<T,U,V,typename enable_if_c<(T::num_bits + U::num_bits <= qc_block_chunking_size)>::type >
- {
- typedef composite_gate<gate<T::num_bits + U::num_bits>,V> result_type;
-
- static const result_type eval (
- const composite_gate<T,U>& lhs,
- const gate_exp<V>& rhs
- )
- {
- typedef gate<T::num_bits + U::num_bits> gate_type;
- return composite_gate<gate_type,V>(gate_type(lhs), rhs);
- }
- };
-
- // this is the recursive step of this template
- template <typename T, typename U, typename V>
- struct combine_gates<T,U,V,typename enable_if_c<(is_composite_gate<U>::value == true)>::type >
- {
- typedef typename combine_gates<typename U::lhs_type, typename U::rhs_type, V>::result_type inner_type;
- typedef composite_gate<T,inner_type> result_type;
-
- static const result_type eval (
- const composite_gate<T,U>& lhs,
- const gate_exp<V>& rhs
- )
- {
- return composite_gate<T,inner_type>(lhs.lhs, combine_gates<typename U::lhs_type, typename U::rhs_type, V>::eval(lhs.rhs,rhs));
- }
-
- };
-
- // This is a base case of this recursive template. It takes care of adding new gates when the left
- // hand side is too big to just turn it into a cached gate object.
- template <typename T, typename U, typename V>
- struct combine_gates<T,U,V,typename enable_if_c<(T::num_bits + U::num_bits > qc_block_chunking_size &&
- is_composite_gate<U>::value == false)>::type >
- {
- typedef composite_gate<T,composite_gate<U, V> > result_type;
-
- static const result_type eval (
- const composite_gate<T,U>& lhs,
- const gate_exp<V>& rhs
- )
- {
- return result_type(lhs.lhs, composite_gate<U,V>(lhs.rhs, rhs));
- }
-
- };
-
- }
-
- template <typename T, typename U>
- const composite_gate<T,U> operator, (
- const gate_exp<T>& lhs,
- const gate_exp<U>& rhs
- )
- {
- return composite_gate<T,U>(lhs,rhs);
- }
-
- template <typename T, typename U, typename V>
- const typename qc_helpers::combine_gates<T,U,V>::result_type operator, (
- const composite_gate<T,U>& lhs,
- const gate_exp<V>& rhs
- )
- {
- return qc_helpers::combine_gates<T,U,V>::eval(lhs,rhs);
- }
-
- // If you are getting an error here then it means that you are trying to combine a gate expression
- // with an integer somewhere (and that is an error).
- template <typename T> void operator, ( const gate_exp<T>&, int) { COMPILE_TIME_ASSERT(sizeof(T) > 100000000); }
- template <typename T> void operator, ( int, const gate_exp<T>&) { COMPILE_TIME_ASSERT(sizeof(T) > 100000000); }
-
-// ----------------------------------------------------------------------------------------
-
- namespace quantum_gates
- {
- template <int control_bit, int target_bit>
- class cnot;
-
- template <int control_bit1, int control_bit2, int target_bit>
- class toffoli;
- }
-
- template <int control_bit, int target_bit>
- struct gate_traits<quantum_gates::cnot<control_bit, target_bit> >
- {
- static const long num_bits = tabs<control_bit-target_bit>::value+1;
- static const long dims = qc_helpers::exp_2_n<num_bits>::value;
- };
-
- template <int control_bit1, int control_bit2, int target_bit>
- struct gate_traits<quantum_gates::toffoli<control_bit1, control_bit2, target_bit> >
- {
- static const long num_bits = tmax<tabs<control_bit1-target_bit>::value,
- tabs<control_bit2-target_bit>::value>::value+1;
- static const long dims = qc_helpers::exp_2_n<num_bits>::value;
- };
-
-
-// ----------------------------------------------------------------------------------------
-
- namespace quantum_gates
- {
-
- inline const gate<1> hadamard(
- )
- {
- gate<1> h;
- h(0,0) = std::sqrt(1/2.0);
- h(0,1) = std::sqrt(1/2.0);
- h(1,0) = std::sqrt(1/2.0);
- h(1,1) = -std::sqrt(1/2.0);
- return h;
- }
-
- // ------------------------------------------------------------------------------------
-
- inline const gate<1> x(
- )
- {
- gate<1> x;
- x(0,1) = 1;
- x(1,0) = 1;
- return x;
- }
-
- // ------------------------------------------------------------------------------------
-
- inline const gate<1> y(
- )
- {
- gate<1> x;
- qc_scalar_type i(0,1);
- x(0,1) = -i;
- x(1,0) = i;
- return x;
- }
-
- // ------------------------------------------------------------------------------------
-
- inline const gate<1> z(
- )
- {
- gate<1> z;
- z(0,0) = 1;
- z(1,1) = -1;
- return z;
- }
-
- // ------------------------------------------------------------------------------------
-
- inline const gate<1> noop(
- )
- {
- gate<1> i;
- i(0,0) = 1;
- i(1,1) = 1;
- return i;
- }
-
- // ------------------------------------------------------------------------------------
-
- template <int control_bit, int target_bit>
- class cnot : public gate_exp<cnot<control_bit, target_bit> >
- {
- public:
- COMPILE_TIME_ASSERT(control_bit != target_bit);
-
- cnot() : gate_exp<cnot>(*this)
- {
- const int min_bit = std::min(control_bit, target_bit);
-
- control_mask = 1;
- target_mask = 1;
-
- // make the masks so that their only on bit corresponds to the given control_bit and target_bit bits
- for (int i = 0; i < control_bit-min_bit; ++i)
- control_mask <<= 1;
- for (int i = 0; i < target_bit-min_bit; ++i)
- target_mask <<= 1;
- }
-
- static const long num_bits = gate_traits<cnot>::num_bits;
- static const long dims = gate_traits<cnot>::dims;
-
- const qc_scalar_type operator() (long r, long c) const
- {
- unsigned long output;
- // if the input control bit is set
- if (control_mask&c)
- {
- output = c^target_mask;
- }
- else
- {
- output = c;
- }
-
- if ((unsigned long)r == output)
- return 1;
- else
- return 0;
- }
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(reg.nr() == dims && reg.nc() == 1 &&
- 0 <= row_idx && row_idx < dims,
- "\tqc_scalar_type cnot::compute_state_element(reg,row_idx)"
- << "\n\tinvalid arguments to this function"
- << "\n\treg.nr(): " << reg.nr()
- << "\n\treg.nc(): " << reg.nc()
- << "\n\tdims: " << dims
- << "\n\trow_idx: " << row_idx
- << "\n\tthis: " << this
- );
-
-
- unsigned long output = row_idx;
- // if the input control bit is set
- if (control_mask&output)
- {
- output = output^target_mask;
- }
-
- return reg(output);
- }
-
- private:
-
- unsigned long control_mask;
- unsigned long target_mask;
-
-
- };
-
- // ------------------------------------------------------------------------------------
-
- template <int control_bit1, int control_bit2, int target_bit>
- class toffoli : public gate_exp<toffoli<control_bit1, control_bit2, target_bit> >
- {
- public:
- COMPILE_TIME_ASSERT(control_bit1 != target_bit && control_bit2 != target_bit && control_bit1 != control_bit2);
- COMPILE_TIME_ASSERT((control_bit1 < target_bit && control_bit2 < target_bit) ||(control_bit1 > target_bit && control_bit2 > target_bit) );
-
- toffoli() : gate_exp<toffoli>(*this)
- {
- const int min_bit = std::min(std::min(control_bit1, control_bit2), target_bit);
-
- control1_mask = 1;
- control2_mask = 1;
- target_mask = 1;
-
- // make the masks so that their only on bit corresponds to the given control_bit1 and target_bit bits
- for (int i = 0; i < control_bit1-min_bit; ++i)
- control1_mask <<= 1;
- for (int i = 0; i < control_bit2-min_bit; ++i)
- control2_mask <<= 1;
- for (int i = 0; i < target_bit-min_bit; ++i)
- target_mask <<= 1;
- }
-
- static const long num_bits = gate_traits<toffoli>::num_bits;
- static const long dims = gate_traits<toffoli>::dims;
-
- const qc_scalar_type operator() (long r, long c) const
- {
- unsigned long output;
- // if the input control bits are set
- if ((control1_mask&c) && (control2_mask&c))
- {
- output = c^target_mask;
- }
- else
- {
- output = c;
- }
-
- if ((unsigned long)r == output)
- return 1;
- else
- return 0;
- }
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const
- {
- // make sure requires clause is not broken
- DLIB_ASSERT(reg.nr() == dims && reg.nc() == 1 &&
- 0 <= row_idx && row_idx < dims,
- "\tqc_scalar_type toffoli::compute_state_element(reg,row_idx)"
- << "\n\tinvalid arguments to this function"
- << "\n\treg.nr(): " << reg.nr()
- << "\n\treg.nc(): " << reg.nc()
- << "\n\tdims: " << dims
- << "\n\trow_idx: " << row_idx
- << "\n\tthis: " << this
- );
-
-
- unsigned long output;
- // if the input control bits are set
- if ((control1_mask&row_idx) && (control2_mask&row_idx))
- {
- output = row_idx^target_mask;
- }
- else
- {
- output = row_idx;
- }
-
- return reg(output);
-
- }
-
- private:
-
- unsigned long control1_mask;
- unsigned long control2_mask;
- unsigned long target_mask;
-
-
- };
-
-
- // ------------------------------------------------------------------------------------
-
- }
-
-// ----------------------------------------------------------------------------------------
-
-}
-
-#endif // DLIB_QUANTUM_COMPUTINg_1_
-
-
diff --git a/ml/dlib/dlib/quantum_computing/quantum_computing_abstract.h b/ml/dlib/dlib/quantum_computing/quantum_computing_abstract.h
deleted file mode 100644
index bcc65af23..000000000
--- a/ml/dlib/dlib/quantum_computing/quantum_computing_abstract.h
+++ /dev/null
@@ -1,590 +0,0 @@
-// Copyright (C) 2008 Davis E. King (davis@dlib.net)
-// License: Boost Software License See LICENSE.txt for the full license.
-#undef DLIB_QUANTUM_COMPUTINg_ABSTRACT_
-#ifdef DLIB_QUANTUM_COMPUTINg_ABSTRACT_
-
-#include <complex>
-#include "../matrix.h"
-#include "../rand.h"
-
-namespace dlib
-{
-
-// ----------------------------------------------------------------------------------------
-
- typedef std::complex<double> qc_scalar_type;
-
-// ----------------------------------------------------------------------------------------
-
- class quantum_register
- {
- /*!
- INITIAL VALUE
- - num_bits() == 1
- - state_vector().nr() == 2
- - state_vector().nc() == 1
- - state_vector()(0) == 1
- - state_vector()(1) == 0
- - probability_of_bit(0) == 0
-
- - i.e. This register represents a single quantum bit and it is
- completely in the 0 state.
-
- WHAT THIS OBJECT REPRESENTS
- This object represents a set of quantum bits.
- !*/
-
- public:
-
- quantum_register(
- );
- /*!
- ensures
- - this object is properly initialized
- !*/
-
- int num_bits (
- ) const;
- /*!
- ensures
- - returns the number of quantum bits in this register
- !*/
-
- void set_num_bits (
- int new_num_bits
- );
- /*!
- requires
- - 1 <= new_num_bits <= 30
- ensures
- - #num_bits() == new_num_bits
- - #state_vector().nr() == 2^new_num_bits
- (i.e. the size of the state_vector is exponential in the number of bits in a register)
- - for all valid i:
- - probability_of_bit(i) == 0
- !*/
-
- void zero_all_bits(
- );
- /*!
- ensures
- - for all valid i:
- - probability_of_bit(i) == 0
- !*/
-
- void append (
- const quantum_register& reg
- );
- /*!
- ensures
- - #num_bits() == num_bits() + reg.num_bits()
- - #this->state_vector() == tensor_product(this->state_vector(), reg.state_vector())
- - The original bits in *this become the high order bits of the resulting
- register and all the bits in reg end up as the low order bits in the
- resulting register.
- !*/
-
- double probability_of_bit (
- int bit
- ) const;
- /*!
- requires
- - 0 <= bit < num_bits()
- ensures
- - returns the probability of measuring the given bit and it being in the 1 state.
- - The returned value is also equal to the sum of norm(state_vector()(i)) for all
- i where the bit'th bit in i is set to 1. (note that the lowest order bit is bit 0)
- !*/
-
- template <typename rand_type>
- bool measure_bit (
- int bit,
- rand_type& rnd
- );
- /*!
- requires
- - 0 <= bit < num_bits()
- - rand_type == an implementation of dlib/rand/rand_float_abstract.h
- ensures
- - measures the given bit in this register. Let R denote the boolean
- result of the measurement, where true means the bit was measured to
- have value 1 and false means it had a value of 0.
- - if (R == true) then
- - returns true
- - #probability_of_bit(bit) == 1
- - else
- - returns false
- - #probability_of_bit(bit) == 0
- !*/
-
- template <typename rand_type>
- bool measure_and_remove_bit (
- int bit,
- rand_type& rnd
- );
- /*!
- requires
- - num_bits() > 1
- - 0 <= bit < num_bits()
- - rand_type == an implementation of dlib/rand/rand_float_abstract.h
- ensures
- - measures the given bit in this register. Let R denote the boolean
- result of the measurement, where true means the bit was measured to
- have value 1 and false means it had a value of 0.
- - #num_bits() == num_bits() - 1
- - removes the bit that was measured from this register.
- - if (R == true) then
- - returns true
- - else
- - returns false
- !*/
-
- const matrix<qc_scalar_type,0,1>& state_vector(
- ) const;
- /*!
- ensures
- - returns a const reference to the state vector that describes the state of
- the quantum bits in this register.
- !*/
-
- matrix<qc_scalar_type,0,1>& state_vector(
- );
- /*!
- ensures
- - returns a non-const reference to the state vector that describes the state of
- the quantum bits in this register.
- !*/
-
- void swap (
- quantum_register& item
- );
- /*!
- ensures
- - swaps *this and item
- !*/
-
- };
-
- inline void swap (
- quantum_register& a,
- quantum_register& b
- ) { a.swap(b); }
- /*!
- provides a global swap function
- !*/
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T>
- class gate_exp
- {
- /*!
- REQUIREMENTS ON T
- T must be some object that inherits from gate_exp and implements its own
- version of operator() and compute_state_element().
-
- WHAT THIS OBJECT REPRESENTS
- This object represents an expression that evaluates to a quantum gate
- that operates on T::num_bits qubits.
-
- This object makes it easy to create new types of gate objects. All
- you need to do is inherit from gate_exp in the proper way and
- then you can use your new gate objects in conjunction with all the
- others.
- !*/
-
- public:
-
- static const long num_bits = T::num_bits;
- static const long dims = T::dims;
-
- gate_exp(
- T& exp
- );
- /*!
- ensures
- - #&ref() == &exp
- !*/
-
- const qc_scalar_type operator() (
- long r,
- long c
- ) const;
- /*!
- requires
- - 0 <= r < dims
- - 0 <= c < dims
- ensures
- - returns ref()(r,c)
- !*/
-
- void apply_gate_to (
- quantum_register& reg
- ) const;
- /*!
- requires
- - reg.num_bits() == num_bits
- ensures
- - applies this quantum gate to the given quantum register
- - Let M represent the matrix for this quantum gate, then
- #reg().state_vector() = M*reg().state_vector()
- !*/
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const;
- /*!
- requires
- - reg.nr() == dims
- - reg.nc() == 1
- - 0 <= row_idx < dims
- ensures
- - Let M represent the matrix for this gate, then
- this function returns rowm(M*reg, row_idx)
- (i.e. returns the row_idx row of what you get when you apply this
- gate to the given column vector in reg)
- - This function works by calling ref().compute_state_element(reg,row_idx)
- !*/
-
- const T& ref(
- );
- /*!
- ensures
- - returns a reference to the subexpression contained in this object
- !*/
-
- const matrix<qc_scalar_type> mat (
- ) const;
- /*!
- ensures
- - returns a dense matrix object that contains the matrix for this gate
- !*/
- };
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T, typename U>
- class composite_gate : public gate_exp<composite_gate<T,U> >
- {
- /*!
- REQUIREMENTS ON T AND U
- Both must be gate expressions that inherit from gate_exp
-
- WHAT THIS OBJECT REPRESENTS
- This object represents a quantum gate that is the tensor product of
- two other quantum gates.
-
-
- As an example, suppose you have 3 registers, reg_high, reg_low, and reg_all. Also
- suppose that reg_all is what you get when you append reg_high and reg_low,
- so reg_all.state_vector() == tensor_product(reg_high.state_vector(),reg_low.state_vector()).
-
- Then applying a composite gate to reg_all would give you the same thing as
- applying the lhs gate to reg_high and the rhs gate to reg_low and then appending
- the two resulting registers. So the lhs gate of a composite_gate applies to
- the high order bits of a regitser and the rhs gate applies to the lower order bits.
- !*/
- public:
-
- composite_gate (
- const composite_gate& g
- );
- /*!
- ensures
- - *this is a copy of g
- !*/
-
- composite_gate(
- const gate_exp<T>& lhs_,
- const gate_exp<U>& rhs_
- ):
- /*!
- ensures
- - #lhs == lhs_.ref()
- - #rhs == rhs_.ref()
- - #num_bits == T::num_bits + U::num_bits
- - #dims == 2^num_bits
- - #&ref() == this
- !*/
-
- const qc_scalar_type operator() (
- long r,
- long c
- ) const;
- /*!
- requires
- - 0 <= r < dims
- - 0 <= c < dims
- ensures
- - Let M denote the tensor product of lhs with rhs, then this function
- returns M(r,c)
- (i.e. returns lhs(r/U::dims,c/U::dims)*rhs(r%U::dims, c%U::dims))
- !*/
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const;
- /*!
- requires
- - reg.nr() == dims
- - reg.nc() == 1
- - 0 <= row_idx < dims
- ensures
- - Let M represent the matrix for this gate, then this function
- returns rowm(M*reg, row_idx)
- (i.e. returns the row_idx row of what you get when you apply this
- gate to the given column vector in reg)
- - This function works by calling rhs.compute_state_element() and using elements
- of the matrix in lhs.
- !*/
-
- static const long num_bits;
- static const long dims;
-
- const T lhs;
- const U rhs;
- };
-
-// ----------------------------------------------------------------------------------------
-
- template <long bits>
- class gate : public gate_exp<gate<bits> >
- {
- /*!
- REQUIREMENTS ON bits
- 0 < bits <= 30
-
- WHAT THIS OBJECT REPRESENTS
- This object represents a quantum gate that operates on bits qubits.
- It stores its gate matrix explicitly in a dense in-memory matrix.
- !*/
-
- public:
- gate(
- );
- /*!
- ensures
- - num_bits == bits
- - dims == 2^bits
- - #&ref() == this
- - for all valid r and c:
- #(*this)(r,c) == 0
- !*/
-
- gate (
- const gate& g
- );
- /*!
- ensures
- - *this is a copy of g
- !*/
-
- template <typename T>
- explicit gate(
- const gate_exp<T>& g
- );
- /*!
- requires
- - T::num_bits == num_bits
- ensures
- - num_bits == bits
- - dims == 2^bits
- - #&ref() == this
- - for all valid r and c:
- #(*this)(r,c) == g(r,c)
- !*/
-
- const qc_scalar_type& operator() (
- long r,
- long c
- ) const;
- /*!
- requires
- - 0 <= r < dims
- - 0 <= c < dims
- ensures
- - Let M denote the matrix for this gate, then this function
- returns a const reference to M(r,c)
- !*/
-
- qc_scalar_type& operator() (
- long r,
- long c
- );
- /*!
- requires
- - 0 <= r < dims
- - 0 <= c < dims
- ensures
- - Let M denote the matrix for this gate, then this function
- returns a non-const reference to M(r,c)
- !*/
-
- template <typename exp>
- qc_scalar_type compute_state_element (
- const matrix_exp<exp>& reg,
- long row_idx
- ) const;
- /*!
- requires
- - reg.nr() == dims
- - reg.nc() == 1
- - 0 <= row_idx < dims
- ensures
- - Let M represent the matrix for this gate, then this function
- returns rowm(M*reg, row_idx)
- (i.e. returns the row_idx row of what you get when you apply this
- gate to the given column vector in reg)
- !*/
-
- static const long num_bits;
- static const long dims;
-
- };
-
-// ----------------------------------------------------------------------------------------
-
- template <typename T, typename U>
- const composite_gate<T,U> operator, (
- const gate_exp<T>& lhs,
- const gate_exp<U>& rhs
- ) { return composite_gate<T,U>(lhs,rhs); }
- /*!
- ensures
- - returns a composite_gate that represents the tensor product of the lhs
- gate with the rhs gate.
- !*/
-
-// ----------------------------------------------------------------------------------------
-
- namespace quantum_gates
- {
-
- inline const gate<1> hadamard(
- );
- /*!
- ensures
- - returns the Hadamard gate.
- (i.e. A gate with a matrix of
- |1, 1|
- 1/sqrt(2) * |1,-1| )
- !*/
-
- inline const gate<1> x(
- );
- /*!
- ensures
- - returns the not gate.
- (i.e. A gate with a matrix of
- |0, 1|
- |1, 0| )
- !*/
-
- inline const gate<1> y(
- );
- /*!
- ensures
- - returns the y gate.
- (i.e. A gate with a matrix of
- |0,-i|
- |i, 0| )
- !*/
-
- inline const gate<1> z(
- );
- /*!
- ensures
- - returns the z gate.
- (i.e. A gate with a matrix of
- |1, 0|
- |0,-1| )
- !*/
-
- inline const gate<1> noop(
- );
- /*!
- ensures
- - returns the no-op or identity gate.
- (i.e. A gate with a matrix of
- |1, 0|
- |0, 1| )
- !*/
-
- template <
- int control_bit,
- int target_bit
- >
- class cnot : public gate_exp<cnot<control_bit, target_bit> >
- {
- /*!
- REQUIREMENTS ON control_bit AND target_bit
- - control_bit != target_bit
-
- WHAT THIS OBJECT REPRESENTS
- This object represents the controlled-not quantum gate. It is a gate that
- operates on abs(control_bit-target_bit)+1 qubits.
-
- In terms of the computational basis vectors, this gate maps input
- vectors to output vectors in the following way:
- - if (the input vector corresponds to a state where the control_bit
- qubit is 1) then
- - this gate outputs the computational basis vector that
- corresponds to the state where the target_bit has been flipped
- with respect to the input vector
- - else
- - this gate outputs the input vector unmodified
-
- !*/
- };
-
- template <
- int control_bit1,
- int control_bit2,
- int target_bit
- >
- class toffoli : public gate_exp<toffoli<control_bit1, control_bit2, target_bit> >
- {
- /*!
- REQUIREMENTS ON control_bit1, control_bit2, AND target_bit
- - all the arguments denote different bits, i.e.:
- - control_bit1 != target_bit
- - control_bit2 != target_bit
- - control_bit1 != control_bit2
- - The target bit can't be in-between the control bits, i.e.:
- - (control_bit1 < target_bit && control_bit2 < target_bit) ||
- (control_bit1 > target_bit && control_bit2 > target_bit)
-
- WHAT THIS OBJECT REPRESENTS
- This object represents the toffoli variant of a controlled-not quantum gate.
- It is a gate that operates on max(abs(control_bit2-target_bit),abs(control_bit1-target_bit))+1
- qubits.
-
- In terms of the computational basis vectors, this gate maps input
- vectors to output vectors in the following way:
- - if (the input vector corresponds to a state where the control_bit1 and
- control_bit2 qubits are 1) then
- - this gate outputs the computational basis vector that
- corresponds to the state where the target_bit has been flipped
- with respect to the input vector
- - else
- - this gate outputs the input vector unmodified
-
- !*/
- };
-
- // ------------------------------------------------------------------------------------
-
- }
-
-// ----------------------------------------------------------------------------------------
-
-}
-
-#endif // DLIB_QUANTUM_COMPUTINg_ABSTRACT_
-
-
-