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
5 changes: 5 additions & 0 deletions docs/input_format.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Input circuit file format

**WARNING:** This format only supports the `gates_qsim` gate set, and is no
longer actively maintained. For other gates, circuits must be defined in code
or through the qsimcirq interface using
[Cirq](https://github.com/quantumlib/cirq).

The first line contains the number of qubits. The rest of the lines specify
gates with one gate per line. The format for a gate is

Expand Down
198 changes: 181 additions & 17 deletions pybind_interface/pybind_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <vector>

#include "../lib/bitstring.h"
#include "../lib/circuit_qsim_parser.h"
#include "../lib/formux.h"
#include "../lib/fuser_basic.h"
#include "../lib/gates_qsim.h"
Expand All @@ -48,20 +47,12 @@ T parseOptions(const py::dict &options, const char *key) {
return value.cast<T>();
}

Circuit<GateQSim<float>> getCircuit(const py::dict &options) {
Circuit<GateQSim<float>> circuit;
std::string circuit_str;
Circuit<Cirq::GateCirq<float>> getCircuit(const py::dict &options) {
try {
circuit_str = parseOptions<std::string>(options, "c\0");
return options["c\0"].cast<Circuit<Cirq::GateCirq<float>>>();
} catch (const std::invalid_argument &exp) {
throw;
}
std::stringstream ss(circuit_str);
if (!CircuitQsimParser<IO>::FromStream(std::numeric_limits<unsigned>::max(),
"cirq_circuit_str", ss, circuit)) {
throw std::invalid_argument("Unable to parse provided circuit.\n");
}
return circuit;
}

std::vector<Bitstring> getBitstrings(const py::dict &options, int num_qubits) {
Expand Down Expand Up @@ -117,8 +108,181 @@ auto reorder_fsv = [](unsigned n, unsigned m, uint64_t i, float *fsv) {

} // namespace

void add_gate(const qsim::Cirq::GateKind gate_kind, const unsigned time,
const std::vector<unsigned>& qubits,
const std::map<std::string, float>& params,
Circuit<Cirq::GateCirq<float>>* circuit) {
switch (gate_kind) {
case Cirq::kI:
circuit->gates.push_back(Cirq::I<float>::Create(time, qubits[0]));
break;
case Cirq::kI2:
circuit->gates.push_back(
Cirq::I2<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kXPowGate:
circuit->gates.push_back(
Cirq::XPowGate<float>::Create(time, qubits[0], params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kYPowGate:
circuit->gates.push_back(
Cirq::YPowGate<float>::Create(time, qubits[0], params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kZPowGate:
circuit->gates.push_back(
Cirq::ZPowGate<float>::Create(time, qubits[0], params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kHPowGate:
circuit->gates.push_back(
Cirq::HPowGate<float>::Create(time, qubits[0], params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kCZPowGate:
circuit->gates.push_back(
Cirq::CZPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kCXPowGate:
circuit->gates.push_back(
Cirq::CXPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::krx:
circuit->gates.push_back(
Cirq::rx<float>::Create(time, qubits[0], params.at("phi")));
break;
case Cirq::kry:
circuit->gates.push_back(
Cirq::ry<float>::Create(time, qubits[0], params.at("phi")));
break;
case Cirq::krz:
circuit->gates.push_back(
Cirq::rz<float>::Create(time, qubits[0], params.at("phi")));
break;
case Cirq::kH:
circuit->gates.push_back(Cirq::H<float>::Create(time, qubits[0]));
break;
case Cirq::kS:
circuit->gates.push_back(Cirq::S<float>::Create(time, qubits[0]));
break;
case Cirq::kCZ:
circuit->gates.push_back(
Cirq::CZ<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kCX:
circuit->gates.push_back(
Cirq::CX<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kT:
circuit->gates.push_back(Cirq::T<float>::Create(time, qubits[0]));
break;
case Cirq::kX:
circuit->gates.push_back(Cirq::X<float>::Create(time, qubits[0]));
break;
case Cirq::kY:
circuit->gates.push_back(Cirq::Y<float>::Create(time, qubits[0]));
break;
case Cirq::kZ:
circuit->gates.push_back(Cirq::Z<float>::Create(time, qubits[0]));
break;
case Cirq::kPhasedXPowGate:
circuit->gates.push_back(
Cirq::PhasedXPowGate<float>::Create(time, qubits[0],
params.at("phase_exponent"),
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kPhasedXZGate:
circuit->gates.push_back(
Cirq::PhasedXZGate<float>::Create(time, qubits[0],
params.at("x_exponent"),
params.at("z_exponent"),
params.at("axis_phase_exponent")));
break;
case Cirq::kXXPowGate:
circuit->gates.push_back(
Cirq::XXPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kYYPowGate:
circuit->gates.push_back(
Cirq::YYPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kZZPowGate:
circuit->gates.push_back(
Cirq::ZZPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kXX:
circuit->gates.push_back(
Cirq::XX<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kYY:
circuit->gates.push_back(
Cirq::YY<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kZZ:
circuit->gates.push_back(
Cirq::ZZ<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kSwapPowGate:
circuit->gates.push_back(
Cirq::SwapPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kISwapPowGate:
circuit->gates.push_back(
Cirq::ISwapPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("exponent"),
params.at("global_shift")));
break;
case Cirq::kriswap:
circuit->gates.push_back(
Cirq::riswap<float>::Create(time, qubits[0], qubits[1],
params.at("phi")));
break;
case Cirq::kSWAP:
circuit->gates.push_back(
Cirq::SWAP<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kISWAP:
circuit->gates.push_back(
Cirq::ISWAP<float>::Create(time, qubits[0], qubits[1]));
break;
case Cirq::kPhasedISwapPowGate:
circuit->gates.push_back(
Cirq::PhasedISwapPowGate<float>::Create(time, qubits[0], qubits[1],
params.at("phase_exponent"),
params.at("exponent")));
break;
case Cirq::kgivens:
circuit->gates.push_back(
Cirq::givens<float>::Create(time, qubits[0], qubits[1],
params.at("phi")));
break;
case Cirq::kFSimGate:
circuit->gates.push_back(
Cirq::FSimGate<float>::Create(time, qubits[0], qubits[1],
params.at("theta"), params.at("phi")));
break;
// TODO: support translating matrix gates.
default:
throw std::invalid_argument("GateKind not supported.");
}
}

std::vector<std::complex<float>> qsim_simulate(const py::dict &options) {
Circuit<GateQSim<float>> circuit;
Circuit<Cirq::GateCirq<float>> circuit;
std::vector<Bitstring> bitstrings;
try {
circuit = getCircuit(options);
Expand All @@ -144,7 +308,7 @@ std::vector<std::complex<float>> qsim_simulate(const py::dict &options) {
}
};

using Runner = QSimRunner<IO, BasicGateFuser<GateQSim<float>>, Simulator>;
using Runner = QSimRunner<IO, BasicGateFuser<Cirq::GateCirq<float>>, Simulator>;

Runner::Parameter param;
try {
Expand All @@ -159,7 +323,7 @@ std::vector<std::complex<float>> qsim_simulate(const py::dict &options) {
}

py::array_t<float> qsim_simulate_fullstate(const py::dict &options) {
Circuit<GateQSim<float>> circuit;
Circuit<Cirq::GateCirq<float>> circuit;
try {
circuit = getCircuit(options);
} catch (const std::invalid_argument &exp) {
Expand All @@ -178,7 +342,7 @@ py::array_t<float> qsim_simulate_fullstate(const py::dict &options) {
using Simulator = qsim::Simulator<For>;
using StateSpace = Simulator::StateSpace;
using State = StateSpace::State;
using Runner = QSimRunner<IO, BasicGateFuser<GateQSim<float>>, Simulator>;
using Runner = QSimRunner<IO, BasicGateFuser<Cirq::GateCirq<float>>, Simulator>;

Runner::Parameter param;
try {
Expand Down Expand Up @@ -223,11 +387,11 @@ py::array_t<float> qsim_simulate_fullstate(const py::dict &options) {

std::vector<std::complex<float>> qsimh_simulate(const py::dict &options) {
using Simulator = qsim::Simulator<For>;
using HybridSimulator = HybridSimulator<IO, GateQSim<float>, BasicGateFuser,
using HybridSimulator = HybridSimulator<IO, Cirq::GateCirq<float>, BasicGateFuser,
Simulator, For>;
using Runner = QSimHRunner<IO, HybridSimulator>;

Circuit<GateQSim<float>> circuit;
Circuit<Cirq::GateCirq<float>> circuit;
std::vector<Bitstring> bitstrings;
Runner::Parameter param;
py::list dense_parts;
Expand Down
60 changes: 60 additions & 0 deletions pybind_interface/pybind_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ namespace py = pybind11;

#include <vector>

#include "../lib/circuit.h"
#include "../lib/gates_cirq.h"

void add_gate(const qsim::Cirq::GateKind gate_kind, const unsigned time,
const std::vector<unsigned>& qubits,
const std::map<std::string, float>& params,
qsim::Circuit<qsim::Cirq::GateCirq<float>>* circuit);

std::vector<std::complex<float>> qsim_simulate(const py::dict &options);

py::array_t<float> qsim_simulate_fullstate(const py::dict &options);
Expand All @@ -36,6 +44,58 @@ PYBIND11_MODULE(qsim, m) {
m.def("qsim_simulate_fullstate", &qsim_simulate_fullstate,
"Call the qsim simulator for full state vector simulation");
m.def("qsimh_simulate", &qsimh_simulate, "Call the qsimh simulator");

using GateCirq = qsim::Cirq::GateCirq<float>;
using GateKind = qsim::Cirq::GateKind;
using Circuit = qsim::Circuit<GateCirq>;

py::class_<Circuit>(m, "Circuit")
.def(py::init<>())
.def_readwrite("num_qubits", &Circuit::num_qubits)
.def_readwrite("gates", &Circuit::gates);

py::enum_<GateKind>(m, "GateKind")
.value("kI", GateKind::kI)
.value("kI2", GateKind::kI2)
.value("kXPowGate", GateKind::kXPowGate)
.value("kYPowGate", GateKind::kYPowGate)
.value("kZPowGate", GateKind::kZPowGate)
.value("kHPowGate", GateKind::kHPowGate)
.value("kCZPowGate", GateKind::kCZPowGate)
.value("kCXPowGate", GateKind::kCXPowGate)
.value("krx", GateKind::krx)
.value("kry", GateKind::kry)
.value("krz", GateKind::krz)
.value("kH", GateKind::kH)
.value("kS", GateKind::kS)
.value("kCZ", GateKind::kCZ)
.value("kCX", GateKind::kCX)
.value("kT", GateKind::kT)
.value("kX", GateKind::kX)
.value("kY", GateKind::kY)
.value("kZ", GateKind::kZ)
.value("kPhasedXPowGate", GateKind::kPhasedXPowGate)
.value("kPhasedXZGate", GateKind::kPhasedXZGate)
.value("kXXPowGate", GateKind::kXXPowGate)
.value("kYYPowGate", GateKind::kYYPowGate)
.value("kZZPowGate", GateKind::kZZPowGate)
.value("kXX", GateKind::kXX)
.value("kYY", GateKind::kYY)
.value("kZZ", GateKind::kZZ)
.value("kSwapPowGate", GateKind::kSwapPowGate)
.value("kISwapPowGate", GateKind::kISwapPowGate)
.value("kriswap", GateKind::kriswap)
.value("kSWAP", GateKind::kSWAP)
.value("kISWAP", GateKind::kISWAP)
.value("kPhasedISwapPowGate", GateKind::kPhasedISwapPowGate)
.value("kgivens", GateKind::kgivens)
.value("kFSimGate", GateKind::kFSimGate)
.value("kMatrixGate1", GateKind::kMatrixGate1)
.value("kMatrixGate2", GateKind::kMatrixGate2)
.value("kGateDecomp", GateKind::kGateDecomp)
.export_values();

m.def("add_gate", &add_gate, "Adds a gate to the given circuit.");
}

#endif
Loading