Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.31)
cmake_minimum_required(VERSION 3.28)
Comment thread
mhucka marked this conversation as resolved.
project(qsim LANGUAGES CXX)

include(CheckLanguage)
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ run-tests tests: $(TESTS)

.PHONY: check-cuquantum-root-set
check-cuquantum-root-set:
@if [[ -z "$(CUQUANTUM_ROOT)" ]]; then \
echo Error: '$$CUQUANTUM_ROOT must be set in order to use cuStateVec.' \
exit 1 \
@if test -z "$(CUQUANTUM_ROOT)"; then \
Comment thread
mhucka marked this conversation as resolved.
echo Error: '$$CUQUANTUM_ROOT must be set in order to use cuStateVec.'; \
exit 1; \
fi

eigen:
Expand Down
16 changes: 9 additions & 7 deletions apps/qsim_qtrajectory_cuda.cu
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "../lib/gates_qsim.h"
#include "../lib/io_file.h"
#include "../lib/qtrajectory.h"
#include "../lib/run_qsim.h"
#include "../lib/simulator_cuda.h"

struct Options {
Expand Down Expand Up @@ -190,7 +191,7 @@ int main(int argc, char* argv[]) {
using fp_type = float;

struct Factory {
using Simulator = qsim::SimulatorCUDA<float>;
using Simulator = qsim::SimulatorCUDA<fp_type>;
using StateSpace = Simulator::StateSpace;

Factory(const StateSpace::Parameter& param) : param(param) {}
Expand All @@ -209,17 +210,18 @@ int main(int argc, char* argv[]) {
using Simulator = Factory::Simulator;
using StateSpace = Simulator::StateSpace;
using State = StateSpace::State;
using Fuser = MultiQubitGateFuser<IO, GateQSim<fp_type>>;
using QTSimulator = QuantumTrajectorySimulator<IO, GateQSim<fp_type>,
MultiQubitGateFuser,
Simulator>;
using Gate = GateQSim<fp_type>;
using Fuser = MultiQubitGateFuser<IO, Gate>;
using FuserQT = MultiQubitGateFuser<IO, const Gate*>;
using RunnerQT = QSimRunner<IO, FuserQT, Factory>;
using QTSimulator = QuantumTrajectorySimulator<IO, Gate, RunnerQT>;

auto opt = GetOptions(argc, argv);
if (!ValidateOptions(opt)) {
return 1;
}

Circuit<GateQSim<fp_type>> circuit;
Circuit<Gate> circuit;
unsigned maxtime = opt.times.back();
if (!CircuitQsimParser<IOFile>::FromFile(maxtime, opt.circuit_file,
circuit)) {
Expand Down Expand Up @@ -254,7 +256,7 @@ int main(int argc, char* argv[]) {

auto noisy_circuits = AddNoise(circuit, opt.times, channel1, channel2);

auto observables = GetObservables<GateQSim<fp_type>>(circuit.num_qubits);
auto observables = GetObservables<Gate>(circuit.num_qubits);

std::vector<std::vector<std::vector<std::complex<double>>>> results;
results.reserve(opt.num_trajectories);
Expand Down
2 changes: 1 addition & 1 deletion lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ cc_library(
name = "run_qsim",
hdrs = ["run_qsim.h"],
deps = [
":circuit",
":gate",
":gate_appl",
":util",
Expand Down Expand Up @@ -636,7 +637,6 @@ cuda_library(
name = "simulator_custatevec",
hdrs = [
"simulator_custatevec.h",
"simulator_custatevec_kernels.h",
],
deps = [
":bits",
Expand Down
43 changes: 43 additions & 0 deletions lib/circuit.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,49 @@ struct Circuit {
std::vector<Gate> gates;
};

namespace detail {

/**
* An adapter for vectors of gates.
*/
template <typename Circuit>
struct Gates;

template <typename Gate>
struct Gates<qsim::Circuit<Gate>> {
static const std::vector<Gate>& get(const qsim::Circuit<Gate>& circuit) {
return circuit.gates;
}

static const Gate& gate(const Gate& g) {
return g;
}
};

template <typename Gate>
struct Gates<std::vector<Gate>> {
static const std::vector<Gate>& get(const std::vector<Gate>& gates) {
return gates;
}

static const Gate& gate(const Gate& g) {
return g;
}
};

template <typename Gate>
struct Gates<std::vector<Gate*>> {
static const std::vector<Gate*>& get(const std::vector<Gate*>& gates) {
return gates;
}

static const Gate& gate(const Gate* g) {
return *g;
}
};

} // namespace detail

} // namespace qsim

#endif // CIRCUIT_H_
33 changes: 14 additions & 19 deletions lib/qtrajectory.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,18 @@ namespace qsim {
* Quantum trajectory simulator.
*/
template <typename IO, typename Gate,
template <typename, typename> class FuserT, typename Simulator,
typename RGen = std::mt19937>
typename Runner, typename RGen = std::mt19937>
class QuantumTrajectorySimulator {
public:
using Fuser = FuserT<IO, const Gate*>;
using Simulator = typename Runner::Simulator;
using StateSpace = typename Simulator::StateSpace;
using State = typename Simulator::State;
using State = typename StateSpace::State;
using MeasurementResult = typename StateSpace::MeasurementResult;

/**
* User-specified parameters for the simulator.
*/
struct Parameter : public Fuser::Parameter {
struct Parameter : public Runner::Parameter {
/**
* If true, collect statistics of sampled Kraus operator indices.
*/
Expand Down Expand Up @@ -265,7 +264,8 @@ class QuantumTrajectorySimulator {
if (channel[0].kind == gate::kMeasurement) {
// Measurement channel.

if (!ApplyDeferredOps(param, num_qubits, simulator, gates, state)) {
if (!ApplyDeferredOps(
param, num_qubits, state_space, simulator, gates, state)) {
return false;
}

Expand Down Expand Up @@ -309,7 +309,8 @@ class QuantumTrajectorySimulator {

if (r < cp) continue;

if (!ApplyDeferredOps(param, num_qubits, simulator, gates, state)) {
if (!ApplyDeferredOps(
param, num_qubits, state_space, simulator, gates, state)) {
return false;
}

Expand Down Expand Up @@ -351,7 +352,8 @@ class QuantumTrajectorySimulator {
}

if (apply_last_deferred_ops || !stat.primary) {
if (!ApplyDeferredOps(param, num_qubits, simulator, gates, state)) {
if (!ApplyDeferredOps(
param, num_qubits, state_space, simulator, gates, state)) {
return false;
}

Expand All @@ -372,20 +374,13 @@ class QuantumTrajectorySimulator {
}

static bool ApplyDeferredOps(
const Parameter& param, unsigned num_qubits, const Simulator& simulator,
const Parameter& param, unsigned num_qubits,
const StateSpace& state_space, const Simulator& simulator,
std::vector<const Gate*>& gates, State& state) {
if (gates.size() > 0) {
auto fgates = Fuser::FuseGates(param, num_qubits, gates);

bool rc = Runner::Run(param, gates, state_space, simulator, state);
gates.resize(0);

if (fgates.size() == 0) {
return false;
}

for (const auto& fgate : fgates) {
ApplyFusedGate(simulator, fgate, state);
}
return rc;
}

return true;
Expand Down
75 changes: 65 additions & 10 deletions lib/run_qsim.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <string>
#include <vector>

#include "circuit.h"
#include "gate.h"
#include "gate_appl.h"
#include "util.h"
Expand Down Expand Up @@ -174,6 +175,56 @@ struct QSimRunner final {
static bool Run(const Parameter& param, const Factory& factory,
const Circuit& circuit, State& state,
std::vector<MeasurementResult>& measure_results) {
StateSpace state_space = factory.CreateStateSpace();
Simulator simulator = factory.CreateSimulator();

return Run(param, circuit, state_space, simulator, state, measure_results);
}

/**
* Runs the given circuit and make the final state available to the caller,
* discarding the result of any intermediate measurements in the circuit.
* @param param Options for gate fusion, parallelism and logging.
* @param factory Object to create simulators and state spaces.
* @param circuit The circuit to be simulated.
* @param state As an input parameter, this should contain the initial state
* of the system. After a successful run, it will be populated with the
* final state of the system.
* @return True if the simulation completed successfully; false otherwise.
*/
template <typename Circuit>
static bool Run(const Parameter& param, const Factory& factory,
const Circuit& circuit, State& state) {
StateSpace state_space = factory.CreateStateSpace();
Simulator simulator = factory.CreateSimulator();

std::vector<MeasurementResult> discarded_results;

return Run(
param, circuit, state_space, simulator, state, discarded_results);
}

/**
* Runs the given circuit and make the final state available to the caller,
* recording the result of any intermediate measurements in the circuit.
* @param param Options for gate fusion, parallelism and logging.
* @param circuit The circuit to be simulated.
* @param state_space StateSpace object required to perform measurements.
* @param simulator Simulator object. Provides specific implementations for
* applying gates.
* @param state As an input parameter, this should contain the initial state
* of the system. After a successful run, it will be populated with the
* final state of the system.
* @param measure_results As an input parameter, this should be empty.
* After a successful run, this will contain all measurements results from
* the run, ordered by time and qubit index.
* @return True if the simulation completed successfully; false otherwise.
*/
template <typename Circuit>
static bool Run(const Parameter& param, const Circuit& circuit,
const StateSpace& state_space, const Simulator& simulator,
State& state,
std::vector<MeasurementResult>& measure_results) {
double t0 = 0.0;
double t1 = 0.0;

Expand All @@ -183,19 +234,18 @@ struct QSimRunner final {

RGen rgen(param.seed);

StateSpace state_space = factory.CreateStateSpace();
Simulator simulator = factory.CreateSimulator();

if (param.verbosity > 1) {
t1 = GetTime();
IO::messagef("init time is %g seconds.\n", t1 - t0);
t0 = GetTime();
}

auto fused_gates = Fuser::FuseGates(param, circuit.num_qubits,
circuit.gates);
using Gates = detail::Gates<Circuit>;
const auto& gates = Gates::get(circuit);

if (fused_gates.size() == 0 && circuit.gates.size() > 0) {
auto fused_gates = Fuser::FuseGates(param, state.num_qubits(), gates);

if (fused_gates.size() == 0 && gates.size() > 0) {
return false;
}

Expand Down Expand Up @@ -242,18 +292,23 @@ struct QSimRunner final {
* Runs the given circuit and make the final state available to the caller,
* discarding the result of any intermediate measurements in the circuit.
* @param param Options for gate fusion, parallelism and logging.
* @param factory Object to create simulators and state spaces.
* @param circuit The circuit to be simulated.
* @param state_space StateSpace object required to perform measurements.
* @param simulator Simulator object. Provides specific implementations for
* applying gates.
* @param state As an input parameter, this should contain the initial state
* of the system. After a successful run, it will be populated with the
* final state of the system.
* @return True if the simulation completed successfully; false otherwise.
*/
template <typename Circuit>
static bool Run(const Parameter& param, const Factory& factory,
const Circuit& circuit, State& state) {
static bool Run(const Parameter& param, const Circuit& circuit,
const StateSpace& state_space, const Simulator& simulator,
State& state) {
std::vector<MeasurementResult> discarded_results;
return Run(param, factory, circuit, state, discarded_results);

return Run(
param, circuit, state_space, simulator, state, discarded_results);
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/simulator_custatevec.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class SimulatorCuStateVec final {
uint64_t size = uint64_t{1} << state.num_qubits();

if (StateSpace::is_float) {
cuComplex a = {matrix[0], matrix[1]};
cuComplex a = {(float) matrix[0], (float) matrix[1]};
auto p = (cuComplex*) state.get();
ErrorCheck(cublasCscal(cublas_handle_, size, &a, p, 1));
} else {
Expand Down
4 changes: 2 additions & 2 deletions lib/vectorspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class VectorSpace {
return num_qubits_;
}

bool requires_copy_to_host() const {
static constexpr bool requires_copy_to_host() {
return false;
}

Expand Down Expand Up @@ -174,7 +174,7 @@ class VectorSpace {
return true;
}

void DeviceSync() {}
static void DeviceSync() {}

protected:
For for_;
Expand Down
4 changes: 2 additions & 2 deletions lib/vectorspace_cuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class VectorSpaceCUDA {
return num_qubits_;
}

bool requires_copy_to_host() const {
static constexpr bool requires_copy_to_host() {
return true;
}

Expand Down Expand Up @@ -160,7 +160,7 @@ class VectorSpaceCUDA {
return true;
}

void DeviceSync() {
static void DeviceSync() {
ErrorCheck(cudaDeviceSynchronize());
}

Expand Down
2 changes: 1 addition & 1 deletion pybind_interface/avx2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.31)
cmake_minimum_required(VERSION 3.28)
project(qsim)

IF (WIN32)
Expand Down
Loading
Loading