Skip to content

Commit a714780

Browse files
committed
Improved swaps optimization in networks, added a test for checking no optimization results against swaps optimized results through the network, added the possibility of overriding the guess for lookahead.
1 parent 97e4f9b commit a714780

9 files changed

Lines changed: 268 additions & 64 deletions

File tree

Network/Network.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,14 @@ class INetwork : public std::enable_shared_from_this<INetwork<Time>> {
988988
virtual void SetMPSOptimizationQubitsNumberThreshold(size_t threshold) = 0;
989989

990990
virtual size_t GetMPSOptimizationQubitsNumberThreshold() const = 0;
991+
992+
virtual void SetLookaheadDepth(int depth) = 0;
993+
994+
virtual int GetLookaheadDepth() const = 0;
995+
996+
virtual void SetLookaheadDepthWithHeuristic(int depth) = 0;
997+
998+
virtual int GetLookaheadDepthWithHeuristic() const = 0;
991999
};
9921000

9931001
} // namespace Network

Network/NetworkJob.h

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -384,24 +384,45 @@ class ExecuteJob {
384384

385385
if (network->GetMPSOptimizeSwaps()) {
386386
// TODO: come up with something better!
387-
int lookaheadVal = nrQubits;
388-
if (nrQubits > 15) lookaheadVal = 15;
389-
390-
const int lookaheadDepth = layers.size() < 10 ? 5
391-
: layers.size() < 20
392-
? static_cast<int>(lookaheadVal)
393-
: layers.size() < 35 ? 1.5 * lookaheadVal
394-
: 2 * lookaheadVal;
395-
396-
const int lookaheadHeuristicDepth = layers.size() < 10 ? 4
397-
: layers.size() < 20
398-
? lookaheadDepth - 1
399-
: lookaheadDepth - 2;
387+
int lookaheadDepthLocal = network->GetLookaheadDepth();
388+
389+
if (lookaheadDepthLocal == std::numeric_limits<int>::max()) {
390+
double avgTwoQubitGatesPerLayer = 0.0;
391+
for (const auto &layer : layers) {
392+
int twoQubitGates = 0;
393+
for (const auto &op : layer->GetOperations()) {
394+
if (op->AffectedQubits().size() >= 2) {
395+
++twoQubitGates;
396+
}
397+
}
398+
avgTwoQubitGatesPerLayer += twoQubitGates;
399+
}
400+
avgTwoQubitGatesPerLayer /= layers.size();
401+
402+
int lookaheadVal =
403+
static_cast<int>(4. * avgTwoQubitGatesPerLayer);
404+
if (lookaheadVal > 15) lookaheadVal = 15;
405+
406+
lookaheadDepthLocal = layers.size() < 10 || nrQubits <= 10 ? 0
407+
: layers.size() < 20
408+
? static_cast<int>(lookaheadVal)
409+
: layers.size() < 35 ? 1.5 * lookaheadVal
410+
: 2 * lookaheadVal;
411+
}
412+
413+
int lookaheadHeuristicDepthLocal =
414+
network->GetLookaheadDepthWithHeuristic();
415+
416+
if (lookaheadHeuristicDepthLocal == std::numeric_limits<int>::max())
417+
lookaheadHeuristicDepthLocal =
418+
layers.size() < 10 || nrQubits <= 10 ? 0
419+
: layers.size() < 20
420+
? lookaheadDepthLocal - 1
421+
: lookaheadDepthLocal - 2;
400422

401423
sim->SetUseOptimalMeetingPosition(true);
402-
sim->SetLookaheadDepth(lookaheadDepth);
403-
sim->SetLookaheadDepthWithHeuristic(lookaheadHeuristicDepth);
404-
424+
sim->SetLookaheadDepth(lookaheadDepthLocal);
425+
sim->SetLookaheadDepthWithHeuristic(lookaheadHeuristicDepthLocal);
405426
sim->SetUpcomingGates(dcirc->GetOperations());
406427
}
407428
}

Network/SimpleDisconnectedNetwork.h

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
#include "../Simulators/MPSDummySimulator.h"
2525

