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 qubits-truncate optimization #164

Merged
merged 8 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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