Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of compute algorithm from arxiv:2101.12223 #1273

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
ca20143
Add AG state for Clifford+phase simulators
or1426 Jun 14, 2021
da04866
Add resize method to binary_vector class
or1426 Jun 14, 2021
73f94b5
add += method to Pauli::Pauli class
or1426 Jun 14, 2021
dc6963c
Add save_specific_probability operation/instruction
or1426 Jun 14, 2021
38141f8
Add compute state class
or1426 Jun 14, 2021
1d31870
add clifford+phase compute algorithm to aer_controller
or1426 Jun 14, 2021
a4cea85
add xorAt method to BinaryVector class
or1426 Jun 14, 2021
54bfd53
remove snapshot code
or1426 Jun 14, 2021
8364caa
fix error in aer_controller
or1426 Jun 14, 2021
9d9a05e
add compute algorithm to aer_simulator.py
or1426 Jun 14, 2021
e77cdcc
fix errors
or1426 Jun 14, 2021
a5f17fe
fix errors
or1426 Jun 14, 2021
04772a9
fix errors
or1426 Jun 16, 2021
51ba8f3
add arbitrary phase gates
or1426 Jun 17, 2021
cafd47e
Merge branch 'Qiskit:main' into main
or1426 Jun 17, 2021
62ff98a
fix linter issues
or1426 Jun 17, 2021
b2a2b29
Merge branch 'main' of https://github.com/or1426/qiskit-aer into main
or1426 Jun 17, 2021
6f70128
remove whitespace for linter
or1426 Jun 17, 2021
17c88d5
Update save_probabilities.py
or1426 Jun 17, 2021
65db315
add docstrings
or1426 Jun 18, 2021
4aba754
merged
or1426 Jun 18, 2021
1047033
Merge branch 'Qiskit:main' into main
or1426 Jun 18, 2021
dc269a7
Merge branch 'Qiskit:main' into main
or1426 Jun 25, 2021
51347d6
reduce length of lines in doc strings
or1426 Jun 25, 2021
76895d4
trailing whitespace
or1426 Jun 25, 2021
8436eec
fix linter issues
or1426 Jun 25, 2021
741c83b
Merge branch 'main' into main
or1426 Jul 19, 2021
7796a82
remove use of designated initializers
or1426 Jul 19, 2021
714a031
Merge branch 'main' into main
or1426 Jul 21, 2021
f7c44a2
replace tab to spaces and fix implicit cast that is not allowed in Wi…
hhorii Aug 16, 2021
87593e4
Merge pull request #1 from hhorii/or1426_fix_ci
or1426 Dec 2, 2021
0c65dd1
fix merge conflicts
or1426 Dec 2, 2021
5c9aa21
Merge branch 'Qiskit-main'
or1426 Dec 2, 2021
633245c
Fix typo in comment
or1426 Dec 2, 2021
3a2651e
fix merge conflict
or1426 Dec 2, 2021
8ee5800
Add save_specific_prob instruction to measurement type case statements
or1426 Dec 14, 2021
ede2628
changes to fix compatibility with new state class
or1426 Dec 14, 2021
7743b95
Merge branch 'main' into main
or1426 Dec 14, 2021
be8c0ca
fix failing build due to new state serialisation code
or1426 Dec 14, 2021
e36d18b
fix type error causing issues on macOS
or1426 Dec 15, 2021
8fcaf43
fix shadowed definitions and signed vs unsigned int comparison
or1426 Dec 15, 2021
d8ac73d
Merge branch 'Qiskit:main' into main
or1426 Dec 15, 2021
7bfd2d4
Merge branch 'Qiskit:main' into main
or1426 Dec 20, 2021
c05574e
correct implementation of compute algorithm for non-T gates
or1426 Feb 9, 2022
535e01d
parallelisation for compute algorithm
or1426 Feb 9, 2022
6327ffd
Merge branch 'Qiskit:main' into main
or1426 Feb 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion qiskit/providers/aer/backends/aer_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ class AerSimulator(AerBackend):
+--------------------------+---------------+
| ``extended_stabilizer`` | No |
+--------------------------+---------------+
| ``compute`` | No |
+--------------------------+---------------+
| ``unitary`` | Yes |
+--------------------------+---------------+
| ``superop`` | No |
Expand Down Expand Up @@ -409,6 +411,9 @@ class AerSimulator(AerBackend):
'extended_stabilizer': sorted([
'quantum_channel', 'qerror_loc', 'roerror', 'snapshot', 'save_statevector'
]),
'clifford_phase_compute': sorted([
'save_specific_probability'
]),
'unitary': sorted([
'snapshot', 'save_state', 'save_unitary', 'set_unitary'
]),
Expand Down Expand Up @@ -449,7 +454,7 @@ class AerSimulator(AerBackend):
_SIMULATION_METHODS = [
'automatic', 'statevector', 'density_matrix',
'stabilizer', 'matrix_product_state', 'extended_stabilizer',
'unitary', 'superop'
'unitary', 'superop', 'clifford_phase_compute'
]

