Skip to content

Commit

Permalink
add qubits-truncate optimization (Qiskit#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
hhorii authored and chriseclectic committed Apr 26, 2019
1 parent 5d9b223 commit 4b743b9
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 14 deletions.
2 changes: 0 additions & 2 deletions src/base/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,6 @@ void State<state_t>::add_creg_to_data(OutputData &data) const {
data.add_register_singleshot(creg_.register_hex());
}
}


//-------------------------------------------------------------------------
} // end namespace Base
//-------------------------------------------------------------------------
Expand Down
3 changes: 1 addition & 2 deletions src/framework/circuitopt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
#include <string>
#include <vector>

#include "base/controller.hpp"
#include "base/state.hpp"
#include "framework/operations.hpp"

namespace AER {

Expand Down
5 changes: 4 additions & 1 deletion src/framework/data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,10 @@ template <typename T>
void OutputData::add_additional_data(const std::string &key, const T &data) {
if (return_additional_data_) {
json_t js = data; // use implicit to_json conversion function for T
additional_data_[key] = js;
if (JSON::check_key(key, additional_data_))
additional_data_[key].update(js.begin(), js.end());
else
additional_data_[key] = js;
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/framework/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,14 @@ struct Op {
};

std::ostream& operator<<(std::ostream& s, const Op& op) {
s << op.name;
s << op.name << "[";
bool first = true;
for (size_t qubit: op.qubits) {
if (!first) s << ",";
s << qubit;
first = false;
}
s << "]";
return s;
}

Expand Down
135 changes: 127 additions & 8 deletions src/simulators/qasm/basic_optimization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ using uint_t = uint_t;
using op_t = Operations::Op;
using optype_t = Operations::OpType;
using oplist_t = std::vector<op_t>;
using opset_t = Operations::OpSet;
using reg_t = std::vector<uint_t>;

class ReduceNop : public CircuitOptimization {
public:
void optimize_circuit(Circuit& circ,
const Operations::OpSet &opset,
const opset_t &opset,
OutputData &data) const override;
};

void ReduceNop::optimize_circuit(Circuit& circ,
const Operations::OpSet &allowed_opset,
const opset_t &allowed_opset,
OutputData &data) const {

oplist_t::iterator it = circ.ops.begin();
Expand All @@ -41,12 +42,12 @@ void ReduceNop::optimize_circuit(Circuit& circ,
class Debug : public CircuitOptimization {
public:
void optimize_circuit(Circuit& circ,
const Operations::OpSet &opset,
const opset_t &opset,
OutputData &data) const override;
};

void Debug::optimize_circuit(Circuit& circ,
const Operations::OpSet &allowed_opset,
const opset_t &allowed_opset,
OutputData &data) const {

oplist_t::iterator it = circ.ops.begin();
Expand All @@ -63,7 +64,7 @@ class Fusion : public CircuitOptimization {
void set_config(const json_t &config) override;

void optimize_circuit(Circuit& circ,
const Operations::OpSet &opset,
const opset_t &opset,
OutputData &data) const override;

bool can_ignore(const op_t& op) const;
Expand Down Expand Up @@ -155,7 +156,7 @@ void Fusion::set_config(const json_t &config) {
#ifdef DEBUG
void Fusion::dump(const Circuit& circuit) const {
int idx = 0;
for (const Operations::Op& op : circuit.ops) {
for (const op_t& op : circuit.ops) {
std::cout << " " << idx++ << ":\t" << op.name << " " << op.qubits << std::endl;
for (const cmatrix_t& mat: op.mats) {
const uint_t row = mat.GetRows();
Expand All @@ -174,12 +175,12 @@ void Fusion::dump(const Circuit& circuit) const {
#endif

void Fusion::optimize_circuit(Circuit& circ,
const Operations::OpSet &allowed_opset,
const opset_t &allowed_opset,
OutputData &data) const {

if (circ.num_qubits < threshold_
|| !active_
|| allowed_opset.optypes.find(Operations::OpType::matrix_sequence) == allowed_opset.optypes.end())
|| allowed_opset.optypes.find(optype_t::matrix_sequence) == allowed_opset.optypes.end())
return;

bool ret = false;
Expand Down Expand Up @@ -463,6 +464,124 @@ cmatrix_t Fusion::matrix(const op_t& op) const {
throw std::runtime_error("Fusion: unexpected operation type");
}
}

class TruncateQubits : public CircuitOptimization {
public:

void set_config(const json_t &config) override;

// truncate unnecessary qubits
void optimize_circuit(Circuit& circ,
const opset_t &opset,
OutputData &data) const override;

private:
// check this optimization can be applied
bool can_apply(const Circuit& circ) const;

// check this optimization can be applied
bool can_apply(const op_t& op) const;

// generate a new mapping. a value of reg_t is original and its index is the new mapping
reg_t generate_mapping(const Circuit& circ) const;

// remap qubits in an operation
op_t remap_qubits(const op_t op, const reg_t new_mapping)const;

// show debug info
bool verbose_ = false;

// disabled in config
bool active_ = true;
};

void TruncateQubits::set_config(const json_t &config) {

CircuitOptimization::set_config(config);

if (JSON::check_key("truncate_verbose", config_))
JSON::get_value(verbose_, "truncate_verbose", config_);

if (JSON::check_key("truncate_enable", config_))
JSON::get_value(active_, "truncate_enable", config_);

if (JSON::check_key("initial_statevector", config_))
active_ = false;

}

void TruncateQubits::optimize_circuit(Circuit& circ,
const opset_t &allowed_opset,
OutputData &data) const {

if (!active_ || !can_apply(circ))
return;

reg_t new_mapping = generate_mapping(circ);

if (new_mapping.size() == circ.num_qubits)
return;

oplist_t new_ops;
for (const op_t& old_op: circ.ops)
new_ops.push_back(remap_qubits(old_op, new_mapping));

circ.ops = new_ops;
circ.num_qubits = new_mapping.size();

if (verbose_) {
data.add_additional_data("metadata",
json_t::object({{"truncate_verbose", new_mapping}}));
}

}

reg_t TruncateQubits::generate_mapping(const Circuit& circ) const {
size_t not_used = circ.num_qubits + 1;
reg_t mapping = reg_t(circ.num_qubits, not_used);

for (const op_t& op: circ.ops)
for (size_t qubit: op.qubits)
mapping[qubit] = qubit;

mapping.erase(std::remove(mapping.begin(), mapping.end(), not_used), mapping.end());

return mapping;
}

op_t TruncateQubits::remap_qubits(const op_t op, const reg_t new_mapping) const {
op_t new_op = op;
new_op.qubits.clear();

for (const size_t qubit: op.qubits) {
size_t new_qubit = std::distance(new_mapping.begin(), find(new_mapping.begin(), new_mapping.end(), qubit));
new_op.qubits.push_back(new_qubit);
}
return new_op;

}

bool TruncateQubits::can_apply(const Circuit& circ) const {

for (const op_t& op: circ.ops)
if (!can_apply(op))
return false;

return true;
}

bool TruncateQubits::can_apply(const op_t& op) const {
switch (op.type) {
case optype_t::matrix_sequence: //TODO
case optype_t::kraus: //TODO
case optype_t::snapshot:
case optype_t::noise_switch:
return false;
default:
return true;
}
}

//-------------------------------------------------------------------------
} // end namespace AER
//-------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/simulators/qasm/qasm_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ class QasmController : public Base::Controller {
QasmController::QasmController() {
add_circuit_optimization(ReduceNop());
add_circuit_optimization(Fusion());
add_circuit_optimization(TruncateQubits());
}

//-------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 4b743b9

Please sign in to comment.