Skip to content

Commit 2630f82

Browse files
Merge branch 'master' into release-v0_15_0
2 parents 9024613 + d78a61f commit 2630f82

File tree

4 files changed

+98
-7
lines changed

4 files changed

+98
-7
lines changed

lib/vectorspace.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,20 @@ class VectorSpace {
160160
return true;
161161
}
162162

163+
// It is the client's responsibility to make sure that src has at least
164+
// min(size, Impl::MinSize(dest.num_qubits())) elements.
165+
bool Copy(const fp_type* src, uint64_t size, Vector& dest) const {
166+
auto f = [](unsigned n, unsigned m, uint64_t i,
167+
const fp_type* src, fp_type* dest) {
168+
dest[i] = src[i];
169+
};
170+
171+
size = std::min(size, Impl::MinSize(dest.num_qubits()));
172+
for_.Run(size, f, src, dest.get());
173+
174+
return true;
175+
}
176+
163177
void DeviceSync() {}
164178

165179
protected:

lib/vectorspace_cuda.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ class VectorSpaceCUDA {
141141
return true;
142142
}
143143

144+
// It is the client's responsibility to make sure that src has at least
145+
// min(size, Impl::MinSize(dest.num_qubits())) elements.
146+
bool Copy(const fp_type* src, uint64_t size, Vector& dest) const {
147+
size = std::min(size, Impl::MinSize(dest.num_qubits()));
148+
cudaMemcpy(dest.get(), src, sizeof(fp_type) * size, cudaMemcpyHostToDevice);
149+
return true;
150+
}
151+
144152
void DeviceSync() {
145153
cudaDeviceSynchronize();
146154
}

pybind_interface/pybind_main.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -694,15 +694,11 @@ class SimulatorHelper {
694694

695695
void init_state(const py::array_t<float> &input_vector) {
696696
StateSpace state_space = factory.CreateStateSpace();
697-
if (state.num_qubits() >= 5) {
698-
state_space.Copy(input_vector.data(), state);
699-
} else {
697+
uint64_t size = 2 * (uint64_t{1} << state.num_qubits());
698+
if (size < state_space.MinSize(state.num_qubits())) {
700699
state_space.SetAllZeros(state);
701-
uint64_t size = 2 * (uint64_t{1} << state.num_qubits());
702-
for (uint64_t i = 0; i < size; ++i) {
703-
state.get()[i] = input_vector.data()[i];
704-
}
705700
}
701+
state_space.Copy(input_vector.data(), size, state);
706702
state_space.NormalToInternalOrder(state);
707703
}
708704

qsimcirq_tests/qsimcirq_test.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,27 @@ def test_cirq_qsimh_simulate():
12621262
assert np.allclose(result, [0j, 0j, (1 + 0j), 0j])
12631263

12641264

1265+
def test_qsim_input_state():
1266+
for num_qubits in range(1, 8):
1267+
size = 2**num_qubits
1268+
qubits = cirq.LineQubit.range(num_qubits)
1269+
circuit = cirq.Circuit()
1270+
1271+
for k in range(num_qubits):
1272+
circuit.append(cirq.H(qubits[k]))
1273+
1274+
qsimSim = qsimcirq.QSimSimulator()
1275+
initial_state = np.asarray([np.sqrt(1.0 / size)] * size, dtype=np.complex64)
1276+
result = qsimSim.simulate(circuit, initial_state=initial_state)
1277+
state_vector = result.state_vector()
1278+
1279+
assert result.state_vector().shape == (size,)
1280+
assert cirq.approx_eq(state_vector[0], 1, atol=1e-6)
1281+
1282+
for i in range(1, size):
1283+
assert cirq.approx_eq(state_vector[i], 0, atol=1e-6)
1284+
1285+
12651286
def test_qsim_gpu_unavailable():
12661287
if qsimcirq.qsim_gpu is not None:
12671288
pytest.skip("GPU is available; skipping test.")
@@ -1358,6 +1379,32 @@ def test_cirq_qsim_gpu_input_state():
13581379
)
13591380

13601381

1382+
def test_qsim_gpu_input_state():
1383+
if qsimcirq.qsim_gpu is None:
1384+
pytest.skip("GPU is not available for testing.")
1385+
1386+
for num_qubits in range(1, 8):
1387+
size = 2**num_qubits
1388+
qubits = cirq.LineQubit.range(num_qubits)
1389+
circuit = cirq.Circuit()
1390+
1391+
for k in range(num_qubits):
1392+
circuit.append(cirq.H(qubits[k]))
1393+
1394+
# Enable GPU acceleration.
1395+
gpu_options = qsimcirq.QSimOptions(use_gpu=True)
1396+
qsimGpuSim = qsimcirq.QSimSimulator(qsim_options=gpu_options)
1397+
initial_state = np.asarray([np.sqrt(1.0 / size)] * size, dtype=np.complex64)
1398+
result = qsimGpuSim.simulate(circuit, initial_state=initial_state)
1399+
state_vector = result.state_vector()
1400+
1401+
assert result.state_vector().shape == (size,)
1402+
assert cirq.approx_eq(state_vector[0], 1, atol=1e-6)
1403+
1404+
for i in range(1, size):
1405+
assert cirq.approx_eq(state_vector[i], 0, atol=1e-6)
1406+
1407+
13611408
def test_cirq_qsim_custatevec_amplitudes():
13621409
if qsimcirq.qsim_custatevec is None:
13631410
pytest.skip("cuStateVec library is not available for testing.")
@@ -1441,6 +1488,32 @@ def test_cirq_qsim_custatevec_input_state():
14411488
)
14421489

14431490

1491+
def test_qsim_custatevec_input_state():
1492+
if qsimcirq.qsim_custatevec is None:
1493+
pytest.skip("cuStateVec library is not available for testing.")
1494+
1495+
for num_qubits in range(1, 8):
1496+
size = 2**num_qubits
1497+
qubits = cirq.LineQubit.range(num_qubits)
1498+
circuit = cirq.Circuit()
1499+
1500+
for k in range(num_qubits):
1501+
circuit.append(cirq.H(qubits[k]))
1502+
1503+
# Enable GPU acceleration.
1504+
custatevec_options = qsimcirq.QSimOptions(use_gpu=True, gpu_mode=1)
1505+
qsimGpuSim = qsimcirq.QSimSimulator(qsim_options=custatevec_options)
1506+
initial_state = np.asarray([np.sqrt(1.0 / size)] * size, dtype=np.complex64)
1507+
result = qsimGpuSim.simulate(circuit, initial_state=initial_state)
1508+
state_vector = result.state_vector()
1509+
1510+
assert result.state_vector().shape == (size,)
1511+
assert cirq.approx_eq(state_vector[0], 1, atol=1e-6)
1512+
1513+
for i in range(1, size):
1514+
assert cirq.approx_eq(state_vector[i], 0, atol=1e-6)
1515+
1516+
14441517
def test_cirq_qsim_old_options():
14451518
old_options = {"f": 3, "t": 4, "r": 100, "v": 1}
14461519
old_sim = qsimcirq.QSimSimulator(qsim_options=old_options)

0 commit comments

Comments
 (0)