_AVAILABLE_METHODS = None
Expand Down
4 changes: 4 additions & 0 deletions qiskit/providers/aer/backends/backend_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg',
'swap', 'u0', 't', 'tdg', 'u1', 'p', 'ccx', 'ccz', 'delay', 'pauli'
]),
'clifford_phase_compute': sorted([
'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg',
'swap', 't', 'tdg', 'delay', 'p', 'u1', 'rz'
]),
'unitary': sorted([
'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x',
'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,38 @@ def __init__(self,
conditional=conditional)


class SaveSpecificProbability(SaveAverageData):
"""Save a probability for a specific measurement probability."""
def __init__(self, num_qubits,
states, qubits,
label="specific-probabilities",
pershot=False,
conditional=False):
"""Instruction to save specific probabilities.

Args:
states (list): list of ints indicating the outcome to compute the probability for.
qubits (list): list of ints indicating which qubits the measurement is on.
num_qubits (int): the number of qubits for the snapshot type.
label (str): the key for retrieving saved data from results.
pershot (bool): if True save a list of probabilities for each shot
of the simulation rather than the average over
all shots [Default: False].
conditional (bool): if True save the probabilities data conditional
on the current classical register values
[Default: False].
e.g:
if states = [0,1,0], qubits = [0,1,2]
we compute the probability of the outcome 0 on qubit 0, 1 on qubit 1 and 0 on qubit 2
if states = [0,1], qubits = [5,1]
we compute the probability of the outcome 0 on qubit 5 and 1 on qubit 0
"""
super().__init__("save_specific_prob", num_qubits, label,
pershot=pershot,
conditional=conditional,
params=[qubits, states])


def save_probabilities(self,
qubits=None,
label="probabilities",
Expand Down Expand Up @@ -140,5 +172,38 @@ def save_probabilities_dict(self,
return self.append(instr, qubits)


def save_specific_probability(self, states, qubits, label="specific_probability",
pershot=False,
conditional=False):
"""Instruction to save specific probabilities.

Args:
states (list): list of ints indicating the outcome to compute the probability for
qubits (list): list of ints indicating which qubits the measurement is on
label (str): the key for retrieving saved data from results.
pershot (bool): if True save a list of probabilities for each shot
of the simulation rather than the average over
all shots [Default: False].
conditional (bool): if True save the probabilities data conditional
on the current classical register values
[Default: False].
e.g:
if states = [0,1,0], qubits = [0,1,2]
we compute the probability of 0 on qubit 0, 1 on qubit 1 and 0 on qubit 2
if states = [0,1], qubits = [5,1]
we compute the probability of 0 on qubit 5 and 1 on qubit 0

Returns:
QuantumCircuit: with attached instruction.
"""
if qubits is None:
qubits = default_qubits(self)
instr = SaveSpecificProbability(len(qubits), states, qubits, label=label,
pershot=pershot,
conditional=conditional)
return self.append(instr, qubits)


QuantumCircuit.save_probabilities = save_probabilities
QuantumCircuit.save_probabilities_dict = save_probabilities_dict
QuantumCircuit.save_specific_probability = save_specific_probability
23 changes: 21 additions & 2 deletions src/controllers/aer_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#include "simulators/statevector/statevector_state.hpp"
#include "simulators/superoperator/superoperator_state.hpp"
#include "simulators/unitary/unitary_state.hpp"
#include "simulators/clifford_plus_phase/compute.hpp"

namespace AER {

Expand Down Expand Up @@ -111,6 +112,7 @@ class Controller {
matrix_product_state,
stabilizer,
extended_stabilizer,
clifford_phase_compute,
unitary,
superop
};
Expand All @@ -127,6 +129,7 @@ class Controller {
{Method::matrix_product_state, "matrix_product_state"},
{Method::stabilizer, "stabilizer"},
{Method::extended_stabilizer, "extended_stabilizer"},
{Method::clifford_phase_compute, "clifford_phase_compute"},
{Method::unitary, "unitary"},
{Method::superop, "superop"}
};
Expand Down Expand Up @@ -477,6 +480,8 @@ void Controller::set_config(const json_t &config) {
method_ = Method::stabilizer;
} else if (method == "extended_stabilizer") {
method_ = Method::extended_stabilizer;
} else if (method == "clifford_phase_compute") {
method_ = Method::clifford_phase_compute;
} else if (method == "matrix_product_state") {
method_ = Method::matrix_product_state;
} else if (method == "unitary") {
Expand Down Expand Up @@ -673,6 +678,8 @@ void Controller::set_parallelization_circuit(const Circuit &circ,
}
case Method::extended_stabilizer:
break;
case Method::clifford_phase_compute:
break;
default:
throw std::invalid_argument("Cannot set parallelization for unresolved method.");
}
Expand Down Expand Up @@ -1136,7 +1143,10 @@ void Controller::run_circuit(const Circuit &circ, const Noise::NoiseModel &noise
circ, noise, config, Method::extended_stabilizer, result);
case Method::matrix_product_state:
return run_circuit_helper<MatrixProductState::State>(
circ, noise, config, Method::matrix_product_state, result);
circ, noise, config, Method::matrix_product_state, result);
case Method::clifford_phase_compute:
return run_circuit_helper<CliffPhaseCompute::State>(
circ, noise, config, Method::clifford_phase_compute, result);
default:
throw std::runtime_error("Controller:Invalid simulation method");
}
Expand All @@ -1145,7 +1155,6 @@ void Controller::run_circuit(const Circuit &circ, const Noise::NoiseModel &noise
//-------------------------------------------------------------------------
// Utility methods
//-------------------------------------------------------------------------

size_t Controller::required_memory_mb(const Circuit &circ,
const Noise::NoiseModel &noise,
const Method method) const {
Expand Down Expand Up @@ -1198,6 +1207,10 @@ size_t Controller::required_memory_mb(const Circuit &circ,
MatrixProductState::State state;
return state.required_memory_mb(circ.num_qubits, circ.ops);
}
case Method::clifford_phase_compute: {
CliffPhaseCompute::State state;
return state.required_memory_mb(circ.num_qubits, circ.ops);
}
default:
// We shouldn't get here, so throw an exception if we do
throw std::runtime_error("Controller: Invalid simulation method");
Expand Down Expand Up @@ -1674,6 +1687,10 @@ bool Controller::check_measure_sampling_opt(const Circuit &circ,
method == Method::unitary) {
return true;
}

if(method == Method::clifford_phase_compute){
return false;
}

// If circuit contains a non-initial initialize that is not a full width
// instruction we can't sample
Expand Down Expand Up @@ -1884,6 +1901,8 @@ bool Controller::validate_method(Method method,
return validate_state(Stabilizer::State(), circ, noise_model, throw_except);
case Method::extended_stabilizer:
return validate_state(ExtendedStabilizer::State(), circ, noise_model, throw_except);
case Method::clifford_phase_compute:
return validate_state(CliffPhaseCompute::State(), circ, noise_model, throw_except);
case Method::matrix_product_state:
return validate_state(MatrixProductState::State(), circ, noise_model, throw_except);
case Method::statevector:
Expand Down
11 changes: 8 additions & 3 deletions src/framework/circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,15 @@ Circuit::Circuit(const inputdata_t &circ, const json_t &qobj_config, bool trunca
// conversion we could call `get_reversed_ops` on the inputdata without first
// converting.
std::vector<Op> converted_ops;
int i = 0;
for(auto the_op: input_ops){
i += 1;
converted_ops.emplace_back(Operations::input_to_op(the_op));
}
ops = std::move(converted_ops);

ops = std::move(converted_ops);
set_params(truncation);

// Check for specified memory slots
uint_t memory_slots = 0;
Parser<json_t>::get_value(memory_slots, "memory_slots", config);
Expand All @@ -205,7 +208,7 @@ Circuit::Circuit(const inputdata_t &circ, const json_t &qobj_config, bool trunca
// is explicitly disabled.
num_qubits = n_qubits;
}
}
}
}

//-------------------------------------------------------------------------
Expand Down Expand Up @@ -354,6 +357,7 @@ void Circuit::set_params(bool truncation) {
case OpType::save_probs:
case OpType::save_probs_ket:
case OpType::save_amps:
case OpType::save_specific_prob:
case OpType::save_amps_sq:
case OpType::save_stabilizer:
case OpType::save_clifford:
Expand Down Expand Up @@ -490,6 +494,7 @@ bool Circuit::check_result_ancestor(const Op& op, std::unordered_set<uint_t>& an
case OpType::save_densmat:
case OpType::save_probs:
case OpType::save_probs_ket:
case OpType::save_specific_prob:
case OpType::save_amps:
case OpType::save_amps_sq:
case OpType::save_stabilizer:
Expand Down
25 changes: 22 additions & 3 deletions src/framework/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ enum class OpType {
// Save instructions
save_state, save_expval, save_expval_var, save_statevec, save_statevec_dict,
save_densmat, save_probs, save_probs_ket, save_amps, save_amps_sq,
save_stabilizer, save_clifford, save_unitary, save_mps, save_superop,
save_stabilizer, save_clifford, save_unitary, save_mps, save_superop, save_specific_prob,
// Set instructions
set_statevec, set_densmat, set_unitary, set_superop,
set_stabilizer, set_mps,
Expand All @@ -61,8 +61,8 @@ static const std::unordered_set<OpType> SAVE_TYPES = {
OpType::save_statevec, OpType::save_statevec_dict,
OpType::save_densmat, OpType::save_probs, OpType::save_probs_ket,
OpType::save_amps, OpType::save_amps_sq, OpType::save_stabilizer,
OpType::save_clifford,
OpType::save_unitary, OpType::save_mps, OpType::save_superop
OpType::save_clifford, OpType::save_unitary, OpType::save_mps,
OpType::save_superop, OpType::save_specific_prob
};

inline std::ostream& operator<<(std::ostream& stream, const OpType& type) {
Expand Down Expand Up @@ -126,6 +126,9 @@ inline std::ostream& operator<<(std::ostream& stream, const OpType& type) {
case OpType::save_superop:
stream << "save_superop";
break;
case OpType::save_specific_prob:
stream << "save_specific_prob";
break;
case OpType::set_statevec:
stream << "set_statevector";
break;
Expand Down Expand Up @@ -576,6 +579,8 @@ template<typename inputdata_t>
Op input_to_op_save_expval(const inputdata_t& input, bool variance);
template<typename inputdata_t>
Op input_to_op_save_amps(const inputdata_t& input, bool squared);
template<typename inputdata_t>
Op input_to_op_save_specific_prob(const inputdata_t& input);

// Snapshots
template<typename inputdata_t>
Expand Down Expand Up @@ -678,6 +683,9 @@ Op input_to_op(const inputdata_t& input) {
return input_to_op_save_amps(input, false);
if (name == "save_amplitudes_sq")
return input_to_op_save_amps(input, true);
if (name == "save_specific_prob"){
return input_to_op_save_specific_prob(input);
}
// Set
if (name == "set_statevector")
return input_to_op_set_vector(input, OpType::set_statevec);
Expand Down Expand Up @@ -1237,6 +1245,17 @@ Op input_to_op_save_amps(const inputdata_t& input, bool squared) {
return op;
}

template<typename inputdata_t>
Op input_to_op_save_specific_prob(const inputdata_t& input) {
Op op = input_to_op_save_default(input, OpType::save_specific_prob);
const inputdata_t& params = Parser<inputdata_t>::get_value("params", input);
op.qubits = Parser<inputdata_t>::template get_list_elem<std::vector<uint_t>>(params, 0);
op.int_params = Parser<inputdata_t>::template get_list_elem<std::vector<uint_t>>(params, 1);

return op;
}


//------------------------------------------------------------------------------
// Implementation: Snapshot deserialization
//------------------------------------------------------------------------------
Expand Down
Loading