Skip to content

Commit

Permalink
Add some missing snapshots (Qiskit#309)
Browse files Browse the repository at this point in the history
* add stabilizer snapshot

* add single-shot expectation values to statevector method
  • Loading branch information
chriseclectic authored Aug 1, 2019
1 parent 50417c8 commit 37af875
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 27 deletions.
6 changes: 2 additions & 4 deletions src/framework/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,11 +932,9 @@ Op json_to_op_snapshot(const json_t &js) {
std::string snapshot_type;
JSON::get_value(snapshot_type, "snapshot_type", js); // LEGACY: to remove in 0.3
JSON::get_value(snapshot_type, "type", js);
if (snapshot_type == "expectation_value_pauli" ||
snapshot_type == "expectation_value_pauli_with_variance")
if (snapshot_type.find("expectation_value_pauli") != std::string::npos)
return json_to_op_snapshot_pauli(js);
if (snapshot_type == "expectation_value_matrix" ||
snapshot_type == "expectation_value_matrix_with_variance")
if (snapshot_type.find("expectation_value_matrix") != std::string::npos)
return json_to_op_snapshot_matrix(js);
// Default snapshot: has "type", "label", "qubits"
auto op = json_to_op_snapshot_default(js);
Expand Down
11 changes: 8 additions & 3 deletions src/simulators/stabilizer/stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ enum class Gates {id, x, y, z, h, s, sdg, cx, cz, swap};

// Allowed snapshots enum class
enum class Snapshots {
cmemory, cregister,
probs, probs_var // TODO
stabilizer, cmemory, cregister,
probs, probs_var
/* TODO: the following snapshots still need to be implemented */
//expval_pauli, expval_pauli_var, // TODO
};

Expand Down Expand Up @@ -75,7 +76,7 @@ class State : public Base::State<Clifford::Clifford> {

// Return the set of qobj snapshot types supported by the State
virtual stringset_t allowed_snapshots() const override {
return {"memory", "register"};
return {"stabilizer", "memory", "register"};
}

// Apply a sequence of operations by looping over list
Expand Down Expand Up @@ -201,6 +202,7 @@ const stringmap_t<Gates> State::gateset_({
});

const stringmap_t<Snapshots> State::snapshotset_({
{"stabilizer", Snapshots::stabilizer},
{"memory", Snapshots::cmemory},
{"register", Snapshots::cregister},
{"probabilities", Snapshots::probs},
Expand Down Expand Up @@ -419,6 +421,9 @@ void State::apply_snapshot(const Operations::Op &op,
throw std::invalid_argument("Stabilizer::State::invalid snapshot instruction \'" +
op.name + "\'.");
switch (it->second) {
case Snapshots::stabilizer:
BaseState::snapshot_state(op, data, "stabilizer");
break;
case Snapshots::cmemory:
BaseState::snapshot_creg_memory(op, data);
break;
Expand Down
79 changes: 59 additions & 20 deletions src/simulators/statevector/statevector_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ enum class Gates {
enum class Snapshots {
statevector, cmemory, cregister,
probs, probs_var,
expval_pauli, expval_pauli_var,
expval_matrix, expval_matrix_var
expval_pauli, expval_pauli_var, expval_pauli_shot,
expval_matrix, expval_matrix_var, expval_matrix_shot
};

// Enum class for different types of expectation values
enum class SnapshotDataType {average, average_var, single_shot};

//=========================================================================
// QubitVector State subclass
//=========================================================================
Expand Down Expand Up @@ -90,8 +93,13 @@ class State : public Base::State<statevec_t> {
virtual stringset_t allowed_snapshots() const override {
return {"statevector", "memory", "register",
"probabilities", "probabilities_with_variance",
"expectation_value_pauli", "expectation_value_pauli_with_variance",
"expectation_value_matrix", "expectation_value_matrix_with_variance"};
"expectation_value_pauli",
"expectation_value_pauli_with_variance",
"expectation_value_matrix_single_shot",
"expectation_value_matrix",
"expectation_value_matrix_with_variance",
"expectation_value_pauli_single_shot"
};
}

// Apply a sequence of operations by looping over list
Expand Down Expand Up @@ -224,17 +232,17 @@ class State : public Base::State<statevec_t> {
// Snapshot current qubit probabilities for a measurement (average)
void snapshot_probabilities(const Operations::Op &op,
OutputData &data,
bool variance);
SnapshotDataType type);

// Snapshot the expectation value of a Pauli operator
void snapshot_pauli_expval(const Operations::Op &op,
OutputData &data,
bool variance);
SnapshotDataType type);

// Snapshot the expectation value of a matrix operator
void snapshot_matrix_expval(const Operations::Op &op,
OutputData &data,
bool variance);
SnapshotDataType type);

//-----------------------------------------------------------------------
// Single-qubit gate helpers
Expand Down Expand Up @@ -325,6 +333,8 @@ const stringmap_t<Snapshots> State<statevec_t>::snapshotset_({
{"probabilities_with_variance", Snapshots::probs_var},
{"expectation_value_pauli_with_variance", Snapshots::expval_pauli_var},
{"expectation_value_matrix_with_variance", Snapshots::expval_matrix_var},
{"expectation_value_pauli_single_shot", Snapshots::expval_pauli_shot},
{"expectation_value_matrix_single_shot", Snapshots::expval_matrix_shot},
{"memory", Snapshots::cmemory},
{"register", Snapshots::cregister}
});
Expand Down Expand Up @@ -487,23 +497,29 @@ void State<statevec_t>::apply_snapshot(const Operations::Op &op,
break;
case Snapshots::probs: {
// get probs as hexadecimal
snapshot_probabilities(op, data, false);
snapshot_probabilities(op, data, SnapshotDataType::average);
} break;
case Snapshots::expval_pauli: {
snapshot_pauli_expval(op, data, false);
snapshot_pauli_expval(op, data, SnapshotDataType::average);
} break;
case Snapshots::expval_matrix: {
snapshot_matrix_expval(op, data, false);
snapshot_matrix_expval(op, data, SnapshotDataType::average);
} break;
case Snapshots::probs_var: {
// get probs as hexadecimal
snapshot_probabilities(op, data, true);
snapshot_probabilities(op, data, SnapshotDataType::average_var);
} break;
case Snapshots::expval_pauli_var: {
snapshot_pauli_expval(op, data, true);
snapshot_pauli_expval(op, data, SnapshotDataType::average_var);
} break;
case Snapshots::expval_matrix_var: {
snapshot_matrix_expval(op, data, true);
snapshot_matrix_expval(op, data, SnapshotDataType::average_var);
} break;
case Snapshots::expval_pauli_shot: {
snapshot_pauli_expval(op, data, SnapshotDataType::single_shot);
} break;
case Snapshots::expval_matrix_shot: {
snapshot_matrix_expval(op, data, SnapshotDataType::single_shot);
} break;
default:
// We shouldn't get here unless there is a bug in the snapshotset
Expand All @@ -515,10 +531,11 @@ void State<statevec_t>::apply_snapshot(const Operations::Op &op,
template <class statevec_t>
void State<statevec_t>::snapshot_probabilities(const Operations::Op &op,
OutputData &data,
bool variance) {
SnapshotDataType type) {
// get probs as hexadecimal
auto probs = Utils::vec2ket(measure_probs(op.qubits),
json_chop_threshold_, 16);
bool variance = type == SnapshotDataType::average_var;
data.add_average_snapshot("probabilities", op.string_params[0],
BaseState::creg_.memory_hex(), probs, variance);
}
Expand All @@ -527,7 +544,7 @@ void State<statevec_t>::snapshot_probabilities(const Operations::Op &op,
template <class statevec_t>
void State<statevec_t>::snapshot_pauli_expval(const Operations::Op &op,
OutputData &data,
bool variance) {
SnapshotDataType type) {
// Check empty edge case
if (op.params_expval_pauli.empty()) {
throw std::invalid_argument("Invalid expval snapshot (Pauli components are empty).");
Expand Down Expand Up @@ -578,16 +595,27 @@ void State<statevec_t>::snapshot_pauli_expval(const Operations::Op &op,
}
// add to snapshot
Utils::chop_inplace(expval, json_chop_threshold_);
data.add_average_snapshot("expectation_value", op.string_params[0],
BaseState::creg_.memory_hex(), expval, variance);
switch (type) {
case SnapshotDataType::average:
data.add_average_snapshot("expectation_value", op.string_params[0],
BaseState::creg_.memory_hex(), expval, false);
break;
case SnapshotDataType::average_var:
data.add_average_snapshot("expectation_value", op.string_params[0],
BaseState::creg_.memory_hex(), expval, true);
break;
case SnapshotDataType::single_shot:
data.add_singleshot_snapshot("expectation_values", op.string_params[0], expval);
break;
}
// Revert to original state
BaseState::qreg_.revert(false);
}

template <class statevec_t>
void State<statevec_t>::snapshot_matrix_expval(const Operations::Op &op,
OutputData &data,
bool variance) {
SnapshotDataType type) {
// Check empty edge case
if (op.params_expval_matrix.empty()) {
throw std::invalid_argument("Invalid matrix snapshot (components are empty).");
Expand Down Expand Up @@ -625,8 +653,19 @@ void State<statevec_t>::snapshot_matrix_expval(const Operations::Op &op,
}
// add to snapshot
Utils::chop_inplace(expval, json_chop_threshold_);
data.add_average_snapshot("expectation_value", op.string_params[0],
BaseState::creg_.memory_hex(), expval, variance);
switch (type) {
case SnapshotDataType::average:
data.add_average_snapshot("expectation_value", op.string_params[0],
BaseState::creg_.memory_hex(), expval, false);
break;
case SnapshotDataType::average_var:
data.add_average_snapshot("expectation_value", op.string_params[0],
BaseState::creg_.memory_hex(), expval, true);
break;
case SnapshotDataType::single_shot:
data.add_singleshot_snapshot("expectation_values", op.string_params[0], expval);
break;
}
// Revert to original state
BaseState::qreg_.revert(false);
}
Expand Down

0 comments on commit 37af875

Please sign in to comment.