15#ifndef _SIMPLE_NETWORK_H_
16#define _SIMPLE_NETWORK_H_
18#include "QubitRegister.h"
22#include "../Estimators/SimulatorsEstimatorInterface.h"
40template <
typename Time = Types::time_type,
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) {
283 const auto recreate = recreateIfNeeded;
287 size_t numQubits = 2;
291 numQubits =
simulator->GetNumberOfQubits();
294 recreateIfNeeded =
false;
295 pauliStrings = &paulis;
297 pauliStrings =
nullptr;
299 recreateIfNeeded = recreate;
303 const auto &first = *res.begin();
311 const size_t offsetBase = qubitsMapOnHost.size();
313 std::vector<double> expectations(paulis.size(), 1.);
316 const size_t numOps =
simulator->GetNumberOfQubits();
319 for (
size_t i = 0; i < paulis.size(); ++i) {
320 std::string translated(std::max(numOps, paulis[i].size()),
'I');
322 size_t offset = offsetBase;
324 for (
size_t j = 0; j < paulis[i].size(); ++j) {
325 auto pos = qubitsMapOnHost.find(j);
326 if (pos != qubitsMapOnHost.end())
327 translated[pos->second] = paulis[i][j];
329 translated[offset] = paulis[i][j];
336 expectations[i] =
simulator->ExpectationValue(translated);
341 method !=
simulator->GetSimulationType() ||
342 simulator->GetNumberOfQubits() != numQubits))
363 size_t shots = 1000)
override {
370 for (
auto q :
distCirc->AffectedQubits()) {
373 <<
"This is a distributed circuit, using entanglement or cutting"
383 if (
distCirc->HasOpsAfterMeasurements() &&
389 distCirc->MoveMeasurementsAndResets();
391 auto method =
simulator->GetSimulationType();
393 const auto saveSimType = simType;
394 const auto saveMethod = method;
418 simulator->GetConfiguration(
"matrix_product_state_max_bond_dimension");
420 "matrix_product_state_truncation_threshold");
431 std::vector<bool> executed;
434 simType, method, executed);
445 !
distCirc->HasOpsAfterMeasurements())
448 nrThreads = std::min(nrThreads, std::max<size_t>(shots, 1ULL));
450 std::mutex resultsMutex;
468 const size_t cntPerThread = std::max<size_t>(shots / nrThreads, 1ULL);
470 threadsPool.Resize(nrThreads);
471 threadsPool.SetFinishLimit(shots);
474 const size_t curCnt = std::min(cntPerThread, shots);
478 auto job = std::make_shared<ExecuteJob<Time>>(
479 dcirc, res, curCnt, nrQubits, nrQubits, nrCbitsResults, simType,
480 method, resultsMutex);
488 job->optSim = optSim->Clone();
489 job->executedGates = executed;
492 threadsPool.AddRunJob(std::move(job));
495 threadsPool.WaitForFinish();
498 const size_t curCnt = shots;
500 auto job = std::make_shared<ExecuteJob<Time>>(
501 dcirc, res, curCnt, nrQubits, nrQubits, nrCbitsResults, simType,
502 method, resultsMutex);
510 optSim->SetMultithreading(
true);
511 job->optSim = optSim;
512 job->executedGates = executed;
514 if (
simulator && method == saveMethod && simType == saveSimType) {
517 job->optSim = optSim;
518 job->executedGates.resize(
distCirc->size(),
525 if (!recreateIfNeeded)
simulator = job->optSim;
552 size_t shots = 1000)
override {
553 if (!circuit || hostId >=
GetNumHosts())
return {};
558 std::shared_ptr<Circuits::Circuit<Time>> optCircuit;
561 std::static_pointer_cast<Circuits::Circuit<Time>>(circuit->Clone());
562 optCircuit->Optimize();
565 GetController()->GetOptimizeCircuit() ? optCircuit : circuit, hostId,
566 nrQubits, nrCbits,
true);
567 if (nrCbits == 0) nrCbits = nrQubits;
574 simulator->GetConfiguration(
"matrix_product_state_max_bond_dimension");
576 "matrix_product_state_truncation_threshold");
579 if (
distCirc->HasOpsAfterMeasurements() &&
585 distCirc->MoveMeasurementsAndResets();
587 auto method =
simulator->GetSimulationType();
588 const auto saveSimType = simType;
589 const auto saveMethod = method;
616 std::vector<bool> executed;
618 nrCbits, simType, method, executed);
631 !
distCirc->HasOpsAfterMeasurements())
634 nrThreads = std::min(nrThreads, std::max<size_t>(shots, 1ULL));
639 std::mutex resultsMutex;
647 const size_t cntPerThread = std::max<size_t>(shots / nrThreads, 1ULL);
649 threadsPool.Resize(nrThreads);
650 threadsPool.SetFinishLimit(shots);
653 const size_t curCnt = std::min(cntPerThread, shots);
656 auto job = std::make_shared<ExecuteJob<Time>>(
657 dcirc, res, curCnt, nrQubits, nrCbits, nrCbits, simType, method,
666 job->optSim = optSim->Clone();
667 job->executedGates = executed;
670 threadsPool.AddRunJob(std::move(job));
673 threadsPool.WaitForFinish();
676 const size_t curCnt = shots;
678 auto job = std::make_shared<ExecuteJob<Time>>(
679 dcirc, res, curCnt, nrQubits, nrCbits, nrCbits, simType, method,
688 optSim->SetMultithreading(
true);
689 job->optSim = optSim;
690 job->executedGates = executed;
694 if (!recreateIfNeeded)
simulator = job->optSim;
714 if (!circuit)
return 0;
716 size_t distgates = 0;
718 for (
const auto &op : circuit->GetOperations())
775 size_t nrQubits = 0)
override {
785 simulator->Configure(
"matrix_product_state_max_bond_dimension",
788 simulator->Configure(
"matrix_product_state_truncation_threshold",
809 void Configure(
const char *key,
const char *value)
override {
810 if (!key || !value)
return;
812 if (std::string(
"matrix_product_state_max_bond_dimension") == key)
814 else if (std::string(
"matrix_product_state_truncation_threshold") == key)
816 else if (std::string(
"mps_sample_measure_algorithm") == key)
818 else if (std::string(
"max_simulators") == key)
832 std::shared_ptr<Simulators::ISimulator>
GetSimulator()
const override {
873 std::shared_ptr<Schedulers::IScheduler<Time>>
GetScheduler()
const override {
888 const std::shared_ptr<IHost<Time>>
GetHost(
size_t hostId)
const override {
889 if (hostId >=
hosts.size())
return nullptr;
891 return hosts[hostId];
926 for (
const auto &host :
hosts) res += host->GetNumQubits();
941 if (hostId >=
hosts.size())
return 0;
943 return hosts[hostId]->GetNumQubits();
957 for (
const auto &host :
hosts) res += host->GetNumNetworkEntangledQubits();
975 if (hostId >=
hosts.size())
return 0;
977 return hosts[hostId]->GetNumNetworkEntangledQubits();
991 for (
const auto &host :
hosts) res += host->GetNumClassicalBits();
1008 if (hostId >=
hosts.size())
return 0;
1010 return hosts[hostId]->GetNumClassicalBits();
1049 const std::vector<uint8_t> &packet)
override {
1076 const auto qubits = op->AffectedQubits();
1078 if (qubits.empty())
return true;
1080 size_t firstQubit = qubits[0];
1082 for (
size_t q = 1; q < qubits.size(); ++q)
1102 const auto qubits = op->AffectedQubits();
1104 if (qubits.empty())
return false;
1108 size_t firstQubit = qubits[0];
1111 firstQubit = qubits[q];
1115 for (; q < qubits.size(); ++q)
1136 const auto qubits = op->AffectedQubits();
1138 if (qubits.empty())
return false;
1140 for (
size_t q = 0; q < qubits.size(); ++q)
1158 const auto qubits = op->AffectedQubits();
1159 if (qubits.size() != 2)
return false;
1177 if (!op->IsConditional())
return false;
1179 const auto qubits = op->AffectedQubits();
1181 const std::shared_ptr<Circuits::IConditionalOperation<Time>> condOp =
1182 std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(op);
1183 const auto &classicalBits = condOp->GetCondition()->GetBitsIndices();
1185 if (qubits.empty() && classicalBits.empty())
1186 throw std::runtime_error(
1187 "No classical bits specified!");
1195 for (
const auto bit : classicalBits)
1213 if (!op->IsConditional())
1214 throw std::runtime_error(
"Operation is not conditional!");
1216 std::shared_ptr<Circuits::IConditionalOperation<Time>> condOp =
1217 std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(op);
1218 const auto classicalBits = condOp->AffectedBits();
1220 if (classicalBits.empty())
1221 throw std::runtime_error(
"No classical bits specified!");
1235 for (
const auto &host :
hosts) {
1236 const bool present1 = host->IsQubitOnHost(qubitId1);
1237 const bool present2 = host->IsQubitOnHost(qubitId2);
1239 if (present1 && present2)
1241 else if (present1 || present2)
1258 for (
const auto &host :
hosts) {
1259 const bool present1 = host->IsClassicalBitOnHost(bitId1);
1260 const bool present2 = host->IsClassicalBitOnHost(bitId2);
1262 if (present1 && present2)
1264 else if (present1 || present2)
1282 size_t bitId)
const override {
1283 for (
const auto &host :
hosts) {
1284 const bool present1 = host->IsQubitOnHost(qubitId);
1285 const bool present2 = host->IsClassicalBitOnHost(bitId);
1287 if (present1 && present2)
1289 else if (present1 || present2)
1306 for (
const auto &host :
hosts)
1307 if (host->IsQubitOnHost(qubitId))
return host->GetId();
1309 return std::numeric_limits<size_t>::max();
1325 for (
const auto &host :
hosts)
1326 if (host->IsEntangledQubitOnHost(qubitId))
return host->GetId();
1328 return std::numeric_limits<size_t>::max();
1357 for (
const auto &host :
hosts)
1358 if (host->IsClassicalBitOnHost(classicalBitId))
return host->GetId();
1360 return std::numeric_limits<size_t>::max();
1372 if (hostId >=
hosts.size())
return std::vector<size_t>();
1374 return hosts[hostId]->GetQubitsIds();
1388 size_t hostId)
const override {
1389 if (hostId >=
hosts.size())
return std::vector<size_t>();
1391 return hosts[hostId]->GetNetworkEntangledQubitsIds();
1404 if (hostId >=
hosts.size())
return std::vector<size_t>();
1406 return hosts[hostId]->GetClassicalBitsIds();
1420 size_t hostId)
const override {
1421 if (hostId >=
hosts.size())
return std::vector<size_t>();
1423 return hosts[hostId]->GetEntangledQubitMeasurementBitIds();
1471 size_t qubitId2)
const override {
1488 throw std::runtime_error(
1489 "Entanglement between hosts is not supported in the simple network");
1504 throw std::runtime_error(
1505 "Entanglement between hosts is not supported in the simple network");
1518 throw std::runtime_error(
1519 "Entanglement between hosts is not supported in the simple network");
1584 else if (val > (
size_t)QC::QubitRegisterCalculator<>::GetNumberOfThreads())
1585 val = (size_t)QC::QubitRegisterCalculator<>::GetNumberOfThreads();
1693 std::shared_ptr<INetwork<Time>>
Clone()
const override {
1696 std::vector<Types::qubit_t> qubits(numHosts);
1697 std::vector<size_t> cbits(numHosts);
1699 for (
size_t h = 0; h < numHosts; ++h) {
1705 std::make_shared<SimpleDisconnectedNetwork<Time, Controller>>(qubits,
1724 size_t nrQubits,
size_t nrCbits,
size_t nrResultCbits,
1726 std::vector<bool> &executed,
bool multithreading =
false,
1727 bool dontRunCircuitStart =
false)
const override {
1738 std::pair<Simulators::SimulatorType, Simulators::SimulationType>>
1741 const bool checkTensorNetwork =
1757#ifndef NO_QISKIT_AER
1777 if (checkTensorNetwork &&
1787 simulatorTypes.emplace_back(
1791#ifndef NO_QISKIT_AER
1804 simulatorTypes.emplace_back(
1812 simulatorTypes.emplace_back(
1826 simulatorTypes.emplace_back(
1837 if (simulatorTypes.empty())
1839 else if (simulatorTypes.size() == 1) {
1840 simType = simulatorTypes[0].first;
1841 method = simulatorTypes[0].second;
1843 std::shared_ptr<Simulators::ISimulator> sim =
1848 sim->Configure(
"matrix_product_state_max_bond_dimension",
1851 sim->Configure(
"matrix_product_state_truncation_threshold",
1854 sim->Configure(
"mps_sample_measure_algorithm",
mpsSample.c_str());
1856 sim->SetMultithreading(
true);
1857 if (!dontRunCircuitStart)
1859 Time>::ExecuteUpToMeasurements(dcirc, nrQubits, nrCbits,
1860 nrResultCbits, sim, executed,
1868 simulatorTypes, dcirc, counts, nrQubits, nrCbits, nrResultCbits,
1871 dontRunCircuitStart);
1887 const auto &qubitsMap = optimiser->GetReverseQubitsMap();
1905 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap) {
1909 theClassicalState.
Remap(qubitsMap);
1926 const auto &qubitsMap = optimiser->GetReverseQubitsMap();
1946 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap)
const {
1949 size_t numClassicalBits = 0;
1950 for (
const auto &[q, b] : bitsMap)
1951 if (b >= numClassicalBits) numClassicalBits = b + 1;
1955 for (
const auto &r : res) {
1958 translatedState.
Remap(bitsMap,
false, numClassicalBits);
1959 translatedRes[translatedState.
GetAllBits()] = r.second;
1962 res.swap(translatedRes);
1978 size_t &nrQubits,
size_t &nrCbits,
bool useSeparateSimForHosts =
false) {
1979 qubitsMapOnHost.clear();
1982 if (!circuit)
return {};
1985 std::static_pointer_cast<SimpleHost<Time>>(
GetHost(hostId));
1986 const size_t hostNrQubits = host->GetNumQubits();
1988 std::unordered_map<Types::qubit_t, Types::qubit_t> reverseQubitsMap;
1990 if (!useSeparateSimForHosts) {
1992 size_t mnq = std::numeric_limits<size_t>::max();
1994 size_t mnb = std::numeric_limits<size_t>::max();
1996 for (
const auto &op : circuit->GetOperations()) {
1997 const auto qbits = op->AffectedQubits();
1998 for (
auto q : qbits) {
1999 if (q > mxq) mxq = q;
2000 if (q < mnq) mnq = q;
2002 const auto cbits = op->AffectedBits();
2003 for (
auto b : cbits) {
2004 if (b > mxb) mxb = b;
2005 if (b < mnb) mnb = b;
2009 if (mnq > mxq) mnq = 0;
2010 if (mnb > mxb) mnb = 0;
2012 nrQubits = mxq - mnq + 1;
2013 nrCbits = mxb - mnb + 1;
2014 if (nrCbits < nrQubits) nrCbits = nrQubits;
2016 const size_t startQubit = host->GetStartQubitId();
2018 if (mnq < startQubit || mxq >= startQubit + hostNrQubits) {
2023 throw std::runtime_error(
"Circuit does not fit on the host!");
2025 for (
size_t i = 0; i < nrCbits; ++i) {
2026 const size_t mapFrom = mnq + i;
2027 const size_t mapTo = startQubit + i;
2029 qubitsMapOnHost[mapFrom] = mapTo;
2030 reverseQubitsMap[mapTo] = mapFrom;
2033 distCirc = std::static_pointer_cast<Circuits::Circuit<Time>>(
2034 circuit->Remap(qubitsMapOnHost, qubitsMapOnHost));
2037 return reverseQubitsMap;
2040 distCirc = circuit->RemapToContinuous(qubitsMapOnHost, reverseQubitsMap,
2043 assert(nrQubits == qubitsMapOnHost.size());
2045 if (nrQubits == 0) nrQubits = 1;
2051 throw std::runtime_error(
"Circuit does not fit on the host!");
2053 return reverseQubitsMap;
2070 GetNumberOfThreads();
2075 std::shared_ptr<Simulators::ISimulator>
2078 std::shared_ptr<Circuits::Circuit<Time>>
2081 std::shared_ptr<IController<Time>>
2086 std::vector<std::shared_ptr<IHost<Time>>>
2089 std::unique_ptr<Estimators::SimulatorsEstimatorInterface<Time>>
2095 bool recreateIfNeeded =
2097 std::unordered_map<Types::qubit_t, Types::qubit_t>
2101 const std::vector<std::string> *pauliStrings =
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.
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.
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.
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.
std::vector< double > ExecuteOnHostExpectations(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, size_t hostId, const std::vector< std::string > &paulis)
Execute the circuit on the specified host and return the expectation values for the specified Pauli s...
std::shared_ptr< Simulators::ISimulator > ChooseBestSimulator(const 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< 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 > 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.
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.
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.
bool AreClassicalBitsOnSameHost(size_t bitId1, size_t bitId2) const override
Check if the specified classical bits are on the same host.
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.
@ kTensorNetwork
Tensor network simulation type.
SimulatorType
The type of simulator.
@ kCompositeQCSim
composite qcsim simulator type
@ kQCSim
qcsim simulator type
@ kQiskitAer
qiskit aer simulator type
@ kCompositeQiskitAer
composite qiskit aer simulator type
@ kGpuSim
gpu simulator type
A way to pack together a circuit and the number of shots for its execution.