Skip to content

Commit

Permalink
Merge pull request Qiskit#118 from chriseclectic/rename-ch
Browse files Browse the repository at this point in the history
Rename "ch" method to "extended_stabilizer"
  • Loading branch information
chriseclectic authored Apr 3, 2019
2 parents 6312a2b + e67f314 commit de682e6
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 205 deletions.
115 changes: 60 additions & 55 deletions qiskit/providers/aer/backends/qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Qiskit Aer qasm simulator backend.
"""
Expand Down Expand Up @@ -35,13 +34,13 @@ class QasmSimulator(AerBackend):
* "statevector": Uses a dense statevector simulation.
* "stabilizer": uses a Clifford stabilizer state simulator that
is only valid for Clifford circuits and noise models.
* "ch": Uses an approximate simulator that decomposes circuits
into stabilizer state terms, the number of which grows with the
number of non-Clifford gates.
* "extended_stabilizer": Uses an approximate simulator that
decomposes circuits into stabilizer state terms, the number of
which grows with the number of non-Clifford gates.
* "automatic": automatically run on stabilizer simulator if
the circuit and noise model supports it. If there is enough
available memory, uses the statevector method. Otherwise, uses
the ch method (Default: "automatic").
the extended_stabilizer method (Default: "automatic").
* "available_memory" (int): Set the amount of memory (in MB)
the simulator has access to (Default: Maximum available)
Expand Down Expand Up @@ -90,33 +89,36 @@ class QasmSimulator(AerBackend):
cores. For systems with a small number of cores it enabling
can reduce performance (Default: False).
* "ch_approximation_error" (double): Set the error in the
approximation for the ch method. A smaller error needs more
memory and computational time. (Default: 0.05)
* "extended_stabilizer_approximation_error" (double): Set the error
in the approximation for the extended_stabilizer method. A
smaller error needs more memory and computational time.
(Default: 0.05)
* "ch_disable_measurement_opt" (bool): Force the simulator to
re-run the monte-carlo step for every measurement. Enabling
this will improve the sampling accuracy if the output
* "extended_stabilizer_disable_measurement_opt" (bool): Force the
simulator to re-run the monte-carlo step for every measurement.
Enabling this will improve the sampling accuracy if the output
distribution is strongly peaked, but requires more
computational time. (Default: True)
* "ch_mixing_time" (int): Set how long the monte-carlo method
runs before performing measurements. If the output
distribution is strongly peaked, this can be
decreased alongside setting ch_disable_measurement_opt
* "extended_stabilizer_mixing_time" (int): Set how long the
monte-carlo method runs before performing measurements. If the
output distribution is strongly peaked, this can be decreased
alongside setting extended_stabilizer_disable_measurement_opt
to True. (Default: 5000)
* "ch_norm_estimation_samples" (int): Number of samples used to
compute the correct normalisation for a statevector snapshot.
(Default: 100)
* "extended_stabilizer_norm_estimation_samples" (int): Number of
samples used to compute the correct normalisation for a
statevector snapshot. (Default: 100)
* "ch_parallel_threshold" (int): Set the minimum size of the ch
decomposition before we enable OpenMP parallelisation. If
parallel circuit or shot execution is enabled this will only
use unallocated CPU cores up to max_parallel_threads. (Default: 100)
* "extended_stabilizer_parallel_threshold" (int): Set the minimum
size of the extended stabilizer decomposition before we enable
OpenMP parallelisation. If parallel circuit or shot execution
is enabled this will only use unallocated CPU cores up to
max_parallel_threads. (Default: 100)
"""

MAX_QUBIT_MEMORY = int(log2(local_hardware_info()['memory'] * (1024 ** 3) / 16))
MAX_QUBIT_MEMORY = int(
log2(local_hardware_info()['memory'] * (1024**3) / 16))

