Skip to content

Commit

Permalink
♻️ Refactor based on changes to Operation class in mqt-core (#363)
Browse files Browse the repository at this point in the history
## Description

This PR updates DDSIM to the latest mqt-core version that has dropped
some long-overdue parameters of functions and members of classes. In
particular, the operation classes no longer need the total number of
qubits and the starting qubit in order to properly function.

## Checklist:

<!---
This checklist serves as a reminder of a couple of things that ensure
your pull request will be merged swiftly.
-->

- [x] The pull request only contains commits that are related to it.
- [x] I have added appropriate tests and documentation.
- [x] I have made sure that all CI jobs on GitHub pass.
- [x] The pull request introduces no new warnings and follows the
project's style guidelines.

---------

Signed-off-by: burgholzer <burgholzer@me.com>
  • Loading branch information
burgholzer authored Apr 4, 2024
1 parent ec820a6 commit 01c926f
Showing 12 changed files with 57 additions and 58 deletions.
2 changes: 1 addition & 1 deletion extern/mqt-core
Submodule mqt-core updated 50 files
+3 −3 .pre-commit-config.yaml
+10 −10 docs/quickstart.ipynb
+2 −2 eval/CMakeLists.txt
+26 −28 include/mqt-core/QuantumComputation.hpp
+0 −5 include/mqt-core/dd/NoiseFunctionality.hpp
+3 −23 include/mqt-core/dd/Operations.hpp
+102 −133 include/mqt-core/dd/Package.hpp
+2 −2 include/mqt-core/ecc/Ecc.hpp
+0 −6 include/mqt-core/operations/ClassicControlledOperation.hpp
+5 −6 include/mqt-core/operations/CompoundOperation.hpp
+10 −8 include/mqt-core/operations/NonUnitaryOperation.hpp
+5 −14 include/mqt-core/operations/Operation.hpp
+15 −26 include/mqt-core/operations/StandardOperation.hpp
+17 −26 include/mqt-core/operations/SymbolicOperation.hpp
+45 −79 src/CircuitOptimizer.cpp
+5 −30 src/QuantumComputation.cpp
+9 −10 src/algorithms/GoogleRandomCircuitSampling.cpp
+1 −1 src/dd/NoiseFunctionality.cpp
+0 −7 src/dd/Operations.cpp
+3 −4 src/dd/Simulation.cpp
+6 −9 src/ecc/Q3Shor.cpp
+1 −2 src/ecc/Q5Laflamme.cpp
+8 −14 src/ecc/Q7Steane.cpp
+2 −3 src/ecc/Q9Shor.cpp
+5 −36 src/mqt/core/_core/operations.pyi
+1 −3 src/mqt/core/io.py
+8 −8 src/mqt/core/plugins/qiskit.py
+6 −13 src/operations/CompoundOperation.cpp
+16 −18 src/operations/NonUnitaryOperation.cpp
+3 −3 src/operations/Operation.cpp
+25 −43 src/operations/StandardOperation.cpp
+28 −42 src/operations/SymbolicOperation.cpp
+12 −15 src/parsers/QASM3Parser.cpp
+2 −2 src/parsers/QCParser.cpp
+3 −4 src/parsers/RealParser.cpp
+5 −7 src/python/operations/register_compound_operation.cpp
+7 −9 src/python/operations/register_non_unitary_operation.cpp
+1 −9 src/python/operations/register_operation.cpp
+25 −32 src/python/operations/register_standard_operation.cpp
+21 −30 src/python/operations/register_symbolic_operation.cpp
+12 −14 src/python/qiskit/QuantumCircuit.cpp
+26 −32 test/dd/test_dd_functionality.cpp
+7 −8 test/dd/test_dd_noise_functionality.cpp
+6 −6 test/dd/test_edge_functionality.cpp
+288 −291 test/dd/test_package.cpp
+0 −9 test/python/test_qiskit.py
+1 −2 test/unittests/test_ecc_functionality.cpp
+1 −1 test/unittests/test_io.cpp
+50 −93 test/unittests/test_qfr_functionality.cpp
+3 −3 test/zx/test_zx_functionality.cpp
2 changes: 1 addition & 1 deletion src/CircuitSimulator.cpp
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ void CircuitSimulator<Config>::reset(qc::NonUnitaryOperation* nonUnitaryOp) {
auto bit = Simulator<Config>::dd->measureOneCollapsing(Simulator<Config>::rootEdge, static_cast<dd::Qubit>(qubit), true, Simulator<Config>::mt);
// apply an X operation whenever the measured result is one
if (bit == '1') {
const auto x = qc::StandardOperation(qc->getNqubits(), qubit, qc::X);
const auto x = qc::StandardOperation(qubit, qc::X);
auto tmp = Simulator<Config>::dd->multiply(dd::getDD(&x, *Simulator<Config>::dd), Simulator<Config>::rootEdge);
Simulator<Config>::dd->incRef(tmp);
Simulator<Config>::dd->decRef(Simulator<Config>::rootEdge);
2 changes: 1 addition & 1 deletion src/DeterministicNoiseSimulator.cpp
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ void DeterministicNoiseSimulator::reset(qc::NonUnitaryOperation* nonUnitaryOp) {
for (const auto& qubit: nonUnitaryOp->getTargets()) {
auto const result = dd->measureOneCollapsing(rootEdge, static_cast<dd::Qubit>(qubit), mt);
if (result == '1') {
const auto x = qc::StandardOperation(getNumberOfQubits(), qubit, qc::X);
const auto x = qc::StandardOperation(qubit, qc::X);
const auto operation = dd::getDD(&x, *dd);
rootEdge = dd->applyOperationToDensity(rootEdge, operation);
}
4 changes: 2 additions & 2 deletions src/HybridSchrodingerFeynmanSimulator.cpp
Original file line number Diff line number Diff line change
@@ -112,9 +112,9 @@ bool HybridSchrodingerFeynmanSimulator<Config>::Slice::apply(std::unique_ptr<dd:
}
} else if (targetInSplit) { // target slice for split or operation in split
const auto& param = op->getParameter();
qc::StandardOperation newOp(nqubits, opControls, opTargets, op->getType(), param, start);
qc::StandardOperation newOp(opControls, opTargets, op->getType(), param);
auto tmp = edge;
edge = sliceDD->multiply(dd::getDD(&newOp, *sliceDD), edge, static_cast<dd::Qubit>(start));
edge = sliceDD->multiply(dd::getDD(&newOp, *sliceDD), edge);
sliceDD->incRef(edge);
sliceDD->decRef(tmp);
}
3 changes: 1 addition & 2 deletions src/PathSimulator.cpp
Original file line number Diff line number Diff line change
@@ -106,7 +106,6 @@ template<class Config>
std::map<std::string, std::size_t> PathSimulator<Config>::simulate(std::size_t shots) {
// build task graph from simulation path
constructTaskGraph();
//std::cout<< *qc << std::endl;
/// Enable the following statements to generate a .dot file of the resulting taskflow
// std::ofstream ofs("taskflow.dot");
// taskflow.dump(ofs);
@@ -115,7 +114,7 @@ std::map<std::string, std::size_t> PathSimulator<Config>::simulate(std::size_t s
executor.run(taskflow).wait();

// measure resulting DD
return Simulator<Config>::measureAllNonCollapsing(shots);
return CircuitSimulator<Config>::measureAllNonCollapsing(shots);
}

template<class Config>
2 changes: 1 addition & 1 deletion src/ShorFastSimulator.cpp
Original file line number Diff line number Diff line change
@@ -314,7 +314,7 @@ dd::mEdge ShorFastSimulator<Config>::addConstMod(std::uint64_t a) {
template<class Config>
void ShorFastSimulator<Config>::applyGate(dd::GateMatrix matrix, dd::Qubit target) {
numberOfOperations++;
const dd::Edge gate = Simulator<Config>::dd->makeGateDD(matrix, static_cast<dd::Qubit>(nQubits), target);
const dd::Edge gate = Simulator<Config>::dd->makeGateDD(matrix, target);
const dd::Edge tmp = Simulator<Config>::dd->multiply(gate, Simulator<Config>::rootEdge);
Simulator<Config>::dd->incRef(tmp);
Simulator<Config>::dd->decRef(Simulator<Config>::rootEdge);
2 changes: 1 addition & 1 deletion src/ShorSimulator.cpp
Original file line number Diff line number Diff line change
@@ -441,7 +441,7 @@ void ShorSimulator<Config>::applyGate(dd::GateMatrix matrix, dd::Qubit target, q

template<class Config>
void ShorSimulator<Config>::applyGate(dd::GateMatrix matrix, dd::Qubit target, const qc::Controls& controls) {
const dd::Edge gate = Simulator<Config>::dd->makeGateDD(matrix, static_cast<dd::Qubit>(nQubits), controls, target);
const dd::Edge gate = Simulator<Config>::dd->makeGateDD(matrix, controls, target);
const dd::Edge tmp = Simulator<Config>::dd->multiply(gate, Simulator<Config>::rootEdge);
Simulator<Config>::dd->incRef(tmp);
Simulator<Config>::dd->decRef(Simulator<Config>::rootEdge);
2 changes: 1 addition & 1 deletion src/StochasticNoiseSimulator.cpp
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ void StochasticNoiseSimulator::runStochSimulationForId(std::size_t stochRun, qc:
for (const auto& qubit: qubits) {
const auto result = localDD->measureOneCollapsing(localRootEdge, static_cast<dd::Qubit>(qubits.at(qubit)), true, generator);
if (result == '1') {
const auto x = qc::StandardOperation(getNumberOfQubits(), qubit, qc::X);
const auto x = qc::StandardOperation(qubit, qc::X);
auto tmp = localDD->multiply(dd::getDD(&x, *localDD), localRootEdge);
localDD->incRef(tmp);
localDD->decRef(localRootEdge);
62 changes: 31 additions & 31 deletions test/test_circuit_sim.cpp
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@

TEST(CircuitSimTest, SingleOneQubitGateOnTwoQubitCircuit) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::X);
quantumComputation->x(0);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));

ASSERT_EQ(ddsim.getNumberOfOps(), 1);
@@ -25,7 +25,7 @@ TEST(CircuitSimTest, SingleOneQubitGateOnTwoQubitCircuit) {

TEST(CircuitSimTest, SingleOneQubitSingleShot) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::H);
quantumComputation->h(0);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));

ASSERT_EQ(ddsim.getNumberOfOps(), 1);
@@ -36,8 +36,8 @@ TEST(CircuitSimTest, SingleOneQubitSingleShot) {

TEST(CircuitSimTest, SingleOneQubitSingleShot2) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2, 2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::H);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(2, 0, 0);
quantumComputation->h(0);
quantumComputation->measure(0, 0);
std::cout << *quantumComputation << "\n";
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(), 1337);

@@ -49,9 +49,9 @@ TEST(CircuitSimTest, SingleOneQubitSingleShot2) {

TEST(CircuitSimTest, SingleOneQubitMultiShots) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2, 2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::H);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(2, 0, 0);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::H);
quantumComputation->h(0);
quantumComputation->measure(0, 0);
quantumComputation->h(0);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));

ASSERT_EQ(ddsim.getNumberOfOps(), 3);
@@ -75,9 +75,9 @@ TEST(CircuitSimTest, BarrierStatement) {

TEST(CircuitSimTest, ClassicControlledOp) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2, 2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::X);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(2, 0, 0);
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(2, 1, qc::X));
quantumComputation->x(0);
quantumComputation->measure(0, 0);
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(1, qc::X));
quantumComputation->emplace_back<qc::ClassicControlledOperation>(op, quantumComputation->getCregs().at("c"), 1);

CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));
@@ -90,9 +90,9 @@ TEST(CircuitSimTest, ClassicControlledOp) {

TEST(CircuitSimTest, ClassicControlledOpAsNop) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2, 2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::X);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(2, 0, 0);
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(2, 1, qc::X));
quantumComputation->x(0);
quantumComputation->measure(0, 0);
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(1, qc::X));
quantumComputation->emplace_back<qc::ClassicControlledOperation>(op, quantumComputation->getCregs().at("c"), 0);

CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));
@@ -105,8 +105,8 @@ TEST(CircuitSimTest, ClassicControlledOpAsNop) {

TEST(CircuitSimTest, DestructiveMeasurementAll) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(2, 1, qc::H);
quantumComputation->h(0);
quantumComputation->h(1);
CircuitSimulator ddsim(std::move(quantumComputation), 42);
ddsim.simulate(1);

@@ -125,8 +125,8 @@ TEST(CircuitSimTest, DestructiveMeasurementAll) {

TEST(CircuitSimTest, DestructiveMeasurementOne) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2);
quantumComputation->emplace_back<qc::StandardOperation>(2, 0, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(2, 1, qc::H);
quantumComputation->h(0);
quantumComputation->h(1);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));
ddsim.simulate(1);

@@ -150,9 +150,9 @@ TEST(CircuitSimTest, DestructiveMeasurementOne) {

TEST(CircuitSimTest, ApproximateByFidelity) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 0, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, qc::Controls{qc::Control{0}, qc::Control{1}}, 2, qc::X);
quantumComputation->h(0);
quantumComputation->h(1);
quantumComputation->mcx(qc::Controls{qc::Control{0}, qc::Control{1}}, 2);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));
std::cout << ddsim.getActiveNodeCount() << "\n";
ddsim.simulate(1);
@@ -166,9 +166,9 @@ TEST(CircuitSimTest, ApproximateByFidelity) {

TEST(CircuitSimTest, ApproximateBySampling) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 0, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, qc::Controls{qc::Control{0}, qc::Control{1}}, 2, qc::X);
quantumComputation->h(0);
quantumComputation->h(1);
quantumComputation->mcx(qc::Controls{qc::Control{0}, qc::Control{1}}, 2);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven));
ddsim.simulate(1);

