Skip to content

Commit 2bd3c08

Browse files
author
Xin Xie
committed
Add cache-local qubit remapping prototype
1 parent c5bc023 commit 2bd3c08

5 files changed

Lines changed: 478 additions & 38 deletions

File tree

apps/qsim_base.cc

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
#include "../lib/fuser_mqubit.h"
2525
#include "../lib/io_file.h"
2626
#include "../lib/operation.h"
27+
#include "../lib/qubit_remap.h"
2728
#include "../lib/run_qsim.h"
2829
#include "../lib/simmux.h"
2930
#include "../lib/util_cpu.h"
3031

3132
constexpr char usage[] = "usage:\n ./qsim_base -c circuit -d maxtime "
3233
"-s seed -t threads -f max_fused_size "
33-
"-v verbosity -z\n";
34+
"-v verbosity -r -z\n";
3435

3536
struct Options {
3637
std::string circuit_file;
@@ -39,6 +40,7 @@ struct Options {
3940
unsigned num_threads = 1;
4041
unsigned max_fused_size = 2;
4142
unsigned verbosity = 0;
43+
bool cache_local_remap = false;
4244
bool denormals_are_zeros = false;
4345
};
4446

@@ -47,7 +49,7 @@ Options GetOptions(int argc, char* argv[]) {
4749

4850
int k;
4951

50-
while ((k = getopt(argc, argv, "c:d:s:t:f:v:z")) != -1) {
52+
while ((k = getopt(argc, argv, "c:d:s:t:f:v:rz")) != -1) {
5153
switch (k) {
5254
case 'c':
5355
opt.circuit_file = optarg;
@@ -67,6 +69,9 @@ Options GetOptions(int argc, char* argv[]) {
6769
case 'v':
6870
opt.verbosity = std::atoi(optarg);
6971
break;
72+
case 'r':
73+
opt.cache_local_remap = true;
74+
break;
7075
case 'z':
7176
opt.denormals_are_zeros = true;
7277
break;
@@ -91,7 +96,8 @@ bool ValidateOptions(const Options& opt) {
9196

9297
template <typename StateSpace, typename State>
9398
void PrintAmplitudes(
94-
unsigned num_qubits, const StateSpace& state_space, const State& state) {
99+
unsigned num_qubits, const StateSpace& state_space, const State& state,
100+
const qsim::qubit_remap::QubitMap& logical_to_physical = {}) {
95101
static constexpr char const* bits[8] = {
96102
"000", "001", "010", "011", "100", "101", "110", "111",
97103
};
@@ -100,7 +106,9 @@ void PrintAmplitudes(
100106
unsigned s = 3 - std::min(unsigned{3}, num_qubits);
101107

102108
for (uint64_t i = 0; i < size; ++i) {
103-
auto a = state_space.GetAmpl(state, i);
109+
uint64_t physical_i =
110+
qsim::qubit_remap::LogicalToPhysicalIndex(i, logical_to_physical);
111+
auto a = state_space.GetAmpl(state, physical_i);
104112
qsim::IO::messagef("%s:%16.8g%16.8g%16.8g\n",
105113
bits[i] + s, std::real(a), std::imag(a), std::norm(a));
106114
}
@@ -141,29 +149,37 @@ int main(int argc, char* argv[]) {
141149
unsigned num_threads;
142150
};
143151

144-
using Simulator = Factory::Simulator;
145-
using StateSpace = Simulator::StateSpace;
152+
using StateSpace = Factory::StateSpace;
146153
using State = StateSpace::State;
147154
using Fuser = MultiQubitGateFuser<IO>;
148155
using Runner = QSimRunner<IO, Fuser, Factory>;
149156

150-
StateSpace state_space = Factory(opt.num_threads).CreateStateSpace();
157+
Factory factory(opt.num_threads);
158+
StateSpace state_space = factory.CreateStateSpace();
151159
State state = state_space.Create(circuit.num_qubits);
152160

153161
if (state_space.IsNull(state)) {
154162
IO::errorf("not enough memory: is the number of qubits too large?\n");
155163
return 1;
156164
}
157165

166+
qubit_remap::QubitMap logical_to_physical;
167+
158168
state_space.SetStateZero(state);
159169

160170
Runner::Parameter param;
161171
param.max_fused_size = opt.max_fused_size;
162172
param.seed = opt.seed;
163173
param.verbosity = opt.verbosity;
174+
param.cache_local_remap = opt.cache_local_remap;
175+
176+
auto simulator = factory.CreateSimulator();
177+
bool ok = Runner::Run(param, circuit, state_space, simulator, state,
178+
logical_to_physical);
164179

165-
if (Runner::Run(param, Factory(opt.num_threads), circuit, state)) {
166-
PrintAmplitudes(circuit.num_qubits, state_space, state);
180+
if (ok) {
181+
PrintAmplitudes(circuit.num_qubits, state_space, state,
182+
logical_to_physical);
167183
}
168184

169185
return 0;

lib/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ cc_library(
5050
"operation_base.h",
5151
"parfor.h",
5252
"qtrajectory.h",
53+
"qubit_remap.h",
5354
"run_qsim.h",
5455
"run_qsimh.h",
5556
"seqfor.h",
@@ -127,6 +128,7 @@ cuda_library(
127128
"operation_base.h",
128129
"parfor.h",
129130
"qtrajectory.h",
131+
"qubit_remap.h",
130132
"run_qsim.h",
131133
"run_qsimh.h",
132134
"seqfor.h",
@@ -274,6 +276,7 @@ cc_library(
274276
"operation.h",
275277
"operation_base.h",
276278
"parfor.h",
279+
"qubit_remap.h",
277280
"run_qsim.h",
278281
"seqfor.h",
279282
"simmux.h",
@@ -515,6 +518,18 @@ cc_library(
515518
],
516519
)
517520

521+
cc_library(
522+
name = "qubit_remap",
523+
hdrs = ["qubit_remap.h"],
524+
deps = [
525+
":circuit",
526+
":fuser",
527+
":gate",
528+
":matrix",
529+
":operation",
530+
],
531+
)
532+
518533
cc_library(
519534
name = "fuser_basic",
520535
hdrs = ["fuser_basic.h"],
@@ -560,6 +575,7 @@ cc_library(
560575
":gate",
561576
":gate_appl",
562577
":operation_base",
578+
":qubit_remap",
563579
":util",
564580
],
565581
)

lib/fuser.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef FUSER_H_
1616
#define FUSER_H_
1717

18+
#include <algorithm>
1819
#include <cstdint>
1920
#include <vector>
2021

@@ -178,6 +179,58 @@ inline void CalculateFusedMatrix(FusedGate<FP>& gate) {
178179
}
179180
}
180181

182+
/**
183+
* Multiplies component gate matrices for a range of fused gates.
184+
* @param gbeg, gend The iterator range [gbeg, gend) of fused gates.
185+
*/
186+
template <typename Iterator>
187+
inline void CalculateFusedMatrices(Iterator gbeg, Iterator gend) {
188+
for (auto g = gbeg; g != gend; ++g) {
189+
if (!g->ParentIsDecomposed()) {
190+
CalculateFusedMatrix(*g);
191+
}
192+
}
193+
}
194+
195+
/**
196+
* Multiplies component gate matrices for a vector of fused gates.
197+
* @param gates The vector of fused gates.
198+
*/
199+
template <typename FusedGate>
200+
inline void CalculateFusedMatrices(std::vector<FusedGate>& gates) {
201+
CalculateFusedMatrices(gates.begin(), gates.end());
202+
}
203+
204+
/**
205+
* Rebuilds fused-gate qubit lists and matrices from component gates.
206+
* @param fused_gates The vector of fused gates to rebuild.
207+
*/
208+
template <typename FusedGate>
209+
inline void RebuildFusedGates(std::vector<FusedGate>& fused_gates) {
210+
for (auto& op : fused_gates) {
211+
auto* fused_gate = OpGetAlternative<std::variant_alternative_t<0, FusedGate>>(
212+
op);
213+
if (fused_gate == nullptr) {
214+
continue;
215+
}
216+
217+
auto& qubits = fused_gate->qubits;
218+
qubits.clear();
219+
220+
for (const auto& gate : fused_gate->gates) {
221+
const auto& gate_qubits = OpQubits(gate);
222+
qubits.insert(qubits.end(), gate_qubits.begin(), gate_qubits.end());
223+
}
224+
225+
std::sort(qubits.begin(), qubits.end());
226+
qubits.erase(std::unique(qubits.begin(), qubits.end()), qubits.end());
227+
228+
if (!fused_gate->ParentIsDecomposed()) {
229+
CalculateFusedMatrix(*fused_gate);
230+
}
231+
}
232+
}
233+
181234
} // namespace qsim
182235

183236
#endif // FUSER_H_

0 commit comments

Comments
 (0)