15#ifndef _SIMPLE_NETWORK_H_
16#define _SIMPLE_NETWORK_H_
18#include "QubitRegister.h"
22#include "../Estimators/SimulatorsEstimatorInterface.h"
41 class Controller = SimpleController<Time>>
58 const std::vector<size_t> &cbits = {}) {
72 const std::vector<size_t> &cbits) {
73 size_t qubitsOffset = 0;
74 size_t cbitsOffset = 0;
76 for (
size_t i = 0; i < qubits.size(); ++i) {
77 const size_t numQubits = qubits[i];
78 const size_t numBits = (i < cbits.size() ? cbits[i] : 0);
80 i, qubitsOffset, numQubits, cbitsOffset, numBits));
81 qubitsOffset += numQubits;
82 cbitsOffset += numBits;
85 for (
size_t i = 0; i <
hosts.size(); ++i) {
86 std::static_pointer_cast<SimpleHost<Time>>(
hosts[i])->SetEntangledQubitId(
88 std::static_pointer_cast<SimpleHost<Time>>(
hosts[i])
89 ->SetEntangledQubitMeasurementBit(cbitsOffset);
109 const auto recreate = recreateIfNeeded;
113 size_t numQubits = 2;
117 numQubits =
simulator->GetNumberOfQubits();
120 recreateIfNeeded =
false;
124 recreateIfNeeded = recreate;
128 const auto &first = *res.begin();
135 method !=
simulator->GetSimulationType() ||
136 simulator->GetNumberOfQubits() != numQubits))))
153 size_t hostId)
override {
154 const auto recreate = recreateIfNeeded;
158 size_t numQubits = 2;
162 numQubits =
simulator->GetNumberOfQubits();
165 recreateIfNeeded =
false;
169 recreateIfNeeded = recreate;
173 const auto &first = *res.begin();
180 method !=
simulator->GetSimulationType() ||
181 simulator->GetNumberOfQubits() != numQubits))))
202 const std::vector<std::string> &paulis)
override {
203 const auto recreate = recreateIfNeeded;
207 size_t numQubits = 2;
211 numQubits =
simulator->GetNumberOfQubits();
214 recreateIfNeeded =
false;
216 pauliStrings = &paulis;
218 pauliStrings =
nullptr;
220 recreateIfNeeded = recreate;
224 const auto &first = *res.begin();
228 std::vector<double> expectations(paulis.size());
231 const size_t numOps =
simulator->GetNumberOfQubits();
236 const auto &qubitsMap = optimiser->GetQubitsMap();
238 for (
size_t i = 0; i < paulis.size(); ++i) {
239 std::string translated(numOps,
'I');
241 for (
size_t j = 0; j < paulis[i].size(); ++j) {
242 const auto pos = qubitsMap.find(j);
243 if (pos != qubitsMap.end())
244 translated[pos->second] = paulis[i][j];
246 translated[j] = paulis[i][j];
249 expectations[i] =
simulator->ExpectationValue(translated);
252 for (
size_t i = 0; i < paulis.size(); ++i)
253 expectations[i] =
simulator->ExpectationValue(paulis[i]);
258 method !=
simulator->GetSimulationType() ||
259 simulator->GetNumberOfQubits() != numQubits))
282 const std::vector<std::string> &paulis)
override {
283 const auto recreate = recreateIfNeeded;
287 size_t numQubits = 2;
291 numQubits =
simulator->GetNumberOfQubits();
295 struct ScopedRestore {
297 const std::vector<std::string> **ps;
298 ScopedRestore(
bool &f,
const std::vector<std::string> **p)
299 : flag(f), saved(f), ps(p) {
306 } restoreGuard(recreateIfNeeded, &pauliStrings);
308 pauliStrings = &paulis;
313 const auto &first = *res.begin();
321 const size_t offsetBase = qubitsMapOnHost.size();
323 std::vector<double> expectations(paulis.size(), 1.);
326 const size_t numOps =
simulator->GetNumberOfQubits();
329 for (
size_t i = 0; i < paulis.size(); ++i) {
330 std::string translated(std::max(numOps, paulis[i].size()),
'I');
332 size_t offset = offsetBase;
334 for (
size_t j = 0; j < paulis[i].size(); ++j) {
335 auto pos = qubitsMapOnHost.find(j);
336 if (pos != qubitsMapOnHost.end())
337 translated[pos->second] = paulis[i][j];
339 translated[offset] = paulis[i][j];
346 expectations[i] =
simulator->ExpectationValue(translated);
349 throw std::runtime_error(
350 "ExecuteOnHostExpectations: no simulator available after execution.");
354 method !=
simulator->GetSimulationType() ||
355 simulator->GetNumberOfQubits() != numQubits))
374 size_t hostId)
override {
375 const auto recreate = recreateIfNeeded;
379 size_t numQubits = 2;
383 numQubits =
simulator->GetNumberOfQubits();
387 struct ScopedRestoreFlag {
389 ScopedRestoreFlag(
bool &f) : flag(f), saved(f) { flag =
false; }
390 ~ScopedRestoreFlag() { flag = saved; }
391 } restoreGuard(recreateIfNeeded);
396 const auto &first = *res.begin();
401 throw std::runtime_error(
402 "ExecuteOnHostAmplitudes: no simulator available after execution.");
404 std::vector<std::complex<double>> amplitudes;
405 const size_t n =
simulator->GetNumberOfQubits();
406 const size_t dim = 1ULL << n;
407 amplitudes.resize(dim);
408 for (
size_t state = 0; state < dim; ++state) amplitudes[state] =
simulator->Amplitude(state);
412 if (!qubitsMapOnHost.empty()) {
413 const size_t offsetBase = qubitsMapOnHost.size();
417 std::vector<size_t> simToOrig(n);
418 size_t offset = offsetBase;
420 for (
size_t qbit = 0; qbit < n; ++qbit)
422 auto pos = qubitsMapOnHost.find(qbit);
423 if (pos != qubitsMapOnHost.end())
424 simToOrig[pos->second] = pos->first;
426 simToOrig[qbit] = offset++;
429 std::vector<std::complex<double>> remapped(dim);
431 for (
size_t sim_state = 0; sim_state < dim; ++sim_state) {
432 size_t orig_state = 0;
433 for (
size_t qbit = 0; qbit < n; ++qbit) {
434 if (sim_state & (1ULL << qbit))
435 orig_state |= (1ULL << simToOrig[qbit]);
437 if (orig_state < dim) remapped[orig_state] = amplitudes[sim_state];
439 amplitudes.swap(remapped);
443 method !=
simulator->GetSimulationType() ||
444 simulator->GetNumberOfQubits() != numQubits))
465 size_t hostId)
override {
466 const auto recreate = recreateIfNeeded;
470 size_t numQubits = 2;
474 numQubits =
simulator->GetNumberOfQubits();
478 struct ScopedRestoreFlag {
480 ScopedRestoreFlag(
bool &f) : flag(f), saved(f) { flag =
false; }
481 ~ScopedRestoreFlag() { flag = saved; }
482 } restoreGuard(recreateIfNeeded);
487 const auto &first = *res.begin();
492 throw std::runtime_error(
493 "ExecuteOnHostProjectOnZero: no simulator available after "
496 const std::complex<double> result =
simulator->ProjectOnZero();
499 method !=
simulator->GetSimulationType() ||
500 simulator->GetNumberOfQubits() != numQubits))
521 size_t shots = 1000)
override {
528 for (
auto q :
distCirc->AffectedQubits()) {
531 <<
"This is a distributed circuit, using entanglement or cutting"
541 if (
distCirc->HasOpsAfterMeasurements() &&
547 distCirc->MoveMeasurementsAndResets();
549 auto method =
simulator->GetSimulationType();
551 const auto saveSimType = simType;
552 const auto saveMethod = method;
576 simulator->GetConfiguration(
"matrix_product_state_max_bond_dimension");
578 "matrix_product_state_truncation_threshold");
589 std::vector<bool> executed;
592 simType, method, executed);
605 !
distCirc->HasOpsAfterMeasurements()) ||
609 nrThreads = std::min(nrThreads, std::max<size_t>(shots, 1ULL));
611 std::mutex resultsMutex;
629 const size_t cntPerThread = std::max<size_t>(shots / nrThreads, 1ULL);
631 threadsPool.Resize(nrThreads);
632 threadsPool.SetFinishLimit(shots);
635 const size_t curCnt = std::min(cntPerThread, shots);
639 auto job = std::make_shared<ExecuteJob<Time>>(
640 dcirc, res, curCnt, nrQubits, nrQubits, nrCbitsResults, simType,
641 method, resultsMutex);
649 job->optSim = optSim->Clone();
650 job->executedGates = executed;
653 threadsPool.AddRunJob(std::move(job));
656 threadsPool.WaitForFinish();
659 const size_t curCnt = shots;
661 auto job = std::make_shared<ExecuteJob<Time>>(
662 dcirc, res, curCnt, nrQubits, nrQubits, nrCbitsResults, simType,
663 method, resultsMutex);
671 optSim->SetMultithreading(
true);
672 job->optSim = optSim;
673 job->executedGates = executed;
675 if (
simulator && method == saveMethod && simType == saveSimType) {
678 job->optSim = optSim;
679 job->executedGates.resize(
distCirc->size(),
686 if (!recreateIfNeeded)
simulator = job->optSim;
713 size_t shots = 1000)
override {
714 if (!circuit || hostId >=
GetNumHosts())
return {};
719 std::shared_ptr<Circuits::Circuit<Time>> optCircuit;
722 std::static_pointer_cast<Circuits::Circuit<Time>>(circuit->Clone());
723 optCircuit->Optimize();
726 GetController()->GetOptimizeCircuit() ? optCircuit : circuit, hostId,
727 nrQubits, nrCbits,
true);
728 if (nrCbits == 0) nrCbits = nrQubits;
735 simulator->GetConfiguration(
"matrix_product_state_max_bond_dimension");
737 "matrix_product_state_truncation_threshold");
740 if (
distCirc->HasOpsAfterMeasurements() &&
746 distCirc->MoveMeasurementsAndResets();
748 auto method =
simulator->GetSimulationType();
749 const auto saveSimType = simType;
750 const auto saveMethod = method;
777 std::vector<bool> executed;
779 nrCbits, simType, method, executed);
792 !
distCirc->HasOpsAfterMeasurements()) ||
796 nrThreads = std::min(nrThreads, std::max<size_t>(shots, 1ULL));
801 std::mutex resultsMutex;
809 const size_t cntPerThread = std::max<size_t>(shots / nrThreads, 1ULL);
811 threadsPool.Resize(nrThreads);
812 threadsPool.SetFinishLimit(shots);
815 const size_t curCnt = std::min(cntPerThread, shots);
818 auto job = std::make_shared<ExecuteJob<Time>>(
819 dcirc, res, curCnt, nrQubits, nrCbits, nrCbits, simType, method,
828 job->optSim = optSim->Clone();
829 job->executedGates = executed;
832 threadsPool.AddRunJob(std::move(job));
835 threadsPool.WaitForFinish();
838 const size_t curCnt = shots;
840 auto job = std::make_shared<ExecuteJob<Time>>(
841 dcirc, res, curCnt, nrQubits, nrCbits, nrCbits, simType, method,
850 optSim->SetMultithreading(
true);
851 job->optSim = optSim;
852 job->executedGates = executed;
856 if (!recreateIfNeeded)
simulator = job->optSim;
876 if (!circuit)
return 0;
878 size_t distgates = 0;
880 for (
const auto &op : circuit->GetOperations())
937 size_t nrQubits = 0)
override {
947 simulator->Configure(
"matrix_product_state_max_bond_dimension",
950 simulator->Configure(
"matrix_product_state_truncation_threshold",
972 void Configure(
const char *key,
const char *value)
override {
973 if (!key || !value)
return;
975 if (std::string(
"matrix_product_state_max_bond_dimension") == key)
977 else if (std::string(
"matrix_product_state_truncation_threshold") == key)
979 else if (std::string(
"mps_sample_measure_algorithm") == key)
981 else if (std::string(
"use_double_precision") == key)
983 (std::string(
"1") == value || std::string(
"true") == value);
984 else if (std::string(
"max_simulators") == key)
998 std::shared_ptr<Simulators::ISimulator>
GetSimulator()
const override {
1039 std::shared_ptr<Schedulers::IScheduler<Time>>
GetScheduler()
const override {
1054 const std::shared_ptr<IHost<Time>>
GetHost(
size_t hostId)
const override {
1055 if (hostId >=
hosts.size())
return nullptr;
1057 return hosts[hostId];
1092 for (
const auto &host :
hosts) res += host->GetNumQubits();
1107 if (hostId >=
hosts.size())
return 0;
1109 return hosts[hostId]->GetNumQubits();
1123 for (
const auto &host :
hosts) res += host->GetNumNetworkEntangledQubits();
1141 if (hostId >=
hosts.size())
return 0;
1143 return hosts[hostId]->GetNumNetworkEntangledQubits();
1157 for (
const auto &host :
hosts) res += host->GetNumClassicalBits();
1174 if (hostId >=
hosts.size())
return 0;
1176 return hosts[hostId]->GetNumClassicalBits();
1215 const std::vector<uint8_t> &packet)
override {
1242 const auto qubits = op->AffectedQubits();
1244 if (qubits.empty())
return true;
1246 size_t firstQubit = qubits[0];
1248 for (
size_t q = 1; q < qubits.size(); ++q)
1268 const auto qubits = op->AffectedQubits();
1270 if (qubits.empty())
return false;
1274 size_t firstQubit = qubits[0];
1277 firstQubit = qubits[q];
1281 for (; q < qubits.size(); ++q)
1302 const auto qubits = op->AffectedQubits();
1304 if (qubits.empty())
return false;
1306 for (
size_t q = 0; q < qubits.size(); ++q)
1324 const auto qubits = op->AffectedQubits();
1325 if (qubits.size() != 2)
return false;
1343 if (!op->IsConditional())
return false;
1345 const auto qubits = op->AffectedQubits();
1347 const std::shared_ptr<Circuits::IConditionalOperation<Time>> condOp =
1348 std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(op);
1349 const auto &classicalBits = condOp->GetCondition()->GetBitsIndices();
1351 if (qubits.empty() && classicalBits.empty())
1352 throw std::runtime_error(
1353 "No classical bits specified!");
1361 for (
const auto bit : classicalBits)
1379 if (!op->IsConditional())
1380 throw std::runtime_error(
"Operation is not conditional!");
1382 std::shared_ptr<Circuits::IConditionalOperation<Time>> condOp =
1383 std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(op);
1384 const auto classicalBits = condOp->AffectedBits();
1386 if (classicalBits.empty())
1387 throw std::runtime_error(
"No classical bits specified!");
1401 for (
const auto &host :
hosts) {
1402 const bool present1 = host->IsQubitOnHost(qubitId1);
1403 const bool present2 = host->IsQubitOnHost(qubitId2);
1405 if (present1 && present2)
1407 else if (present1 || present2)
1424 for (
const auto &host :
hosts) {
1425 const bool present1 = host->IsClassicalBitOnHost(bitId1);
1426 const bool present2 = host->IsClassicalBitOnHost(bitId2);
1428 if (present1 && present2)
1430 else if (present1 || present2)
1448 size_t bitId)
const override {
1449 for (
const auto &host :
hosts) {
1450 const bool present1 = host->IsQubitOnHost(qubitId);
1451 const bool present2 = host->IsClassicalBitOnHost(bitId);
1453 if (present1 && present2)
1455 else if (present1 || present2)
1472 for (
const auto &host :
hosts)
1473 if (host->IsQubitOnHost(qubitId))
return host->GetId();
1475 return std::numeric_limits<size_t>::max();
1491 for (
const auto &host :
hosts)
1492 if (host->IsEntangledQubitOnHost(qubitId))
return host->GetId();
1494 return std::numeric_limits<size_t>::max();
1523 for (
const auto &host :
hosts)
1524 if (host->IsClassicalBitOnHost(classicalBitId))
return host->GetId();
1526 return std::numeric_limits<size_t>::max();
1538 if (hostId >=
hosts.size())
return std::vector<size_t>();
1540 return hosts[hostId]->GetQubitsIds();
1554 size_t hostId)
const override {
1555 if (hostId >=
hosts.size())
return std::vector<size_t>();
1557 return hosts[hostId]->GetNetworkEntangledQubitsIds();
1570 if (hostId >=
hosts.size())
return std::vector<size_t>();
1572 return hosts[hostId]->GetClassicalBitsIds();
1586 size_t hostId)
const override {
1587 if (hostId >=
hosts.size())
return std::vector<size_t>();
1589 return hosts[hostId]->GetEntangledQubitMeasurementBitIds();
1637 size_t qubitId2)
const override {
1654 throw std::runtime_error(
1655 "Entanglement between hosts is not supported in the simple network");
1670 throw std::runtime_error(
1671 "Entanglement between hosts is not supported in the simple network");
1684 throw std::runtime_error(
1685 "Entanglement between hosts is not supported in the simple network");
1750 else if (val > (
size_t)QC::QubitRegisterCalculator<>::GetNumberOfThreads())
1751 val = (size_t)QC::QubitRegisterCalculator<>::GetNumberOfThreads();
1859 std::shared_ptr<INetwork<Time>>
Clone()
const override {
1862 std::vector<Types::qubit_t> qubits(numHosts);
1863 std::vector<size_t> cbits(numHosts);
1865 for (
size_t h = 0; h < numHosts; ++h) {
1871 std::make_shared<SimpleDisconnectedNetwork<Time, Controller>>(qubits,
1890 size_t nrQubits,
size_t nrCbits,
size_t nrResultCbits,
1892 std::vector<bool> &executed,
bool multithreading =
false,
1893 bool dontRunCircuitStart =
false)
const override {
1904 std::pair<Simulators::SimulatorType, Simulators::SimulationType>>
1907 const bool checkTensorNetwork =
1923#ifndef NO_QISKIT_AER
1943 if (checkTensorNetwork &&
1953 simulatorTypes.emplace_back(
1963#ifndef NO_QISKIT_AER
1976 simulatorTypes.emplace_back(
1984 simulatorTypes.emplace_back(
1998 simulatorTypes.emplace_back(
2009 simulatorTypes.emplace_back(
2020 if (simulatorTypes.empty())
2022 else if (simulatorTypes.size() == 1) {
2023 simType = simulatorTypes[0].first;
2024 method = simulatorTypes[0].second;
2026 std::shared_ptr<Simulators::ISimulator> sim =
2031 sim->Configure(
"matrix_product_state_max_bond_dimension",
2034 sim->Configure(
"matrix_product_state_truncation_threshold",
2037 sim->Configure(
"mps_sample_measure_algorithm",
mpsSample.c_str());
2039 sim->SetMultithreading(
true);
2040 if (!dontRunCircuitStart)
2042 Time>::ExecuteUpToMeasurements(dcirc, nrQubits, nrCbits,
2043 nrResultCbits, sim, executed,
2051 simulatorTypes, dcirc, counts, nrQubits, nrCbits, nrResultCbits,
2054 dontRunCircuitStart);
2059 optimizeInitialQubitsMap = optimize;
2063 return optimizeInitialQubitsMap;
2067 mpsOptimizationBondDimensionThreshold = threshold;
2071 return mpsOptimizationBondDimensionThreshold;
2075 mpsOptimizationQubitsNumberThreshold = threshold;
2079 return mpsOptimizationQubitsNumberThreshold;
2095 const auto &qubitsMap = optimiser->GetReverseQubitsMap();
2113 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap) {
2117 theClassicalState.
Remap(qubitsMap);
2134 const auto &qubitsMap = optimiser->GetReverseQubitsMap();
2154 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap)
const {
2157 size_t numClassicalBits = 0;
2158 for (
const auto &[q, b] : bitsMap)
2159 if (b >= numClassicalBits) numClassicalBits = b + 1;
2163 for (
const auto &r : res) {
2166 translatedState.
Remap(bitsMap,
false, numClassicalBits);
2167 translatedRes[translatedState.
GetAllBits()] = r.second;
2170 res.swap(translatedRes);
2186 size_t &nrQubits,
size_t &nrCbits,
bool useSeparateSimForHosts =
false) {
2187 qubitsMapOnHost.clear();
2190 if (!circuit)
return {};
2193 std::static_pointer_cast<SimpleHost<Time>>(
GetHost(hostId));
2194 const size_t hostNrQubits = host->GetNumQubits();
2196 std::unordered_map<Types::qubit_t, Types::qubit_t> reverseQubitsMap;
2198 if (!useSeparateSimForHosts) {
2200 size_t mnq = std::numeric_limits<size_t>::max();
2202 size_t mnb = std::numeric_limits<size_t>::max();
2204 for (
const auto &op : circuit->GetOperations()) {
2205 const auto qbits = op->AffectedQubits();
2206 for (
auto q : qbits) {
2207 if (q > mxq) mxq = q;
2208 if (q < mnq) mnq = q;
2210 const auto cbits = op->AffectedBits();
2211 for (
auto b : cbits) {
2212 if (b > mxb) mxb = b;
2213 if (b < mnb) mnb = b;
2217 if (mnq > mxq) mnq = 0;
2218 if (mnb > mxb) mnb = 0;
2220 nrQubits = mxq - mnq + 1;
2221 nrCbits = mxb - mnb + 1;
2222 if (nrCbits < nrQubits) nrCbits = nrQubits;
2224 const size_t startQubit = host->GetStartQubitId();
2226 if (mnq < startQubit || mxq >= startQubit + hostNrQubits) {
2231 throw std::runtime_error(
"Circuit does not fit on the host!");
2233 for (
size_t i = 0; i < nrCbits; ++i) {
2234 const size_t mapFrom = mnq + i;
2235 const size_t mapTo = startQubit + i;
2237 qubitsMapOnHost[mapFrom] = mapTo;
2238 reverseQubitsMap[mapTo] = mapFrom;
2241 distCirc = std::static_pointer_cast<Circuits::Circuit<Time>>(
2242 circuit->Remap(qubitsMapOnHost, qubitsMapOnHost));
2245 return reverseQubitsMap;
2248 distCirc = circuit->RemapToContinuous(qubitsMapOnHost, reverseQubitsMap,
2251 assert(nrQubits == qubitsMapOnHost.size());
2253 if (nrQubits == 0) nrQubits = 1;
2259 throw std::runtime_error(
"Circuit does not fit on the host!");
2261 return reverseQubitsMap;
2279 GetNumberOfThreads();
2284 std::shared_ptr<Simulators::ISimulator>
2287 std::shared_ptr<Circuits::Circuit<Time>>
2290 std::shared_ptr<IController<Time>>
2295 std::vector<std::shared_ptr<IHost<Time>>>
2298 std::unique_ptr<Estimators::SimulatorsEstimatorInterface<Time>>
2304 bool recreateIfNeeded =
2306 std::unordered_map<Types::qubit_t, Types::qubit_t>
2310 const std::vector<std::string> *pauliStrings =
2314 bool optimizeInitialQubitsMap =
true;
2316 size_t mpsOptimizationBondDimensionThreshold =
2318 size_t mpsOptimizationQubitsNumberThreshold =
Circuit class for holding the sequence of operations.
The state class that stores the classical state of a quantum circuit execution.
const std::vector< bool > & GetAllBits() const
Get the classical bits.
void AllocateBits(size_t numBits)
Allocate more bits.
void Clear()
Clear the classical state.
void SetResultsInOrder(const std::vector< bool > &results)
Set the classical bits.
void Remap(const std::unordered_map< Types::qubit_t, Types::qubit_t > &mapping, bool ignoreNotMapped=false, size_t newSize=0)
Convert the state using the provided mapping.
An interface for runtime estimators.
The controller host interface.
std::unordered_set< SimulatorPair, boost::hash< SimulatorPair > > SimulatorsSet
std::shared_ptr< INetwork< Time > > getptr()
Get a shared pointer to this object.
typename Circuits::Circuit< Time >::ExecuteResults ExecuteResults
The simple network implementation.
Simulators::SimulatorType GetLastSimulatorType() const override
Get the last used simulator type.
void SetController(const std::shared_ptr< IController< Time > > &cntrl)
Set the network controller host.
std::vector< double > ExecuteExpectations(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, const std::vector< std::string > &paulis) override
Execute the circuit on the network and return the expectation values for the specified Pauli strings.
Simulators::SimulatorType lastSimulatorType
The last simulator type used.
size_t GetHostIdForEntangledQubit(size_t qubitId) const override
Get the host id for the specified qubit used for entanglement between hosts.
std::shared_ptr< Simulators::ISimulator > simulator
The quantum computing simulator for the network.
std::string singularValueThreshold
bool ExpectsClassicalBitFromOtherHost(const std::shared_ptr< Circuits::IOperation< Time > > &op) const override
Checks if a gate expects a classical bit from another host.
void ExecuteOnHost(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId) override
Execute the circuit on the specified host.
size_t GetHostIdForClassicalControl(const std::shared_ptr< Circuits::IOperation< Time > > &op) const override
Get the host id where the classical control bit resides for a conditioned gate.
void MarkEntangledQubitFree(size_t qubitId) override
Mark the specified qubit used for entanglement between hosts as free.
bool OptimizationSimulatorExists(Simulators::SimulatorType type, Simulators::SimulationType kind) const override
Checks if a simulator exists in the optimization set.
size_t GetNumNetworkEntangledQubits() const override
Get the number of qubits used for entanglement between hosts.
std::unordered_map< Types::qubit_t, Types::qubit_t > MapCircuitOnHost(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId, size_t &nrQubits, size_t &nrCbits, bool useSeparateSimForHosts=false)
Map the circuit on the host.
size_t GetNumQubitsForHost(size_t hostId) const override
Get the number of qubits in the network for the specified host.
Circuits::OperationState & GetState() override
Get the classical state of the network.
void AddOptimizationSimulator(Simulators::SimulatorType type, Simulators::SimulationType kind) override
Adds a simulator to the simulators optimization set.
ExecuteResults RepeatedExecuteOnHost(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId, size_t shots=1000) override
Execute the circuit on the specified host, repeatedly.
Simulators::SimulationType lastMethod
The last simulation method used.
ExecuteResults RepeatedExecute(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t shots=1000) override
Execute the circuit on the network, repeatedly.
bool optimizeSimulator
The flag to optimize the simulator.
std::vector< size_t > GetQubitsIds(size_t hostId) const override
Get the qubit ids for the specified host.
std::shared_ptr< Circuits::Circuit< Time > > GetDistributedCircuit() const override
Get the distributed circuit.
size_t GetNumQubits() const override
Get the number of qubits in the network.
bool GetOptimizeSimulator() const override
Returns the 'optimize' flag.
size_t GetNumberOfGatesDistributedOrCut(const std::shared_ptr< Circuits::Circuit< Time > > &circuit) const override
Get the number of gates that span more than one host.
size_t GetHostIdForClassicalBit(size_t classicalBitId) const override
Get the host id for the specified classical bit.
bool IsLocalOperation(const std::shared_ptr< Circuits::IOperation< Time > > &op) const override
Check if the circuit operation is local.
void Configure(const char *key, const char *value) override
Configures the network.
void CreateSimulator(Simulators::SimulatorType simType=Simulators::SimulatorType::kQCSim, Simulators::SimulationType simExecType=Simulators::SimulationType::kMatrixProductState, size_t nrQubits=0) override
Create the simulator for the network.
std::unique_ptr< Estimators::SimulatorsEstimatorInterface< Time > > simulatorsEstimator
The simulators estimator.
const std::shared_ptr< IHost< Time > > GetHost(size_t hostId) const override
Get the host with the specified id.
size_t GetNumHosts() const override
Get the number of hosts in the network.
void SetInitialQubitsMapOptimization(bool optimize=true) override
size_t GetMPSOptimizationBondDimensionThreshold() const override
size_t GetHostIdForQubit(size_t qubitId) const override
Get the host id for the specified qubit.
bool IsNetworkEntangledQubit(size_t qubitId) const override
Check if the specified qubit id is for a qubit used for entanglement between hosts.
std::vector< double > ExecuteOnHostExpectations(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId, const std::vector< std::string > &paulis) override
Execute the circuit on the specified host and return the expectation values for the specified Pauli s...
void RemoveOptimizationSimulator(Simulators::SimulatorType type, Simulators::SimulationType kind) override
Removes a simulator from the simulators optimization set.
std::shared_ptr< INetwork< Time > > Clone() const override
Clone the network.
std::complex< double > ExecuteOnHostProjectOnZero(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId) override
Execute circuit on host and return the projection onto the zero state.
Simulators::SimulationType GetLastSimulationType() const override
Get the last used simulation type.
void SetMaxSimulators(size_t val) override
Set the maximum number of simulators that can be used in the network.
bool AreQubitAndClassicalBitOnSameHost(size_t qubitId, size_t bitId) const override
Check if the specified qubit and classical bit are on the same host.
typename BaseClass::ExecuteResults ExecuteResults
The execute results type.
void SetOptimizeSimulator(bool optimize=true) override
Allows using an optimized simulator.
size_t GetNumClassicalBitsForHost(size_t hostId) const override
Get the number of classical bits in the network for the specified host.
bool IsEntanglingGate(const std::shared_ptr< Circuits::IOperation< Time > > &op) const override
Checks if a gate is an entangling gate.
void Execute(const std::shared_ptr< Circuits::Circuit< Time > > &circuit) override
Execute the circuit on the network.
std::vector< std::shared_ptr< IHost< Time > > > hosts
The hosts in the network.
BaseClass::SimulatorsSet simulatorsForOptimizations
bool AreQubitsOnSameHost(size_t qubitId1, size_t qubitId2) const override
Check if the specified qubits are on the same host.
std::vector< ExecuteResults > ExecuteScheduled(const std::vector< Schedulers::ExecuteCircuit< Time > > &circuits) override
Schedule and execute circuits on the network.
size_t GetHostIdForAnyQubit(size_t qubitId) const override
Get the host id for the specified qubit.
size_t GetNumNetworkEntangledQubitsForHost(size_t hostId) const override
Get the number of qubits used for entanglement between hosts for the specified host.
Circuits::OperationState classicalState
The classical state of the network.
void ConvertBackResults(ExecuteResults &res, const std::unordered_map< Types::qubit_t, Types::qubit_t > &bitsMap) const
Converts back the results using the passed qubits map.
void ConvertBackState()
Converts back the state from the optimized network distribution mapping.
bool GetInitialQubitsMapOptimization() const override
std::shared_ptr< Circuits::Circuit< Time > > distCirc
The distributed circuit.
std::shared_ptr< Schedulers::IScheduler< Time > > GetScheduler() const override
Get the scheduler for the network.
size_t GetNumClassicalBits() const override
Get the number of classical bits in the network.
const std::shared_ptr< IController< Time > > GetController() const override
Get the controller for the network.
bool IsDistributedOperation(const std::shared_ptr< Circuits::IOperation< Time > > &op) const override
Check if the circuit operation is distributed.
std::vector< std::shared_ptr< IHost< Time > > > & GetHosts()
Get the hosts in the network.
bool SendPacket(size_t fromHostId, size_t toHostId, const std::vector< uint8_t > &packet) override
Sends a packet between two hosts.
const BaseClass::SimulatorsSet & GetSimulatorsSet() const override
Get the optimizations simulators set.
std::shared_ptr< Simulators::ISimulator > ChooseBestSimulator(std::shared_ptr< Circuits::Circuit< Time > > &dcirc, size_t &counts, size_t nrQubits, size_t nrCbits, size_t nrResultCbits, Simulators::SimulatorType &simType, Simulators::SimulationType &method, std::vector< bool > &executed, bool multithreading=false, bool dontRunCircuitStart=false) const override
Choose the best simulator for the given circuit.
std::shared_ptr< Simulators::ISimulator > GetSimulator() const override
Get the simulator for the network.
bool OperatesWithNetworkEntangledQubit(const std::shared_ptr< Circuits::IOperation< Time > > &op) const override
Check if the circuit operation operates on the entanglement qubits between hosts.
std::vector< std::complex< double > > ExecuteOnHostAmplitudes(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId) override
Execute circuit on host and return full statevector amplitudes.
size_t GetMaxSimulators() const override
Get the maximum number of simulators that can be used in the network.
void MarkEntangledQubitsBusy(size_t qubitId1, size_t qubitId2) override
Mark the pair of the specified qubits used for entanglement between hosts as busy.
void CreateScheduler(SchedulerType schType=SchedulerType::kNoEntanglementQubitsParallel) override
Create the scheduler for the network.
std::vector< size_t > GetClassicalBitsIds(size_t hostId) const override
Get the classical bit ids for the specified host.
std::vector< size_t > GetEntangledQubitMeasurementBitIds(size_t hostId) const override
Get the classical bit ids used for measurement of entanglement qubits between the hosts for the speci...
bool AreEntanglementQubitsBusy(size_t qubitId1, size_t qubitId2) const override
Check if any of the two specified qubits used for entanglement between hosts are busy.
size_t maxSimulators
The maximum number of simulators that can be used in the network.
std::shared_ptr< IController< Time > > controller
The controller for the network.
void ClearEntanglements() override
Clear all entanglements between hosts in the network.
void ConvertBackResults(ExecuteResults &res)
Converts back the results from the optimized network distribution mapping.
void SetMPSOptimizationQubitsNumberThreshold(size_t threshold) override
bool IsEntanglementQubitBusy(size_t qubitId) const override
Check if the specified qubit used for entanglement between hosts is busy.
void RemoveAllOptimizationSimulatorsAndAdd(Simulators::SimulatorType type, Simulators::SimulationType kind) override
Removes all simulators from the simulators optimization set and adds the one specified.
void CreateNetwork(const std::vector< Types::qubit_t > &qubits, const std::vector< size_t > &cbits)
Creates the network hosts and controller.
SimpleDisconnectedNetwork(const std::vector< Types::qubit_t > &qubits={}, const std::vector< size_t > &cbits={})
The constructor.
std::vector< size_t > GetNetworkEntangledQubitsIds(size_t hostId) const override
Get the qubit ids used for entanglement between hosts for the specified host.
void ConvertBackState(const std::unordered_map< Types::qubit_t, Types::qubit_t > &qubitsMap)
Converts back the state using the passed qubits map.
NetworkType GetType() const override
Get the type of the network.
void SetMPSOptimizationBondDimensionThreshold(size_t threshold) override
bool AreClassicalBitsOnSameHost(size_t bitId1, size_t bitId2) const override
Check if the specified classical bits are on the same host.
size_t GetMPSOptimizationQubitsNumberThreshold() const override
The simple host implementation.
static bool IsGpuLibraryAvailable()
static std::shared_ptr< ISimulator > CreateSimulator(SimulatorType t=SimulatorType::kQCSim, SimulationType method=SimulationType::kMatrixProductState)
Create a quantum computing simulator.
ThreadsPool class for holding and controlling a pool of threads.
@ kGate
the usual quantum gate, result stays in simulator's state
NetworkType
The type of the network.
@ kSimpleDisconnectedNetwork
Simple network, no communication among hosts, sequential simulation.
SchedulerType
The type of the network scheduler for scheduling execution of multiple circuits.
@ kNoEntanglementQubitsParallel
SimulationType
The type of simulation.
@ kStatevector
statevector simulation type
@ kMatrixProductState
matrix product state simulation type
@ kStabilizer
Clifford gates simulation type.
@ kPauliPropagator
Pauli propagator simulation type.
@ kTensorNetwork
Tensor network simulation type.
SimulatorType
The type of simulator.
@ kCompositeQCSim
composite qcsim simulator type
@ kQCSim
qcsim simulator type
@ kQiskitAer
qiskit aer simulator type
@ kQuestSim
quest simulator type
@ kCompositeQiskitAer
composite qiskit aer simulator type
@ kGpuSim
gpu simulator type
double time_type
The type of time.
A way to pack together a circuit and the number of shots for its execution.