@@ -191,12 +191,12 @@ TEST(CircuitSimTest, ApproximationByMemoryInSimulator) {

TEST(CircuitSimTest, ApproximationByFidelityInSimulator) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 0, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, qc::Controls{qc::Control{0}, qc::Control{1}}, 2, qc::X);
quantumComputation->h(0);
quantumComputation->h(1);
quantumComputation->mcx(qc::Controls{qc::Control{0}, qc::Control{1}}, 2);

quantumComputation->emplace_back<qc::StandardOperation>(3, 1, qc::I); // some dummy operations
quantumComputation->emplace_back<qc::StandardOperation>(3, 1, qc::I);
quantumComputation->i(1); // some dummy operations
quantumComputation->i(1);

CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(0.3, 1, ApproximationInfo::FidelityDriven));
ddsim.simulate(1);
@@ -225,9 +225,9 @@ TEST(CircuitSimTest, GRCS4x4Test) {

TEST(CircuitSimTest, TestingProperties) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 0, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, qc::Controls{qc::Control{0}, qc::Control{1}}, 2, qc::X);
quantumComputation->h(0);
quantumComputation->h(1);
quantumComputation->mcx(qc::Controls{qc::Control{0}, qc::Control{1}}, 2);
CircuitSimulator ddsim(std::move(quantumComputation), ApproximationInfo(1, 1, ApproximationInfo::FidelityDriven), 1);
ddsim.simulate(1);

