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

Add qobj header global phase support #931

Merged
merged 9 commits into from
Sep 21, 2020
7 changes: 7 additions & 0 deletions releasenotes/notes/global-phase-9fc2105dac076f48.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
features:
- |
Adds support for qobj global phase to the
:class:`~qiskit.providers.aer.StatevectorSimulator`,
:class:`~qiskit.providers.aer.UnitarySimulator`, and statevector
methods of the :class:`~qiskit.providers.aer.QasmSimulator`.
1 change: 1 addition & 0 deletions src/controllers/qasm_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,7 @@ void QasmController::run_circuit_helper(const Circuit& circ,
// Set state config
state.set_config(config);
state.set_parallalization(parallel_state_update_);
state.set_global_phase(circ.global_phase_angle);

// Rng engine
RngEngine rng;
Expand Down
1 change: 1 addition & 0 deletions src/controllers/statevector_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ void StatevectorController::run_circuit_helper(
// Set config
state.set_config(config);
state.set_parallalization(parallel_state_update_);
state.set_global_phase(circ.global_phase_angle);

// Rng engine
RngEngine rng;
Expand Down
1 change: 1 addition & 0 deletions src/controllers/unitary_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ void UnitaryController::run_circuit_helper(
// Set state config
state.set_config(config);
state.set_parallalization(parallel_state_update_);
state.set_global_phase(circ.global_phase_angle);

// Rng engine (not actually needed for unitary controller)
RngEngine rng;
Expand Down
3 changes: 2 additions & 1 deletion src/framework/circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Circuit {
uint_t shots = 1;
uint_t seed;
json_t header;

double global_phase_angle = 0;

// Constructor
// The constructor automatically calculates the num_qubits, num_memory, num_registers
Expand Down Expand Up @@ -184,6 +184,7 @@ Circuit::Circuit(const json_t &circ, const json_t &qobj_config) : Circuit() {
// Load metadata
JSON::get_value(header, "header", circ);
JSON::get_value(shots, "shots", config);
JSON::get_value(global_phase_angle, "global_phase", header);

// Check for specified memory slots
uint_t memory_slots = 0;
Expand Down
22 changes: 20 additions & 2 deletions src/simulators/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class State {
// Load any settings for the State class from a config JSON
virtual void set_config(const json_t &config);

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// Optional: Add information to metadata
//-----------------------------------------------------------------------

Expand Down Expand Up @@ -191,13 +191,16 @@ class State {
std::string name = "register") const;

//-----------------------------------------------------------------------
// OpenMP thread settings
// Config Settings
//-----------------------------------------------------------------------

// Sets the number of threads available to the State implementation
// If negative there is no restriction on the backend
inline void set_parallalization(int n) {threads_ = n;}

// Set a complex global phase value exp(1j * theta) for the state
void set_global_phase(const double &phase);

protected:

// The quantum state data structure
Expand All @@ -212,6 +215,10 @@ class State {
// Maximum threads which may be used by the backend for OpenMP multithreading
// Default value is single-threaded unless overridden
int threads_ = 1;

// Set a global phase exp(1j * theta) for the state
bool has_global_phase_ = false;
complex_t global_phase_ = 1;
};


Expand All @@ -224,6 +231,17 @@ void State<state_t>::set_config(const json_t &config) {
(ignore_argument)config;
}

template <class state_t>
void State<state_t>::set_global_phase(const double &phase_angle) {
if (Linalg::almost_equal(phase_angle, 0.0)) {
has_global_phase_ = false;
global_phase_ = 1;
}
else {
has_global_phase_ = true;
global_phase_ = std::exp(complex_t(0.0, phase_angle));
}
}

template <class state_t>
std::vector<reg_t> State<state_t>::sample_measure(const reg_t &qubits,
Expand Down
14 changes: 14 additions & 0 deletions src/simulators/statevector/statevector_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ class State : public Base::State<statevec_t> {
// Config Settings
//-----------------------------------------------------------------------

// Apply the global phase
void apply_global_phase();

// OpenMP qubit threshold
int omp_qubit_threshold_ = 14;

Expand Down Expand Up @@ -367,6 +370,7 @@ void State<statevec_t>::initialize_qreg(uint_t num_qubits) {
initialize_omp();
BaseState::qreg_.set_num_qubits(num_qubits);
BaseState::qreg_.initialize();
apply_global_phase();
}

template <class statevec_t>
Expand All @@ -379,6 +383,7 @@ void State<statevec_t>::initialize_qreg(uint_t num_qubits,
initialize_omp();
BaseState::qreg_.set_num_qubits(num_qubits);
BaseState::qreg_.initialize_from_data(state.data(), 1ULL << num_qubits);
apply_global_phase();
}

template <class statevec_t>
Expand All @@ -390,6 +395,7 @@ void State<statevec_t>::initialize_qreg(uint_t num_qubits,
initialize_omp();
BaseState::qreg_.set_num_qubits(num_qubits);
BaseState::qreg_.initialize_from_vector(state);
apply_global_phase();
}

template <class statevec_t>
Expand All @@ -403,6 +409,13 @@ void State<statevec_t>::initialize_omp() {
// Utility
//-------------------------------------------------------------------------

template <class statevec_t>
void State<statevec_t>::apply_global_phase() {
if (BaseState::has_global_phase_) {
BaseState::qreg_.apply_diagonal_matrix(0, {BaseState::global_phase_, BaseState::global_phase_});
}
}

template <class statevec_t>
size_t State<statevec_t>::required_memory_mb(uint_t num_qubits,
const std::vector<Operations::Op> &ops)
Expand All @@ -413,6 +426,7 @@ size_t State<statevec_t>::required_memory_mb(uint_t num_qubits,

template <class statevec_t>
void State<statevec_t>::set_config(const json_t &config) {
BaseState::set_config(config);

// Set threshold for truncating snapshots
JSON::get_value(json_chop_threshold_, "zero_threshold", config);
Expand Down
17 changes: 17 additions & 0 deletions src/simulators/unitary/unitary_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ class State : public Base::State<unitary_matrix_t> {
// Config Settings
//-----------------------------------------------------------------------

// Apply the global phase
void apply_global_phase();

// OpenMP qubit threshold
int omp_qubit_threshold_ = 6;

Expand Down Expand Up @@ -253,6 +256,8 @@ size_t State<unitary_matrix_t>::required_memory_mb(

template <class unitary_matrix_t>
void State<unitary_matrix_t>::set_config(const json_t &config) {
BaseState::set_config(config);

// Set OMP threshold for state update functions
JSON::get_value(omp_qubit_threshold_, "unitary_parallel_threshold", config);

Expand All @@ -266,6 +271,7 @@ void State<unitary_matrix_t>::initialize_qreg(uint_t num_qubits) {
initialize_omp();
BaseState::qreg_.set_num_qubits(num_qubits);
BaseState::qreg_.initialize();
apply_global_phase();
}

template <class unitary_matrix_t>
Expand All @@ -281,6 +287,7 @@ void State<unitary_matrix_t>::initialize_qreg(
BaseState::qreg_.set_num_qubits(num_qubits);
const size_t sz = 1ULL << BaseState::qreg_.size();
BaseState::qreg_.initialize_from_data(unitary.data(), sz);
apply_global_phase();
}

template <class unitary_matrix_t>
Expand All @@ -295,6 +302,7 @@ void State<unitary_matrix_t>::initialize_qreg(
initialize_omp();
BaseState::qreg_.set_num_qubits(num_qubits);
BaseState::qreg_.initialize_from_matrix(unitary);
apply_global_phase();
}

template <class unitary_matrix_t>
Expand Down Expand Up @@ -425,6 +433,15 @@ void State<unitary_matrix_t>::apply_snapshot(const Operations::Op &op,
}
}

template <class unitary_matrix_t>
void State<unitary_matrix_t>::apply_global_phase() {
if (BaseState::has_global_phase_) {
BaseState::qreg_.apply_diagonal_matrix(
{0}, {BaseState::global_phase_, BaseState::global_phase_}
);
}
}

//------------------------------------------------------------------------------
} // namespace QubitUnitary
} // end namespace AER
Expand Down