26-
2726
namespace Network {
2827

2928
/**
@@ -407,7 +406,8 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
407406
const size_t n = simulator->GetNumberOfQubits();
408407
const size_t dim = 1ULL << n;
409408
amplitudes.resize(dim);
410-
for (size_t state = 0; state < dim; ++state) amplitudes[state] = simulator->Amplitude(state);
409+
for (size_t state = 0; state < dim; ++state)
410+
amplitudes[state] = simulator->Amplitude(state);
411411

412412
// Remap amplitudes back to the original qubit ordering if qubits were
413413
// remapped during execution on the host.
@@ -419,8 +419,7 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
419419
std::vector<size_t> simToOrig(n);
420420
size_t offset = offsetBase;
421421

422-
for (size_t qbit = 0; qbit < n; ++qbit)
423-
{
422+
for (size_t qbit = 0; qbit < n; ++qbit) {
424423
auto pos = qubitsMapOnHost.find(qbit);
425424
if (pos != qubitsMapOnHost.end())
426425
simToOrig[pos->second] = pos->first;
@@ -652,7 +651,7 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
652651
if (optSim) {
653652
job->optSim = optSim->Clone();
654653
job->executedGates = executed;
655-
}
654+
}
656655

657656
threadsPool.AddRunJob(std::move(job));
658657
}
@@ -680,7 +679,7 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
680679
} else {
681680
if (simulator && method == saveMethod && simType == saveSimType) {
682681
// use the already created simulator
683-
682+
684683
optSim = simulator;
685684
job->optSim = optSim;
686685
OptimizeMPSInitialQubitsMap(optSim, distCirc,
@@ -2048,14 +2047,14 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
20482047
singularValueThreshold.c_str());
20492048
if (!mpsSample.empty())
20502049
sim->Configure("mps_sample_measure_algorithm", mpsSample.c_str());
2051-
2050+
20522051
sim->AllocateQubits(nrQubits);
20532052
sim->Initialize();
20542053

20552054
OptimizeMPSInitialQubitsMap(sim, dcirc, nrQubits);
20562055
} else {
20572056
sim->AllocateQubits(nrQubits);
2058-
sim->Initialize();
2057+
sim->Initialize();
20592058
}
20602059

20612060
if (!dontRunCircuitStart) {
@@ -2072,9 +2071,9 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
20722071

20732072
std::shared_ptr<Simulators::ISimulator> sim =
20742073
simulatorsEstimator->ChooseBestSimulator(
2075-
simulatorTypes, dcirc, counts, nrQubits, nrCbits, nrResultCbits,
2076-
simType, method, executed, maxBondDim, singularValueThreshold,
2077-
mpsSample, GetMaxSimulators(), pauliStrings, multithreading);
2074+
simulatorTypes, dcirc, counts, nrQubits, nrCbits, nrResultCbits,
2075+
simType, method, executed, maxBondDim, singularValueThreshold,
2076+
mpsSample, GetMaxSimulators(), pauliStrings, multithreading);
20782077

20792078
if (sim) {
20802079
sim->AllocateQubits(nrQubits);
@@ -2093,7 +2092,6 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
20932092
return sim;
20942093
}
20952094

2096-
20972095
void SetInitialQubitsMapOptimization(bool optimize = true) override {
20982096
optimizeInitialQubitsMap = optimize;
20992097
}
@@ -2124,6 +2122,26 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
21242122
return mpsOptimizationQubitsNumberThreshold;
21252123
}
21262124

2125+
void SetLookaheadDepth(int depth) override {
2126+
if (depth < 0) depth = std::numeric_limits<int>::max();
2127+
2128+
lookaheadDepth = depth;
2129+
}
2130+
2131+
int GetLookaheadDepth() const override { return lookaheadDepth; }
2132+
2133+
void SetLookaheadDepthWithHeuristic(int depth) override {
2134+
if (depth < 0) depth = std::numeric_limits<int>::max();
2135+
2136+
if (depth > lookaheadDepth) depth = lookaheadDepth;
2137+
2138+
lookaheadDepthWithHeuristic = depth;
2139+
}
2140+
2141+
int GetLookaheadDepthWithHeuristic() const override {
2142+
return lookaheadDepthWithHeuristic;
2143+
}
2144+
21272145
protected:
21282146
void OptimizeMPSInitialQubitsMap(
21292147
std::shared_ptr<Simulators::ISimulator> &sim,
@@ -2142,18 +2160,6 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
21422160
dcirc->ConvertForCutting(); // convert the three qubit gates
21432161
auto layers = dcirc->ToMultipleQubitsLayersNoClone();
21442162

2145-
double avgTwoQubitGatesPerLayer = 0.0;
2146-
for (const auto &layer : layers) {
2147-
int twoQubitGates = 0;
2148-
for (const auto &op : layer->GetOperations()) {
2149-
if (op->AffectedQubits().size() >= 2) {
2150-
++twoQubitGates;
2151-
}
2152-
}
2153-
avgTwoQubitGatesPerLayer += twoQubitGates;
2154-
}
2155-
avgTwoQubitGatesPerLayer /= layers.size();
2156-
21572163
Simulators::MPSDummySimulator dummySim(nrQubits);
21582164
if (!maxBondDim.empty())
21592165
dummySim.SetMaxBondDimension(maxBondDimValue);
@@ -2168,24 +2174,43 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
21682174

21692175
if (mpsOptimizeSwaps) {
21702176
// TODO: come up with something better!
2171-
int lookaheadVal = static_cast<int>(4. * avgTwoQubitGatesPerLayer);
2172-
if (lookaheadVal > 15) lookaheadVal = 15;
2177+
int lookaheadDepthLocal = lookaheadDepth;
2178+
2179+
if (lookaheadDepthLocal == std::numeric_limits<int>::max()) {
2180+
double avgTwoQubitGatesPerLayer = 0.0;
2181+
for (const auto &layer : layers) {
2182+
int twoQubitGates = 0;
2183+
for (const auto &op : layer->GetOperations()) {
2184+
if (op->AffectedQubits().size() >= 2) {
2185+
++twoQubitGates;
2186+
}
2187+
}
2188+
avgTwoQubitGatesPerLayer += twoQubitGates;
2189+
}
2190+
avgTwoQubitGatesPerLayer /= layers.size();
21732191

2174-
const int lookaheadDepth = layers.size() < 10 ? 0
2175-
: layers.size() < 20
2176-
? static_cast<int>(lookaheadVal)
2177-
: layers.size() < 35 ? 1.5 * lookaheadVal
2178-
: 2 * lookaheadVal;
2192+
int lookaheadVal = static_cast<int>(4. * avgTwoQubitGatesPerLayer);
2193+
if (lookaheadVal > 15) lookaheadVal = 15;
21792194

2180-
const int lookaheadHeuristicDepth = layers.size() < 10 ? 0
2181-
: layers.size() < 20
2182-
? lookaheadDepth - 1
2183-
: lookaheadDepth - 2;
2195+
lookaheadDepthLocal = layers.size() < 10 || nrQubits <= 10 ? 0
2196+
: layers.size() < 20
2197+
? static_cast<int>(lookaheadVal)
2198+
: layers.size() < 35 ? 1.5 * lookaheadVal
2199+
: 2 * lookaheadVal;
2200+
}
21842201

2185-
sim->SetUseOptimalMeetingPosition(true);
2186-
sim->SetLookaheadDepth(lookaheadDepth);
2187-
sim->SetLookaheadDepthWithHeuristic(lookaheadHeuristicDepth);
2202+
int lookaheadHeuristicDepthLocal = lookaheadDepthWithHeuristic;
21882203

2204+
if (lookaheadHeuristicDepthLocal == std::numeric_limits<int>::max())
2205+
lookaheadHeuristicDepthLocal =
2206+
layers.size() < 10 || nrQubits <= 10 ? 0
2207+
: layers.size() < 20
2208+
? lookaheadDepthLocal - 1
2209+
: lookaheadDepthLocal - 2;
2210+
2211+
sim->SetUseOptimalMeetingPosition(true);
2212+
sim->SetLookaheadDepth(lookaheadDepthLocal);
2213+
sim->SetLookaheadDepthWithHeuristic(lookaheadHeuristicDepthLocal);
21892214
sim->SetUpcomingGates(dcirc->GetOperations());
21902215
}
21912216
}
@@ -2431,6 +2456,12 @@ class SimpleDisconnectedNetwork : public INetwork<Time> {
24312456
32; /**< The bond dimension threshold for using MPS optimization. */
24322457
size_t mpsOptimizationQubitsNumberThreshold =
24332458
12; /**< The qubits number threshold for using MPS optimization. */
2459+
2460+
int lookaheadDepth =
2461+
std::numeric_limits<int>::max(); /**< The lookahead depth for MPS swap
2462+
optimization. */
2463+
int lookaheadDepthWithHeuristic = std::numeric_limits<int>::max(); /**< The
2464+
lookahead depth with heuristic for MPS swap optimization. */
24342465
};
24352466

