Skip to content

Commit

Permalink
Fixed MPS expectation value when qubits are not given in ascending or…
Browse files Browse the repository at this point in the history
…der (Qiskit#603)

* added support for computing expectation value pauli when qubits are not in ascending order
* in expectation_value_pauli, moved the reverse_qubits to before the sort
* update MPS expectation value snapshots
* added support for expectation value matrix when the qubits are not ordered in ascending order
* rewrote the function move_qubits_to_new_position
* changed name of method and parameters, to suit functionality
* updated documentation accordingly

Co-authored-by: yaelbh <[email protected]>
(cherry picked from commit 0d010b3)
  • Loading branch information
merav-aharoni authored and mtreinish committed Feb 24, 2020
1 parent e30ea21 commit 0e9d02c
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 96 deletions.
121 changes: 87 additions & 34 deletions src/simulators/matrix_product_state/matrix_product_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ namespace MatrixProductState {
// Allowed snapshots enum class
enum class Snapshots {
statevector, cmemory, cregister,
probs, //probs_var,
expval_pauli, //expval_pauli_var,
expval_matrix//, //expval_matrix_var
probs, probs_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
Expand Down Expand Up @@ -111,11 +111,11 @@ class State : public Base::State<matrixproductstate_t> {

// Return the set of qobj snapshot types supported by the State
virtual stringset_t allowed_snapshots() const override {
//TODO: Review this
//TODO: Review this
return {"statevector", "memory", "register", "probabilities",
"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_pauli_single_shot",
"expectation_value_matrix", "expectation_value_matrix_with_variance", "expectation_value_matrix_single_shot"
};
}

// Apply a sequence of operations by looping over list
Expand Down Expand Up @@ -244,12 +244,12 @@ class State : public Base::State<matrixproductstate_t> {
// Snapshot the expectation value of a Pauli operator
void snapshot_pauli_expval(const Operations::Op &op,
ExperimentData &data,
bool variance);
SnapshotDataType type);

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

// Snapshot the state vector
void snapshot_state(const Operations::Op &op,
Expand Down Expand Up @@ -324,9 +324,11 @@ const stringmap_t<Snapshots> State::snapshotset_({
{"probabilities", Snapshots::probs},
{"expectation_value_pauli", Snapshots::expval_pauli},
{"expectation_value_matrix", Snapshots::expval_matrix},
//{"probabilities_with_variance", Snapshots::probs_var},
//{"expectation_value_pauli_with_variance", Snapshots::expval_pauli_var},
//{"expectation_value_matrix_with_variance", Snapshots::expval_matrix_var},
{"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 @@ -463,7 +465,7 @@ void State::apply_ops(const std::vector<Operations::Op> &ops,

void State::snapshot_pauli_expval(const Operations::Op &op,
ExperimentData &data,
bool variance){
SnapshotDataType type){
if (op.params_expval_pauli.empty()) {
throw std::invalid_argument("Invalid expval snapshot (Pauli components are empty).");
}
Expand All @@ -475,15 +477,29 @@ void State::snapshot_pauli_expval(const Operations::Op &op,
complex_t coeff = param.first;
std::string pauli_matrices = param.second;
complex_t pauli_expval = qreg_.expectation_value_pauli(op.qubits, pauli_matrices);

expval += coeff * pauli_expval;
}
data.add_pershot_snapshot("expectation_value", op.string_params[0], expval);

// add to snapshot
Utils::chop_inplace(expval, json_chop_threshold_);
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::pershot:
data.add_pershot_snapshot("expectation_values", op.string_params[0], expval);
break;
}
}

void State::snapshot_matrix_expval(const Operations::Op &op,
ExperimentData &data,
bool variance){
SnapshotDataType type){
if (op.params_expval_matrix.empty()) {
throw std::invalid_argument("Invalid matrix snapshot (components are empty).");
}
Expand All @@ -494,13 +510,31 @@ void State::snapshot_matrix_expval(const Operations::Op &op,
complex_t coeff = param.first;

for (const auto &pair: param.second) {
const reg_t &qubits = pair.first;
reg_t sub_qubits;
for (const auto pos : pair.first) {
sub_qubits.push_back(op.qubits[pos]);
}
const cmatrix_t &mat = pair.second;
one_expval = qreg_.expectation_value(qubits, mat);
one_expval = qreg_.expectation_value(sub_qubits, mat);
expval += coeff * one_expval;
data.add_pershot_snapshot("expectation_value", op.string_params[0], expval);
}
}

// add to snapshot
Utils::chop_inplace(expval, json_chop_threshold_);
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::pershot:
data.add_pershot_snapshot("expectation_values", op.string_params[0], expval);
break;
}
}

void State::snapshot_state(const Operations::Op &op,
Expand Down Expand Up @@ -529,7 +563,6 @@ void State::apply_gate(const Operations::Op &op) {
if (it == gateset_.end())
throw std::invalid_argument(
"MatrixProductState::State::invalid gate instruction \'" + op.name + "\'.");

switch (it -> second) {
case Gates::mcx:
qreg_.apply_ccx(op.qubits);
Expand Down Expand Up @@ -682,24 +715,44 @@ void State::apply_snapshot(const Operations::Op &op, ExperimentData &data) {
case Snapshots::statevector: {
snapshot_state(op, data, "statevector");
break;
}
}
case Snapshots::cmemory:
BaseState::snapshot_creg_memory(op, data);
break;
case Snapshots::cregister:
BaseState::snapshot_creg_register(op, data);
break;
case Snapshots::probs: {
// get probs as hexadecimal
snapshot_probabilities(op, data, SnapshotDataType::average);
break;
}
case Snapshots::expval_pauli: {
snapshot_pauli_expval(op, data, false);
break;
}
case Snapshots::expval_matrix: {
snapshot_matrix_expval(op, data, false);
break;
}
default:
// We shouldn't get here unless there is a bug in the snapshotset
throw std::invalid_argument("MatrixProductState::State::invalid snapshot instruction \'" +
op.name + "\'.");
}
case Snapshots::expval_pauli: {
snapshot_pauli_expval(op, data, SnapshotDataType::average);
} break;
case Snapshots::expval_matrix: {
snapshot_matrix_expval(op, data, SnapshotDataType::average);
} break;
case Snapshots::probs_var: {
// get probs as hexadecimal
snapshot_probabilities(op, data, SnapshotDataType::average_var);
} break;
case Snapshots::expval_pauli_var: {
snapshot_pauli_expval(op, data, SnapshotDataType::average_var);
} break;
case Snapshots::expval_matrix_var: {
snapshot_matrix_expval(op, data, SnapshotDataType::average_var);
} break;
case Snapshots::expval_pauli_shot: {
snapshot_pauli_expval(op, data, SnapshotDataType::pershot);
} break;
case Snapshots::expval_matrix_shot: {
snapshot_matrix_expval(op, data, SnapshotDataType::pershot);
} break;
default:
// We shouldn't get here unless there is a bug in the snapshotset
throw std::invalid_argument("MatrixProductState::State::invalid snapshot instruction \'" +
op.name + "\'.");
}
}

Expand Down
Loading

0 comments on commit 0e9d02c

Please sign in to comment.