Skip to content

Commit

Permalink
python precision
Browse files Browse the repository at this point in the history
  • Loading branch information
KowerKoint committed Nov 22, 2024
1 parent 239438d commit 9aad61b
Show file tree
Hide file tree
Showing 24 changed files with 583 additions and 293 deletions.
43 changes: 22 additions & 21 deletions include/scaluq/circuit/circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,55 +76,56 @@ class Circuit {

#ifdef SCALUQ_USE_NANOBIND
namespace internal {
template <std::floating_point Fp>
void bind_circuit_circuit_hpp(nb::module_& m) {
nb::class_<Circuit<double>>(m, "Circuit", "Quantum circuit represented as gate array")
nb::class_<Circuit<Fp>>(m, "Circuit", "Quantum circuit represented as gate array")
.def(nb::init<std::uint64_t>(), "Initialize empty circuit of specified qubits.")
.def("n_qubits", &Circuit<double>::n_qubits, "Get property of `n_qubits`.")
.def("n_qubits", &Circuit<Fp>::n_qubits, "Get property of `n_qubits`.")
.def("gate_list",
&Circuit<double>::gate_list,
&Circuit<Fp>::gate_list,
"Get property of `gate_list`.",
nb::rv_policy::reference)
.def("n_gates", &Circuit<double>::n_gates, "Get property of `n_gates`.")
.def("key_set", &Circuit<double>::key_set, "Get set of keys of parameters.")
.def("get_gate_at", &Circuit<double>::get_gate_at, "Get reference of i-th gate.")
.def("n_gates", &Circuit<Fp>::n_gates, "Get property of `n_gates`.")
.def("key_set", &Circuit<Fp>::key_set, "Get set of keys of parameters.")
.def("get_gate_at", &Circuit<Fp>::get_gate_at, "Get reference of i-th gate.")
.def("get_param_key_at",
&Circuit<double>::get_param_key_at,
&Circuit<Fp>::get_param_key_at,
"Get parameter key of i-th gate. If it is not parametric, return None.")
.def("calculate_depth", &Circuit<double>::calculate_depth, "Get depth of circuit.")
.def("calculate_depth", &Circuit<Fp>::calculate_depth, "Get depth of circuit.")
.def("add_gate",
nb::overload_cast<const Gate<double>&>(&Circuit<double>::add_gate),
nb::overload_cast<const Gate<Fp>&>(&Circuit<Fp>::add_gate),
"Add gate. Given gate is copied.")
.def("add_param_gate",
nb::overload_cast<const ParamGate<double>&, std::string_view>(
&Circuit<double>::add_param_gate),
"Add parametric gate with specifing key. Given param_gate is copied.")
.def(
"add_param_gate",
nb::overload_cast<const ParamGate<Fp>&, std::string_view>(&Circuit<Fp>::add_param_gate),
"Add parametric gate with specifing key. Given param_gate is copied.")
.def("add_circuit",
nb::overload_cast<const Circuit<double>&>(&Circuit<double>::add_circuit),
nb::overload_cast<const Circuit<Fp>&>(&Circuit<Fp>::add_circuit),
"Add all gates in specified circuit. Given gates are copied.")
.def("update_quantum_state",
&Circuit<double>::update_quantum_state,
&Circuit<Fp>::update_quantum_state,
"Apply gate to the StateVector. StateVector in args is directly updated. If the "
"circuit contains parametric gate, you have to give real value of parameter as "
"dict[str, float] in 2nd arg.")
.def(
"update_quantum_state",
[&](const Circuit<double>& circuit, StateVector<double>& state, nb::kwargs kwargs) {
std::map<std::string, double> parameters;
[&](const Circuit<Fp>& circuit, StateVector<Fp>& state, nb::kwargs kwargs) {
std::map<std::string, Fp> parameters;
for (auto&& [key, param] : kwargs) {
parameters[nb::cast<std::string>(key)] = nb::cast<double>(param);
parameters[nb::cast<std::string>(key)] = nb::cast<Fp>(param);
}
circuit.update_quantum_state(state, parameters);
},
"Apply gate to the StateVector. StateVector in args is directly updated. If the "
"circuit contains parametric gate, you have to give real value of parameter as "
"\"name=value\" format in kwargs.")
.def("update_quantum_state",
[](const Circuit<double>& circuit, StateVector<double>& state) {
[](const Circuit<Fp>& circuit, StateVector<Fp>& state) {
circuit.update_quantum_state(state);
})
.def("copy", &Circuit<double>::copy, "Copy circuit. All the gates inside is copied.")
.def("copy", &Circuit<Fp>::copy, "Copy circuit. All the gates inside is copied.")
.def("get_inverse",
&Circuit<double>::get_inverse,
&Circuit<Fp>::get_inverse,
"Get inverse of circuit. All the gates are newly created.");
}
} // namespace internal
Expand Down
37 changes: 14 additions & 23 deletions include/scaluq/gate/gate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,21 +342,20 @@ namespace internal {
[](const GATE_TYPE<FLOAT>& gate) { return gate->to_string(""); }, \
"Get string representation of the gate.")

nb::class_<Gate<double>> gate_base_def_double;
nb::class_<Gate<float>> gate_base_def_float;
template <std::floating_point Fp>
nb::class_<Gate<Fp>> gate_base_def;

#define DEF_GATE(GATE_TYPE, FLOAT, DESCRIPTION) \
::scaluq::internal::gate_base_def_##FLOAT.def(nb::init<GATE_TYPE<FLOAT>>(), \
"Upcast from `" #GATE_TYPE "`."); \
::scaluq::internal::gate_base_def<FLOAT>.def(nb::init<GATE_TYPE<FLOAT>>(), \
"Upcast from `" #GATE_TYPE "`."); \
DEF_GATE_BASE( \
GATE_TYPE, \
FLOAT, \
DESCRIPTION \
"\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \
.def(nb::init<Gate<FLOAT>>())

template <std::floating_point Fp>
void bind_gate_gate_hpp(nb::module_& m) {
void bind_gate_gate_hpp_without_precision(nb::module_& m) {
nb::enum_<GateType>(m, "GateType", "Enum of Gate Type.")
.value("I", GateType::I)
.value("GlobalPhase", GateType::GlobalPhase)
Expand Down Expand Up @@ -385,24 +384,16 @@ void bind_gate_gate_hpp(nb::module_& m) {
.value("TwoTargetMatrix", GateType::TwoTargetMatrix)
.value("Pauli", GateType::Pauli)
.value("PauliRotation", GateType::PauliRotation);
}

if constexpr (std::is_same_v<Fp, double>) {
gate_base_def_double =
DEF_GATE_BASE(Gate,
double,
"General class of QuantumGate.\n\n.. note:: Downcast to requred to use "
"gate-specific functions.")
.def(nb::init<Gate<double>>(), "Just copy shallowly.");
} else if constexpr (std::is_same_v<Fp, float>) {
gate_base_def_float =
DEF_GATE_BASE(Gate,
float,
"General class of QuantumGate.\n\n.. note:: Downcast to requred to use "
"gate-specific functions.")
.def(nb::init<Gate<float>>(), "Just copy shallowly.");
} else {
static_assert(internal::lazy_false_v<void>);
}
template <std::floating_point Fp>
void bind_gate_gate_hpp(nb::module_& m) {
gate_base_def<Fp> =
DEF_GATE_BASE(Gate,
Fp,
"General class of QuantumGate.\n\n.. note:: Downcast to requred to use "
"gate-specific functions.")
.def(nb::init<Gate<Fp>>(), "Just copy shallowly.");
}
} // namespace internal
#endif
Expand Down
73 changes: 37 additions & 36 deletions include/scaluq/gate/gate_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,190 +251,191 @@ inline Gate<Fp> Probablistic(const std::vector<Fp>& distribution,

#ifdef SCALUQ_USE_NANOBIND
namespace internal {
template <std::floating_point Fp>
void bind_gate_gate_factory_hpp(nb::module_& mgate) {
mgate.def("I", &gate::I<double>, "Generate general Gate class instance of I.");
mgate.def("I", &gate::I<Fp>, "Generate general Gate class instance of I.");
mgate.def("GlobalPhase",
&gate::GlobalPhase<double>,
&gate::GlobalPhase<Fp>,
"Generate general Gate class instance of GlobalPhase.",
"phase"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("X",
&gate::X<double>,
&gate::X<Fp>,
"Generate general Gate class instance of X.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Y",
&gate::Y<double>,
&gate::Y<Fp>,
"Generate general Gate class instance of Y.",
"taget"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Z",
&gate::Z<double>,
&gate::Z<Fp>,
"Generate general Gate class instance of Z.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("H",
&gate::H<double>,
&gate::H<Fp>,
"Generate general Gate class instance of H.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("S",
&gate::S<double>,
&gate::S<Fp>,
"Generate general Gate class instance of S.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Sdag",
&gate::Sdag<double>,
&gate::Sdag<Fp>,
"Generate general Gate class instance of Sdag.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("T",
&gate::T<double>,
&gate::T<Fp>,
"Generate general Gate class instance of T.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Tdag",
&gate::Tdag<double>,
&gate::Tdag<Fp>,
"Generate general Gate class instance of Tdag.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("SqrtX",
&gate::SqrtX<double>,
&gate::SqrtX<Fp>,
"Generate general Gate class instance of SqrtX.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("SqrtXdag",
&gate::SqrtXdag<double>,
&gate::SqrtXdag<Fp>,
"Generate general Gate class instance of SqrtXdag.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("SqrtY",
&gate::SqrtY<double>,
&gate::SqrtY<Fp>,
"Generate general Gate class instance of SqrtY.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("SqrtYdag",
&gate::SqrtYdag<double>,
&gate::SqrtYdag<Fp>,
"Generate general Gate class instance of SqrtYdag.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("P0",
&gate::P0<double>,
&gate::P0<Fp>,
"Generate general Gate class instance of P0.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("P1",
&gate::P1<double>,
&gate::P1<Fp>,
"Generate general Gate class instance of P1.",
"target"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("RX",
&gate::RX<double>,
&gate::RX<Fp>,
"Generate general Gate class instance of RX.",
"target"_a,
"angle"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("RY",
&gate::RY<double>,
&gate::RY<Fp>,
"Generate general Gate class instance of RY.",
"target"_a,
"angle"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("RZ",
&gate::RZ<double>,
&gate::RZ<Fp>,
"Generate general Gate class instance of RZ.",
"target"_a,
"angle"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("U1",
&gate::U1<double>,
&gate::U1<Fp>,
"Generate general Gate class instance of U1.",
"target"_a,
"lambda_"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("U2",
&gate::U2<double>,
&gate::U2<Fp>,
"Generate general Gate class instance of U2.",
"target"_a,
"phi"_a,
"lambda_"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("U3",
&gate::U3<double>,
&gate::U3<Fp>,
"Generate general Gate class instance of U3.",
"target"_a,
"theta"_a,
"phi"_a,
"lambda_"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Swap",
&gate::Swap<double>,
&gate::Swap<Fp>,
"Generate general Gate class instance of Swap.",
"target1"_a,
"target2"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def(
"CX",
&gate::CX<double>,
&gate::CX<Fp>,
"Generate general Gate class instance of CX.\n\n.. note:: CX is a specialization of X.");
mgate.def("CNot",
&gate::CX<double>,
&gate::CX<Fp>,
"Generate general Gate class instance of CNot.\n\n.. note:: CNot is an alias of CX.");
mgate.def(
"CZ",
&gate::CZ<double>,
&gate::CZ<Fp>,
"Generate general Gate class instance of CZ.\n\n.. note:: CZ is a specialization of Z.");
mgate.def(
"CCX",
&gate::CCX<double>,
&gate::CCX<Fp>,
"Generate general Gate class instance of CXX.\n\n.. note:: CX is a specialization of X.");
mgate.def(
"CCNot",
&gate::CCX<double>,
&gate::CCX<Fp>,
"Generate general Gate class instance of CCNot.\n\n.. note:: CCNot is an alias of CCX.");
mgate.def("Toffoli",
&gate::CCX<double>,
&gate::CCX<Fp>,
"Generate general Gate class instance of Toffoli.\n\n.. note:: Toffoli is an alias "
"of CCX.");
mgate.def("OneTargetMatrix",
&gate::OneTargetMatrix<double>,
&gate::OneTargetMatrix<Fp>,
"Generate general Gate class instance of OneTargetMatrix.",
"target"_a,
"matrix"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("TwoTargetMatrix",
&gate::TwoTargetMatrix<double>,
&gate::TwoTargetMatrix<Fp>,
"Generate general Gate class instance of TwoTargetMatrix.",
"target1"_a,
"target2"_a,
"matrix"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("DenseMatrix",
&gate::DenseMatrix<double>,
&gate::DenseMatrix<Fp>,
"Generate general Gate class instance of DenseMatrix.",
"targets"_a,
"matrix"_a,
"controls"_a = std::vector<std::uint64_t>{},
"is_unitary"_a = false);
mgate.def("SparseMatrix",
&gate::SparseMatrix<double>,
&gate::SparseMatrix<Fp>,
"Generate general Gate class instance of SparseMatrix.",
"targets"_a,
"matrix"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Pauli",
&gate::Pauli<double>,
&gate::Pauli<Fp>,
"Generate general Gate class instance of Pauli.",
"pauli"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("PauliRotation",
&gate::PauliRotation<double>,
&gate::PauliRotation<Fp>,
"Generate general Gate class instance of PauliRotation.",
"pauli"_a,
"angle"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("Probablistic",
&gate::Probablistic<double>,
&gate::Probablistic<Fp>,
"Generate general Gate class instance of Probablistic.",
"distribution"_a,
"gate_list"_a);
Expand Down
13 changes: 7 additions & 6 deletions include/scaluq/gate/gate_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,18 @@ using DenseMatrixGate = internal::GatePtr<internal::DenseMatrixGateImpl<Fp>>;

#ifdef SCALUQ_USE_NANOBIND
namespace internal {
template <std::floating_point Fp>
void bind_gate_gate_matrix_hpp(nb::module_& m) {
DEF_GATE(OneTargetMatrixGate, double, "Specific class of one-qubit dense matrix gate.")
DEF_GATE(OneTargetMatrixGate, Fp, "Specific class of one-qubit dense matrix gate.")
.def("matrix", [](const OneTargetMatrixGate<double>& gate) { return gate->matrix(); });
DEF_GATE(TwoTargetMatrixGate, double, "Specific class of two-qubit dense matrix gate.")
DEF_GATE(TwoTargetMatrixGate, Fp, "Specific class of two-qubit dense matrix gate.")
.def("matrix", [](const TwoTargetMatrixGate<double>& gate) { return gate->matrix(); });
DEF_GATE(SparseMatrixGate, double, "Specific class of sparse matrix gate.")
DEF_GATE(SparseMatrixGate, Fp, "Specific class of sparse matrix gate.")
.def("matrix", [](const SparseMatrixGate<double>& gate) { return gate->get_matrix(); })
.def("sparse_matrix",
[](const SparseMatrixGate<double>& gate) { return gate->get_sparse_matrix(); });
DEF_GATE(DenseMatrixGate, double, "Specific class of dense matrix gate.")
.def("matrix", [](const DenseMatrixGate<double>& gate) { return gate->get_matrix(); });
[](const SparseMatrixGate<Fp>& gate) { return gate->get_sparse_matrix(); });
DEF_GATE(DenseMatrixGate, Fp, "Specific class of dense matrix gate.")
.def("matrix", [](const DenseMatrixGate<Fp>& gate) { return gate->get_matrix(); });
}
} // namespace internal
#endif
Expand Down
Loading

0 comments on commit 9aad61b

Please sign in to comment.