Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -489,6 +489,7 @@ cc_library(
name = "run_qsim",
hdrs = ["run_qsim.h"],
deps = [
":circuit",
":gate",
":gate_appl",
":util",
Expand Down Expand Up @@ -650,7 +651,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