Skip to content

Commit

Permalink
Merge pull request qulacs#455 from qulacs/execute-and-get-state
Browse files Browse the repository at this point in the history
Execute and get state
  • Loading branch information
KowerKoint authored Dec 26, 2022
2 parents 98986d3 + 9b6907b commit d033248
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 19 deletions.
19 changes: 19 additions & 0 deletions pysrc/qulacs/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ __all__ = [
"QuantumGate_SingleParameter",
"QuantumState",
"QuantumStateBase",
"SimulationResult",
"StateVector",
"circuit",
"gate",
Expand Down Expand Up @@ -270,6 +271,10 @@ class NoiseSimulator():
"""
Sampling & Return result [array]
"""
def execute_and_get_result(self, arg0: int) -> SimulationResult:
"""
Simulate & Return ressult [array of (state, frequency)]
"""
pass
class Observable(GeneralQuantumOperator):
def __init__(self, qubit_count: int) -> None:
Expand Down Expand Up @@ -1007,6 +1012,20 @@ class DensityMatrix(QuantumStateBase):
to string
"""
pass
class SimulationResult():
def get_count(self) -> int:
"""
get state count
"""
def get_frequency(self, arg0: int) -> int:
"""
get state frequency
"""
def get_state(self, arg0: int) -> QuantumState:
"""
get state
"""
pass
def StateVector(arg0: int) -> QuantumState:
"""
StateVector
Expand Down
25 changes: 24 additions & 1 deletion python/cppsim_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1322,8 +1322,31 @@ PYBIND11_MODULE(qulacs_core, m) {
.def("get_coef_list", &CausalConeSimulator::get_coef_list,
"Return coef_list");

py::class_<NoiseSimulator::Result>(m, "SimulationResult")
.def(
"get_count",
[](const NoiseSimulator::Result& result) -> UINT {
return result.result.size();
},
"get state count")
.def(
"get_state",
[](const NoiseSimulator::Result& result, UINT i) -> QuantumState* {
return result.result[i].first->copy();
},
"get state", py::return_value_policy::take_ownership)
.def(
"get_frequency",
[](const NoiseSimulator::Result& result, UINT i) -> UINT {
return result.result[i].second;
},
"get state frequency");

py::class_<NoiseSimulator>(m, "NoiseSimulator")
.def(py::init<QuantumCircuit*, QuantumState*>(), "Constructor")
.def("execute", &NoiseSimulator::execute,
"Sampling & Return result [array]");
"Sampling & Return result [array]",
py::return_value_policy::take_ownership)
.def("execute_and_get_result", &NoiseSimulator::execute_and_get_result,
"Simulate & Return ressult [array of (state, frequency)]");
}
61 changes: 45 additions & 16 deletions src/cppsim/noisesimulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,48 @@ NoiseSimulator::~NoiseSimulator() {
delete circuit;
}

