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 probabilistic instrument #250

Merged
merged 1 commit into from
Oct 30, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion python/cppsim_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ PYBIND11_MODULE(qulacs, m) {

mgate.def("to_matrix_gate", &gate::to_matrix_gate, pybind11::return_value_policy::take_ownership, "Convert named gate to matrix gate", py::arg("gate"));
mgate.def("Probabilistic", &gate::Probabilistic, pybind11::return_value_policy::take_ownership, "Create probabilistic gate", py::arg("prob_list"), py::arg("gate_list"));
mgate.def("CPTP", &gate::CPTP, pybind11::return_value_policy::take_ownership, "Create completely-positive trace preserving map", py::arg("kraus_list"));
mgate.def("ProbabilisticInstrument", &gate::ProbabilisticInstrument, pybind11::return_value_policy::take_ownership, "Create probabilistic instrument gate", py::arg("prob_list"), py::arg("gate_list"), py::arg("register"));
mgate.def("CPTP", &gate::CPTP, pybind11::return_value_policy::take_ownership, "Create completely-positive trace preserving map", py::arg("kraus_list"));
mgate.def("CP", &gate::CP, pybind11::return_value_policy::take_ownership, "Create completely-positive map", py::arg("kraus_list"), py::arg("state_normalize"), py::arg("probability_normalize"), py::arg("assign_zero_if_not_matched"));
mgate.def("Instrument", &gate::Instrument, pybind11::return_value_policy::take_ownership, "Create instruments", py::arg("kraus_list"), py::arg("register"));
mgate.def("Adaptive", &gate::Adaptive, pybind11::return_value_policy::take_ownership, "Create adaptive gate", py::arg("gate"), py::arg("condition"));
Expand Down
82 changes: 82 additions & 0 deletions src/cppsim/gate_general.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,88 @@ class QuantumGate_Probabilistic : public QuantumGateBase {
}
};


/**
* \~japanese-en 選択内容を保存する確率的な操作
*/
class QuantumGate_ProbabilisticInstrument : public QuantumGateBase {
protected:
Random random;
std::vector<double> _distribution;
std::vector<double> _cumulative_distribution;
std::vector<QuantumGateBase*> _gate_list;
UINT _classical_register_address;

public:
/**
* \~japanese-en コンストラクタ
*
* @param distribution ゲートが現れる確率
* @param gate_list ゲートのリスト
* @param classical_register 選択結果を保存するアドレス
*/
QuantumGate_ProbabilisticInstrument(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list, UINT classical_register_address) {
_distribution = distribution;
_classical_register_address = classical_register_address;

double sum = 0.;
_cumulative_distribution.push_back(0.);
for (auto val : distribution) {
sum += val;
_cumulative_distribution.push_back(sum);
}
for (auto gate : gate_list) {
_gate_list.push_back(gate->copy());
}
};

virtual ~QuantumGate_ProbabilisticInstrument() {
for (unsigned int i = 0; i < _gate_list.size(); ++i) {
delete _gate_list[i];
}
}

/**
* \~japanese-en 量子状態を更新する
*
* @param state 更新する量子状態
*/
virtual void update_quantum_state(QuantumStateBase* state) override {
double r = random.uniform();
auto ite = std::lower_bound(_cumulative_distribution.begin(), _cumulative_distribution.end(), r);
assert(ite != _cumulative_distribution.begin());
size_t gate_index = std::distance(_cumulative_distribution.begin(), ite) - 1;

if (gate_index < _gate_list.size()) {
_gate_list[gate_index]->update_quantum_state(state);
}
state->set_classical_value(this->_classical_register_address,gate_index);
};
/**
* \~japanese-en 自身のディープコピーを生成する
*
* @return 自身のディープコピー
*/
virtual QuantumGateBase* copy() const override {
std::vector<QuantumGateBase*> new_gate_list;
for (auto item : _gate_list) {
new_gate_list.push_back(item->copy());
}
return new QuantumGate_ProbabilisticInstrument(_distribution, new_gate_list, _classical_register_address);
};

/**
* \~japanese-en 自身のゲート行列をセットする
*
* @param matrix 行列をセットする変数の参照
*/
virtual void set_matrix(ComplexMatrix& matrix) const override {
std::cerr << "* Warning : Gate-matrix of probabilistic gate cannot be obtained. Identity matrix is returned." << std::endl;
matrix = Eigen::MatrixXcd::Ones(1, 1);
}
};


/**
* \~japanese-en Kraus表現のCPTP-map
*/
Expand Down
4 changes: 4 additions & 0 deletions src/cppsim/gate_merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ namespace gate {
return new QuantumGate_Probabilistic(distribution, gate_list);
}

QuantumGateBase* ProbabilisticInstrument(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list, UINT classical_register_address) {
return new QuantumGate_ProbabilisticInstrument(distribution, gate_list, classical_register_address);
}

QuantumGateBase* CPTP(std::vector<QuantumGateBase*> gate_list) {
return new QuantumGate_CPTP(gate_list);
}
Expand Down
11 changes: 11 additions & 0 deletions src/cppsim/gate_merge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ namespace gate {
*/
DllExport QuantumGateBase* Probabilistic(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list);

/**
* \~japanese-en 密度行列にも確率的に作用する量子ゲートを作成する。
*
* 確率分布の総和が1でない場合、残った確率が採用されたときには何も作用しない。
* @param distribution 確率分布
* @param gate_list 作用する量子ゲート
* @param classical_register_address 作用したゲートの添え字を保存するアドレス
* @return 確率的に作用するゲート
*/
DllExport QuantumGateBase* ProbabilisticInstrument(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list, UINT classical_register_address);

/**
* \~japanese-en CPTP-mapを作成する
*
Expand Down