// Copyright (c) 2012 Vadym Kliuchnikov sqct(dot)software(at)gmail(dot)com, Dmitri Maslov, Michele Mosca // // This file is part of SQCT. // // SQCT is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SQCT is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with SQCT. If not, see . // #include "toptimalitytest.h" #include "output.h" #include "exactdecomposer.h" #include "numbers-stat.h" #include #include using namespace std; static void print_list( std::vector& a, std::vector& b, std::vector& c) { cout << "sde(|.|^2) total min-T max-T" << endl; cout << " gates gates" << endl; for( int i = 0; i < a.size(); ++i ) if( a[i] != 0 ) cout << setw (10) << i << ":" << setw (7) << a[i] << " " << setw (7) << b[i] << " " << setw (7) << c[i] << endl; } toptimalitytest::toptimalitytest() { init(); } //assumes that initial node is identity matrix static void getCircuit( circuit& res, const optNode* node, const vector& genIdToGateId ) { const optNode* current = node; while( current->parent != 0 ) { res.push_front( genIdToGateId[current->gen_id] ); current = current->parent; } } void toptimalitytest::init() { static const gateLibrary& gl = gateLibrary::instance(); const bool verbose = true; typedef matrix2x2 m; ogc.m_generators = { m::X(), m::Y(), m::Z(), m::H(), m::P(), m::P().conjugateTranspose() }; vector genIdToGateId = { gl.X, gl.Y, gl.Z, gl.H, gl.P, gl.Pd }; ogc.m_cost = { 1,2,1,10,40,40 }; ogc.m_initial = { m::Id() }; vector initialGates = { gl.Id }; ogc.m_initial_cost = {0}; ogc.generate(); //produce couning bounds typedef columnsCounter<8> cC; unique_ptr cp( new cC ); cp->generate_all_numbers(); cp->count_all_columns(); //setup bounds for( int i = 0 ; i < cp->sde_stat.size() ; ++i ) og.m_sde_required.at(i) = cp->sde_stat[i]; m_clifford.resize( ogc.unique_elements().size() ); vector pauliCounts( ogc.unique_elements().size() ); auto k = m_clifford.begin(); auto k1 = pauliCounts.begin(); //number of Pauli gates used in each generator if( verbose ) cout << "Single qubit Clifford circuits:" << endl; for( auto i : ogc.unique_elements() ) { getCircuit(*k,i.get(),genIdToGateId); auto counts = k->count(); *k1 = counts[ gl.Z ] + counts[ gl.X ] + counts[ gl.Y ]; if( verbose ) { k->toStreamSym(cout); cout << " " << *k1 << "," << endl; } og.m_generators.push_back( i->unitary * m::T() ); og.m_cost.push_back( 1 ); og.m_initial.push_back( i->unitary ); ++k;++k1; } og.m_initial_cost.resize( og.m_initial.size(), 0 ); og.generate(); if( verbose ) print_list( og.m_sde_found, og.m_min_cost, og.m_max_cost ); /////////////////////////////////////////////////////////////////////////// cout << "Maximal number of Paulies in prefix:" << endl; int maxPauliCounts = 0; for( auto i : og.unique_elements() ) { if( i->unitary.max_sde_abs2() <= 3 ) { const optNode* current = i.get(); int paulis = pauliCounts[current->gen_id]; while( current->parent != 0 ) { current = current->parent; paulis += pauliCounts[current->gen_id]; } maxPauliCounts = std::max( maxPauliCounts, paulis); } } cout << maxPauliCounts << endl; /////////////////////////////////////////////////////////////////////////// exactDecomposer ed; int counter = 0; int nonoptimal = 0; double den = 1.0 / (double) og.unique_elements().size(); cout << "Percent of checked gates:" << endl; for( auto i : og.unique_elements() ) { circuit c; ed.decompose(i->unitary,c); auto counts = gl.toCliffordT(c.count()); int Tc = counts[gl.T] + counts[ gl.Td ]; if( i->cost != Tc ) { cout << "*"; nonoptimal++; } counter++; if( counter % 100000 == 0 ) cout << (double) counter * den << endl; } cerr << "non optimal:" << nonoptimal << endl; }