std::vector<ITYPE> NoiseSimulator::execute(const UINT sample_count) {
NoiseSimulator::Result::Result(
const std::vector<std::pair<QuantumState*, UINT>>& result_) {
std::transform(result_.begin(), result_.end(), std::back_inserter(result),
[](const std::pair<QuantumState*, UINT>& p) {
return std::make_pair(p.first->copy(), p.second);
});
}

NoiseSimulator::Result::~Result() {
for (const auto& p : result) {
delete p.first;
}
}

std::vector<ITYPE> NoiseSimulator::Result::sampling() const {
std::vector<ITYPE> sampling_result;
for (auto& p : result) {
std::vector<ITYPE> sampling_result_p = p.first->sampling(p.second);
std::copy(sampling_result_p.begin(), sampling_result_p.end(),
std::back_inserter(sampling_result));
}
return sampling_result;
}

std::vector<ITYPE> NoiseSimulator::execute(const UINT execution_count) {
Result* result = execute_and_get_result(execution_count);
std::vector<ITYPE> ret = result->sampling();
delete result;
return ret;
}

NoiseSimulator::Result* NoiseSimulator::execute_and_get_result(
const UINT sample_count) {
std::vector<SamplingRequest> sampling_required =
generate_sampling_request(sample_count);
return execute_sampling(sampling_required);
std::vector<std::pair<QuantumState*, UINT>> simulate_result =
simulate(sampling_required);
Result* result = new Result(simulate_result);
for (const std::pair<QuantumState*, UINT>& p : simulate_result) {
delete p.first;
}
return result;
}

std::vector<NoiseSimulator::SamplingRequest>
Expand Down Expand Up @@ -81,15 +119,15 @@ NoiseSimulator::generate_sampling_request(const UINT sample_count) {
return required_sampling_requests;
}

std::vector<ITYPE> NoiseSimulator::execute_sampling(
std::vector<std::pair<QuantumState*, UINT>> NoiseSimulator::simulate(
std::vector<NoiseSimulator::SamplingRequest> sampling_requests) {
std::sort(begin(sampling_requests), end(sampling_requests),
[](const NoiseSimulator::SamplingRequest& l,
const NoiseSimulator::SamplingRequest& r) {
return l.gate_pos > r.gate_pos;
});

std::vector<ITYPE> sampling_result;
std::vector<std::pair<QuantumState*, UINT>> simulation_result;

QuantumState common_state(initial_state->qubit_count);
QuantumState buffer(initial_state->qubit_count);
Expand Down Expand Up @@ -118,19 +156,10 @@ std::vector<ITYPE> NoiseSimulator::execute_sampling(

buffer.load(&common_state);
apply_gates(current_gate_pos, &buffer, done_itr);
std::vector<ITYPE> samples =
buffer.sampling(sampling_requests[i].num_of_sampling);
for (UINT q = 0; q < samples.size(); ++q) {
sampling_result.push_back(samples[q]);
}
simulation_result.emplace_back(
buffer.copy(), sampling_requests[i].num_of_sampling);
}

// shuffle result because near sampling result may be sampled from same
// merged state.
std::mt19937 randomizer(random.int32());
std::shuffle(begin(sampling_result), end(sampling_result), randomizer);

return sampling_result;
return simulation_result;
}

UINT NoiseSimulator::randomly_select_which_gate_pos_to_apply(
Expand Down
26 changes: 24 additions & 2 deletions src/cppsim/noisesimulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,25 @@ class DllExport NoiseSimulator {
/**
* \~japanese-en
*
* SamplingRequestの計画通りにサンプリングを行い、結果を配列で返す
* SamplingRequestの計画通りにシミュレーションを行い、結果をpairの配列で返す
* @param[in] sampling_request_vector SamplingRequestのvector
*/
std::vector<ITYPE> execute_sampling(
std::vector<std::pair<QuantumState*, UINT>> simulate(
std::vector<SamplingRequest> sampling_request_vector);

public:
/**
* \~japanese-en 複数回の実行結果をまとめた構造体
*/
struct Result {
public:
std::vector<std::pair<QuantumState*, UINT>> result;

Result(const std::vector<std::pair<QuantumState*, UINT>>& result_);
~Result();
std::vector<ITYPE> sampling() const;
};

/**
* \~japanese-en
* コンストラクタ。
Expand All @@ -95,4 +107,14 @@ class DllExport NoiseSimulator {
* @param[in] sample_count 行うsamplingの回数
*/
virtual std::vector<ITYPE> execute(const UINT sample_count);

/**
* \~japanese-en
*
* 実際にサンプリングまではせずにノイズがランダムにかかった量子状態の列を返す。
* @param[in] execution_count 実行回数
* @return
* 量子状態の列。Resultクラスに入れられる。
*/
virtual Result* execute_and_get_result(const UINT execution_count);
};

0 comments on commit d033248

Please sign in to comment.