2 changes: 1 addition & 1 deletion test/test_det_noise_sim.cpp
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ TEST(DeterministicNoiseSimTest, ClassicControlledOp) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(2, 2);
quantumComputation->x(0);
quantumComputation->measure(0, 0);
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(2, 1, qc::X));
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(1, qc::X));
auto classicalRegister = std::pair<std::size_t, std::size_t>(0, 1);
quantumComputation->emplace_back<qc::ClassicControlledOperation>(op, classicalRegister, 1);
quantumComputation->measure(0, 0);
2 changes: 1 addition & 1 deletion test/test_stoch_noise_sim.cpp
Original file line number Diff line number Diff line change
@@ -110,7 +110,7 @@ TEST(StochNoiseSimTest, SimulateClassicControlledOpWithError) {
quantumComputation->x(0);
quantumComputation->measure(0, 0);
quantumComputation->h(0);
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(2, 1, qc::X));
std::unique_ptr<qc::Operation> op(new qc::StandardOperation(1, qc::X));
auto classicalRegister = std::pair<std::size_t, std::size_t>(0, 1);
quantumComputation->emplace_back<qc::ClassicControlledOperation>(op, classicalRegister, 1);

30 changes: 15 additions & 15 deletions test/test_unitary_sim.cpp
Original file line number Diff line number Diff line change
@@ -7,9 +7,9 @@ using namespace qc::literals;