DEFAULT_CONFIGURATION = {
'backend_name': 'qasm_simulator',
Expand All @@ -131,42 +133,43 @@ class QasmSimulator(AerBackend):
'max_shots': 100000,
'description': 'A C++ simulator with realistic noise for qobj files',
'coupling_map': None,
'basis_gates': ['u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z',
'h', 's', 'sdg', 't', 'tdg', 'ccx', 'swap',
'snapshot', 'unitary'],
'gates': [
{
'name': 'TODO',
'parameters': [],
'qasm_def': 'TODO'
}
'basis_gates': [
'u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg',
't', 'tdg', 'ccx', 'swap', 'snapshot', 'unitary'
],
'gates': [{
'name': 'TODO',
'parameters': [],
'qasm_def': 'TODO'
}],
# Location where we put external libraries that will be loaded at runtime
# by the simulator extension
'library_dir': os.path.dirname(__file__)
}

def __init__(self, configuration=None, provider=None):
super().__init__(qasm_controller_execute,
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION),
provider=provider)
super().__init__(
qasm_controller_execute,
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION),
provider=provider)

def _validate(self, qobj, backend_options, noise_model):
"""Semantic validations of the qobj which cannot be done via schemas.
1. Check number of qubits will fit in local memory.
2. warn if no classical registers or measurements in circuit.
"""
clifford_instructions = ["id", "x", "y", "z", "h", "s", "sdg",
"CX", "cx", "cz", "swap",
"barrier", "reset", "measure"]
clifford_instructions = [
"id", "x", "y", "z", "h", "s", "sdg", "CX", "cx", "cz", "swap",
"barrier", "reset", "measure"
]
unsupported_ch_instructions = ["u2", "u3"]
# Check if noise model is Clifford:
method = "automatic"
if backend_options and "method" in backend_options:
method = backend_options["method"]

clifford_noise = not (method == "statevector")
clifford_noise = (method != "statevector")

if clifford_noise:
if method != "stabilizer" and noise_model:
Expand All @@ -182,12 +185,13 @@ def _validate(self, qobj, backend_options, noise_model):
name = experiment.header.name
# Check for classical bits
if experiment.config.memory_slots == 0:
logger.warning('No classical registers in circuit "%s": '
'result data will not contain counts.', name)
logger.warning(
'No classical registers in circuit "%s": '
'result data will not contain counts.', name)
# Check if Clifford circuit or if measure opts missing
no_measure = True
ch_supported = False
ch_supported = method in ["ch", "automatic"]
ch_supported = method in ["extended_stabilizer", "automatic"]
clifford = False if method == "statevector" else clifford_noise
for op in experiment.instructions:
if not clifford and not no_measure:
Expand All @@ -200,10 +204,11 @@ def _validate(self, qobj, backend_options, noise_model):
ch_supported = False
# Print warning if clbits but no measure
if no_measure:
logger.warning('No measurements in circuit "%s": '
'count data will return all zeros.', name)
logger.warning(
'No measurements in circuit "%s": '
'count data will return all zeros.', name)
# Check qubits for statevector simulation
if not clifford and method != "ch":
if not clifford and method != "extended_stabilizer":
n_qubits = experiment.config.n_qubits
max_qubits = self.configuration().n_qubits
if n_qubits > max_qubits:
Expand All @@ -217,14 +222,14 @@ def _validate(self, qobj, backend_options, noise_model):
raise AerError(err_string + '.')
else:
if n_qubits > 63:
raise AerError(err_string + ', and has too many ' +
'qubits to fall back to the ' +
'CH simulator.')
raise AerError('{}, and has too many qubits to fall '
'back to the extended_stabilizer '
'method.'.format(err_string))
if not ch_supported:
raise AerError(err_string + ', and contains ' +
'instructions not supported by ' +
'the CH simulator.')
logger.info('The QasmSimulator will automatically '
'switch to the CH backend, based on '
'the memory requirements.')

