Skip to content

Commit 67cf305

Browse files
Merge pull request #246 from quantumlib/more-cirq-qubits
Pass through max fused qubits from Python
2 parents f8e791a + 8d72462 commit 67cf305

File tree

5 files changed

+58
-7
lines changed

5 files changed

+58
-7
lines changed

docs/tutorials/qsimcirq.ipynb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,33 @@
375375
"print(f'qsim runtime: {qsim_elapsed} seconds.')"
376376
]
377377
},
378+
{
379+
"cell_type": "markdown",
380+
"metadata": {
381+
"id": "HVkTbqfH4zls"
382+
},
383+
"source": [
384+
"Another option is to adjust the maximum number of qubits over which to fuse gates. Increasing this value (as demonstrated below) increases arithmetic intensity, which may improve performance with the right environment settings."
385+
]
386+
},
387+
{
388+
"cell_type": "code",
389+
"metadata": {
390+
"id": "kkQ5ARpI5phJ"
391+
},
392+
"source": [
393+
"# Increase maximum fused gate size to three qubits.\n",
394+
"options = {'f': 3}\n",
395+
"\n",
396+
"qsim_simulator = qsimcirq.QSimSimulator(options)\n",
397+
"qsim_start = time.time()\n",
398+
"qsim_results = qsim_simulator.simulate(circuit)\n",
399+
"qsim_elapsed = time.time() - qsim_start\n",
400+
"print(f'qsim runtime: {qsim_elapsed} seconds.')"
401+
],
402+
"execution_count": null,
403+
"outputs": []
404+
},
378405
{
379406
"cell_type": "markdown",
380407
"metadata": {

pybind_interface/pybind_main.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
#include "../lib/bitstring.h"
2525
#include "../lib/formux.h"
26-
#include "../lib/fuser_basic.h"
26+
#include "../lib/fuser_mqubit.h"
2727
#include "../lib/gates_qsim.h"
2828
#include "../lib/io.h"
2929
#include "../lib/run_qsim.h"
@@ -358,12 +358,13 @@ std::vector<std::complex<float>> qsim_simulate(const py::dict &options) {
358358
}
359359
};
360360

361-
using Runner = QSimRunner<IO, BasicGateFuser<IO, Cirq::GateCirq<float>>,
361+
using Runner = QSimRunner<IO, MultiQubitGateFuser<IO, Cirq::GateCirq<float>>,
362362
Simulator>;
363363

364364
Runner::Parameter param;
365365
try {
366366
param.num_threads = parseOptions<unsigned>(options, "t\0");
367+
param.max_fused_size = parseOptions<unsigned>(options, "f\0");
367368
param.verbosity = parseOptions<unsigned>(options, "v\0");
368369
param.seed = parseOptions<unsigned>(options, "s\0");
369370
} catch (const std::invalid_argument &exp) {
@@ -386,12 +387,13 @@ py::array_t<float> qsim_simulate_fullstate(const py::dict &options) {
386387
using Simulator = qsim::Simulator<For>;
387388
using StateSpace = Simulator::StateSpace;
388389
using State = StateSpace::State;
389-
using Runner = QSimRunner<IO, BasicGateFuser<IO, Cirq::GateCirq<float>>,
390+
using Runner = QSimRunner<IO, MultiQubitGateFuser<IO, Cirq::GateCirq<float>>,
390391
Simulator>;
391392

392393
Runner::Parameter param;
393394
try {
394395
param.num_threads = parseOptions<unsigned>(options, "t\0");
396+
param.max_fused_size = parseOptions<unsigned>(options, "f\0");
395397
param.verbosity = parseOptions<unsigned>(options, "v\0");
396398
param.seed = parseOptions<unsigned>(options, "s\0");
397399
} catch (const std::invalid_argument &exp) {
@@ -437,12 +439,13 @@ std::vector<unsigned> qsim_sample(const py::dict &options) {
437439
using StateSpace = Simulator::StateSpace;
438440
using State = StateSpace::State;
439441
using MeasurementResult = StateSpace::MeasurementResult;
440-
using Runner = QSimRunner<IO, BasicGateFuser<IO, Cirq::GateCirq<float>>,
442+
using Runner = QSimRunner<IO, MultiQubitGateFuser<IO, Cirq::GateCirq<float>>,
441443
Simulator>;
442444

443445
Runner::Parameter param;
444446
try {
445447
param.num_threads = parseOptions<unsigned>(options, "t\0");
448+
param.max_fused_size = parseOptions<unsigned>(options, "f\0");
446449
param.verbosity = parseOptions<unsigned>(options, "v\0");
447450
param.seed = parseOptions<unsigned>(options, "s\0");
448451
} catch (const std::invalid_argument &exp) {
@@ -479,7 +482,7 @@ std::vector<unsigned> qsim_sample(const py::dict &options) {
479482
std::vector<std::complex<float>> qsimh_simulate(const py::dict &options) {
480483
using Simulator = qsim::Simulator<For>;
481484
using HybridSimulator = HybridSimulator<IO, Cirq::GateCirq<float>,
482-
BasicGateFuser, Simulator, For>;
485+
MultiQubitGateFuser, Simulator, For>;
483486
using Runner = QSimHRunner<IO, HybridSimulator>;
484487

485488
Circuit<Cirq::GateCirq<float>> circuit;
@@ -495,6 +498,7 @@ std::vector<std::complex<float>> qsimh_simulate(const py::dict &options) {
495498
param.num_prefix_gatexs = parseOptions<unsigned>(options, "p\0");
496499
param.num_root_gatexs = parseOptions<unsigned>(options, "r\0");
497500
param.num_threads = parseOptions<unsigned>(options, "t\0");
501+
param.max_fused_size = parseOptions<unsigned>(options, "f\0");
498502
param.verbosity = parseOptions<unsigned>(options, "v\0");
499503
} catch (const std::invalid_argument &exp) {
500504
IO::errorf(exp.what());

qsimcirq/qsim_simulator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def __init__(self, qsim_options: dict = {},
6262
'Keys "c" & "i" are reserved for internal use and cannot be used in QSimCircuit instantiation.'
6363
)
6464
self._prng = value.parse_random_state(seed)
65-
self.qsim_options = {'t': 1, 'v': 0}
65+
self.qsim_options = {'t': 1, 'f': 2, 'v': 0}
6666
self.qsim_options.update(qsim_options)
6767

6868
def get_seed(self):

qsimcirq/qsimh_simulator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
class QSimhSimulator(SimulatesAmplitudes):
2424

2525
def __init__(self, qsimh_options: dict = {}):
26-
self.qsimh_options = {'t': 1, 'v': 0}
26+
self.qsimh_options = {'t': 1, 'f': 2, 'v': 0}
2727
self.qsimh_options.update(qsimh_options)
2828

2929
def compute_amplitudes_sweep(

qsimcirq_tests/qsimcirq_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,26 @@ def test_complicated_decomposition(self):
405405
result.state_vector(), cirq_result.state_vector())
406406

407407

408+
def test_multi_qubit_fusion(self):
409+
q0, q1, q2, q3 = cirq.LineQubit.range(4)
410+
qubits = [q0, q1, q2, q3]
411+
cirq_circuit = cirq.Circuit(
412+
cirq.CX(q0, q1), cirq.X(q2)**0.5, cirq.Y(q3)**0.5,
413+
cirq.CX(q0, q2), cirq.T(q1), cirq.T(q3),
414+
cirq.CX(q1, q2), cirq.X(q3)**0.5, cirq.Y(q0)**0.5,
415+
cirq.CX(q1, q3), cirq.T(q0), cirq.T(q2),
416+
cirq.CX(q2, q3), cirq.X(q0)**0.5, cirq.Y(q1)**0.5,
417+
)
418+
419+
qsimSim = qsimcirq.QSimSimulator(qsim_options={'f': 2})
420+
result_2q_fusion = qsimSim.simulate(cirq_circuit, qubit_order=qubits)
421+
422+
qsimSim = qsimcirq.QSimSimulator(qsim_options={'f': 4})
423+
result_4q_fusion = qsimSim.simulate(cirq_circuit, qubit_order=qubits)
424+
assert cirq.linalg.allclose_up_to_global_phase(
425+
result_2q_fusion.state_vector(), result_4q_fusion.state_vector())
426+
427+
408428
def test_cirq_qsim_simulate_random_unitary(self):
409429

410430
q0, q1 = cirq.LineQubit.range(2)

0 commit comments

Comments
 (0)