TEST(UnitarySimTest, ConstructSimpleCircuitSequential) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2_pc, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2_pc, 0, qc::H);
quantumComputation->h(2);
quantumComputation->ch(2, 1);
quantumComputation->ch(2, 0);
UnitarySimulator ddsim(std::move(quantumComputation), UnitarySimulator<>::Mode::Sequential);
ASSERT_NO_THROW(ddsim.construct());
const auto& e = ddsim.getConstructedDD();
@@ -24,9 +24,9 @@ TEST(UnitarySimTest, ConstructSimpleCircuitSequential) {

TEST(UnitarySimTest, ConstructSimpleCircuitRecursive) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2_pc, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2_pc, 0, qc::H);
quantumComputation->h(2);
quantumComputation->ch(2, 1);
quantumComputation->ch(2, 0);
UnitarySimulator ddsim(std::move(quantumComputation), UnitarySimulator<>::Mode::Recursive);
ASSERT_NO_THROW(ddsim.construct());
const auto& e = ddsim.getConstructedDD();
@@ -41,9 +41,9 @@ TEST(UnitarySimTest, ConstructSimpleCircuitRecursive) {

TEST(UnitarySimTest, ConstructSimpleCircuitRecursiveWithSeed) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(3);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2_pc, 1, qc::H);
quantumComputation->emplace_back<qc::StandardOperation>(3, 2_pc, 0, qc::H);
quantumComputation->h(2);
quantumComputation->ch(2, 1);
quantumComputation->ch(2, 0);
UnitarySimulator ddsim(std::move(quantumComputation), ApproximationInfo{}, 1337, UnitarySimulator<>::Mode::Recursive);
ASSERT_NO_THROW(ddsim.construct());
const auto& e = ddsim.getConstructedDD();
@@ -52,12 +52,12 @@ TEST(UnitarySimTest, ConstructSimpleCircuitRecursiveWithSeed) {
}

TEST(UnitarySimTest, NonStandardOperation) {
auto quantumComputation = std::make_unique<qc::QuantumComputation>(1);
quantumComputation->emplace_back<qc::StandardOperation>(1, 0, qc::H);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(1, 0, 0);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(1, 0, qc::Barrier);
quantumComputation->emplace_back<qc::StandardOperation>(1, 0, qc::H);
quantumComputation->emplace_back<qc::NonUnitaryOperation>(1, 0, 0);
auto quantumComputation = std::make_unique<qc::QuantumComputation>(1, 1);
quantumComputation->h(0);
quantumComputation->measure(0, 0);
quantumComputation->barrier(0);
quantumComputation->h(0);
quantumComputation->measure(0, 0);

UnitarySimulator ddsim(std::move(quantumComputation));
EXPECT_TRUE(ddsim.getMode() == UnitarySimulator<>::Mode::Recursive);

0 comments on commit 01c926f

Please sign in to comment.