raise AerError('{}, and contains instructions '
'not supported by the extended_etabilizer '
'method.'.format(err_string))
logger.info(
'The QasmSimulator will automatically '
'switch to the Extended Stabilizer backend, based on '
'the memory requirements.')
30 changes: 0 additions & 30 deletions src/simulators/ch/ch_standalone.cmake

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ bool Runner::check_omp_threshold()

void Runner::apply_pauli_projector(const std::vector<pauli_t> &generators)
{
const int_t END = num_states_;
#pragma omp parallel for if(num_states_ > omp_threshold_ && num_threads_ > 1) num_threads(num_threads_)
for(uint_t i=0; i<num_states_; i++)
for(int_t i=0; i<END; i++)
{
apply_pauli_projector(generators, i);
}
Expand Down Expand Up @@ -401,12 +402,20 @@ double Runner::norm_estimation(uint_t n_samples, AER::RngEngine &rng)
std::vector<uint_t> adiag_1(n_samples, 0ULL);
std::vector<uint_t> adiag_2(n_samples, 0ULL);
std::vector< std::vector<uint_t> > a(n_samples, std::vector<uint_t>(n_qubits_, 0ULL));
#pragma omp parallel for if(num_threads_ > 1) collapse(2) num_threads(num_threads_)
for (size_t l=0; l<n_samples; l++)
const int_t NSAMPLES = n_samples;
const int_t NQUBITS = n_qubits_;
#pragma omp parallel if (num_threads_ > 1) num_threads(num_threads_)
{
for (size_t i=0; i<n_qubits_; i++)
#ifdef _WIN32
#pragma omp for
#else
#pragma omp for collapse(2)
#endif
for (int_t l=0; l<NSAMPLES; l++)
{
for (int_t i=0; i<NQUBITS; i++)
{
for (size_t j=i; j<n_qubits_; j++)
for (int_t j=i; j<NQUBITS; j++)
{
if(rng.rand() < 0.5)
{
Expand All @@ -421,6 +430,7 @@ double Runner::norm_estimation(uint_t n_samples, AER::RngEngine &rng)
}
}
}
} // end omp parallel
return ParallelNormEstimate(states_, coefficients_, adiag_1, adiag_2, a, num_threads_);
}

Expand Down Expand Up @@ -460,8 +470,9 @@ void Runner::init_metropolis(AER::RngEngine &rng)
x_string_ = rng.rand_int(ZERO, max);
last_proposal_=0;
double local_real=0., local_imag=0.;
const int_t END = num_states_;
#pragma omp parallel for if(num_states_ > omp_threshold_ && num_threads_ > 1) num_threads(num_threads_) reduction(+:local_real) reduction(+:local_imag)
for (uint_t i=0; i<num_states_; i++)
for (int_t i=0; i<END; i++)
{
scalar_t amp = states_[i].Amplitude(x_string_);
if(amp.eps == 1)
Expand All @@ -484,8 +495,9 @@ void Runner::metropolis_step(AER::RngEngine &rng)
double real_part = 0.,imag_part =0.;
if (accept_ == 0)
{
const int_t END = num_states_;
#pragma omp parallel for if(num_states_ > omp_threshold_ && num_threads_ > 1) num_threads(num_threads_) reduction(+:real_part) reduction(+:imag_part)
for (uint_t i=0; i<num_states_; i++)
for (int_t i=0; i<END; i++)
{
scalar_t amp = states_[i].ProposeFlip(proposal);
if(amp.eps == 1)
Expand All @@ -498,8 +510,9 @@ void Runner::metropolis_step(AER::RngEngine &rng)
}
else
{
const int_t END = num_states_;
#pragma omp parallel for if(num_states_ > omp_threshold_ && num_threads_ > 1) num_threads(num_threads_) reduction(+:real_part) reduction(+:imag_part)
for (uint_t i=0; i<num_states_; i++)
for (int_t i=0; i<END; i++)
{
states_[i].AcceptFlip();
scalar_t amp = states_[i].ProposeFlip(proposal);
Expand Down Expand Up @@ -564,8 +577,9 @@ complex_t Runner::amplitude(uint_t x_measure)
{
double real_part=0., imag_part=0.;
//Splitting the reduction guarantees support on more OMP versions.
const int_t END = num_states_;
#pragma omp parallel for if(num_states_ > omp_threshold_ && num_threads_ > 1) num_threads(num_threads_) reduction(+:real_part) reduction(+:imag_part)
for(uint_t i=0; i<num_states_; i++)
for(int_t i=0; i<END; i++)
{
complex_t amplitude = states_[i].Amplitude(x_measure).to_complex();
amplitude *= coefficients_[i];
Expand Down Expand Up @@ -609,8 +623,9 @@ inline void to_json(json_t &js, const Runner &rn)
std::vector<std::string> Runner::serialize_decomposition() const
{
std::vector<std::string> serialized_states(num_states_);
const int_t END = num_states_;
#pragma omp parallel for if(num_threads_ > 1 && num_states_ > omp_threshold_) num_threads(num_threads_)
for(uint_t i=0; i<num_states_; i++)
for(int_t i=0; i<END; i++)
{
serialized_states[i] = serialize_state(i).dump();
}
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "gates.hpp"

namespace AER{
namespace CH {
namespace ExtendedStabilizer {

using chpauli_t = CHSimulator::pauli_t;
using chstate_t = CHSimulator::Runner;
Expand All @@ -39,7 +39,7 @@ class State: public Base::State<chstate_t>
State() = default;
virtual ~State() = default;

virtual std::string name() const override {return "ch";}
virtual std::string name() const override {return "extended_stabilizer";}

inline virtual Operations::OpSet::optypeset_t allowed_ops() const override {
return Operations::OpSet::optypeset_t({
Expand Down Expand Up @@ -223,14 +223,18 @@ void State::initialize_qreg(uint_t num_qubits, const chstate_t &state)
void State::set_config(const json_t &config)
{
// Set the error upper bound in the stabilizer rank approximation
JSON::get_value(approximation_error_, "ch_approximation_error", config);
JSON::get_value(approximation_error_, "ch_approximation_error", config); // DEPRECIATED
JSON::get_value(approximation_error_, "extended_stabilizer_approximation_error", config);
// Set the number of samples used in the norm estimation routine
JSON::get_value(norm_estimation_samples_, "ch_norm_estimation_samples", config);
JSON::get_value(norm_estimation_samples_, "ch_norm_estimation_samples", config); // DEPRECIATED
JSON::get_value(norm_estimation_samples_, "extended_stabilizer_norm_estimation_samples", config);
// Set the number of steps used in the metropolis sampler before we
// consider the distribution as approximating the output
JSON::get_value(metropolis_mixing_steps_, "ch_mixing_time", config);
JSON::get_value(metropolis_mixing_steps_, "ch_mixing_time", config); // DEPRECIATED
JSON::get_value(metropolis_mixing_steps_, "extended_stabilizer_mixing_time", config);
//Set the threshold of the decomposition before we use omp
JSON::get_value(omp_threshold_rank_, "ch_parallel_threshold", config);
JSON::get_value(omp_threshold_rank_, "ch_parallel_threshold", config); // DEPRECIATED
JSON::get_value(omp_threshold_rank_, "extended_stabilizer_parallel_threshold", config);
//Set the truncation threshold for the probabilities snapshot.
JSON::get_value(snapshot_chop_threshold_, "chop_threshold", config);
//Set the number of samples for the probabilities snapshot
Expand Down Expand Up @@ -625,7 +629,7 @@ void State::apply_snapshot(const Operations::Op &op, OutputData &data, RngEngine
switch(it->second)
{
case Snapshots::state:
BaseState::snapshot_state(op, data, "ch_state");
BaseState::snapshot_state(op, data, "extended_stabilizer_state");
break;
case Snapshots::cmemory:
BaseState::snapshot_creg_memory(op, data);
Expand Down
File renamed without changes.
Loading

0 comments on commit de682e6

Please sign in to comment.