24362467
} // namespace Network

Simulators/GpuSimulator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ class GpuSimulator : public GpuState {
738738
cloned->singularValueThreshold = singularValueThreshold;
739739

740740
cloned->lookaheadDepth = lookaheadDepth;
741-
cloned->useOptimalMeetingPositionOnly = useOptimalMeetingPositionOnly;
741+
cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
742742
cloned->upcomingGates = upcomingGates;
743743
cloned->upcomingGateIndex = upcomingGateIndex;
744744

Simulators/GpuState.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class GpuState : public ISimulator {
7676
} else
7777
throw std::runtime_error(
7878
"GpuState::Initialize: Failed to create the MPS state.");
79+
// default is true
80+
if (!useOptimalMeetingPosition)
81+
mps->SetUseOptimalMeetingPosition(false);
7982
} else if (simulationType == SimulationType::kTensorNetwork) {
8083
tn = SimulatorsFactory::CreateGpuLibTensorNetSim();
8184
if (tn) {
@@ -265,13 +268,13 @@ class GpuState : public ISimulator {
265268
}
266269

267270
void SetUseOptimalMeetingPosition(bool enable) override {
268-
useOptimalMeetingPositionOnly = enable;
271+
useOptimalMeetingPosition = enable;
269272
if (mps) mps->SetUseOptimalMeetingPosition(enable);
270273
}
271274

272275
void SetLookaheadDepth(int depth) override {
273276
lookaheadDepth = depth;
274-
if (mps && depth > 0 && !useOptimalMeetingPositionOnly)
277+
if (mps && depth > 0 && !useOptimalMeetingPosition)
275278
mps->SetUseOptimalMeetingPosition(true);
276279
}
277280

@@ -1202,7 +1205,7 @@ class GpuState : public ISimulator {
12021205

12031206
int lookaheadDepth = 0;
12041207
int lookaheadDepthWithHeuristic = 0;
1205-
bool useOptimalMeetingPositionOnly = false;
1208+
bool useOptimalMeetingPosition = true;
12061209
std::vector<std::shared_ptr<Circuits::IOperation<>>> upcomingGates;
12071210
long long int upcomingGateIndex = 0;
12081211
std::unique_ptr<Simulators::MPSDummySimulator> dummySim;

Simulators/MPSDummySimulator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ class MPSDummySimulator {
405405

406406
std::vector<long long int> ComputeOptimalQubitsMap(
407407
const std::vector<std::shared_ptr<Circuits::Circuit<>>>& layers,
408-
int nrShuffles = 25) {
408+
int nrShuffles = 10) {
409409
const IndexType nrQubits = getNrQubits();
410410

411411
if (layers.empty() || nrQubits <= 2) return qubitsMap;

Simulators/QCSimSimulator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ class QCSimSimulator : public QCSimState {
924924
cloned->useMPSMeasureNoCollapse = useMPSMeasureNoCollapse;
925925

926926
cloned->lookaheadDepth = lookaheadDepth;
927-
cloned->useOptimalMeetingPositionOnly = useOptimalMeetingPositionOnly;
927+
cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
928928
cloned->upcomingGates = upcomingGates;
929929
cloned->upcomingGateIndex = upcomingGateIndex;
930930

Simulators/QCSimState.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class QCSimState : public ISimulator {
6868
if (limitEntanglement && singularValueThreshold > 0.)
6969
mpsSimulator->setLimitEntanglement(singularValueThreshold);
7070
if (limitSize && chi > 0) mpsSimulator->setLimitBondDimension(chi);
71+
// default is true
72+
if (!useOptimalMeetingPosition) mpsSimulator->SetUseOptimalMeetingPosition(false);
7173
} else if (simulationType == SimulationType::kStabilizer)
7274
cliffordSimulator =
7375
std::make_unique<QC::Clifford::StabilizerSimulator>(nrQubits);
@@ -250,14 +252,14 @@ class QCSimState : public ISimulator {
250252
}
251253

252254
void SetUseOptimalMeetingPosition(bool enable) override {
253-
useOptimalMeetingPositionOnly = enable;
255+
useOptimalMeetingPosition = enable;
254256
if (mpsSimulator)
255257
mpsSimulator->SetUseOptimalMeetingPosition(enable);
256258
}
257259

258260
void SetLookaheadDepth(int depth) override {
259261
lookaheadDepth = depth;
260-
if (mpsSimulator && depth > 0 && !useOptimalMeetingPositionOnly)
262+
if (mpsSimulator && depth > 0 && !useOptimalMeetingPosition)
261263
mpsSimulator->SetUseOptimalMeetingPosition(true);
262264
}
263265

@@ -1494,7 +1496,7 @@ class QCSimState : public ISimulator {
14941496

14951497
int lookaheadDepth = 0;
14961498
int lookaheadDepthWithHeuristic = 0;
1497-
bool useOptimalMeetingPositionOnly = false;
1499+
bool useOptimalMeetingPosition = true;
14981500
std::vector<std::shared_ptr<Circuits::IOperation<>>> upcomingGates;
14991501
long long int upcomingGateIndex = 0;
15001502
std::unique_ptr<Simulators::MPSDummySimulator> dummySim;

0 commit comments

Comments
 (0)