diff --git a/Project.toml b/Project.toml index 0c58e3a8..9cdea500 100644 --- a/Project.toml +++ b/Project.toml @@ -28,6 +28,7 @@ GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" +PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" Quac = "b9105292-1415-45cf-bff1-d6ccf71e6143" Reactant = "3c362404-f566-11ee-1572-e11a4b42c853" Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c" @@ -41,6 +42,7 @@ TenetDaggerExt = "Dagger" TenetFiniteDifferencesExt = "FiniteDifferences" TenetGraphMakieExt = ["GraphMakie", "Makie"] TenetKrylovKitExt = ["KrylovKit"] +TenetPythonCallExt = "PythonCall" TenetQuacExt = "Quac" TenetReactantExt = "Reactant" TenetYaoExt = "Yao" @@ -63,6 +65,7 @@ KrylovKit = "0.8.1" LinearAlgebra = "1.9" Makie = "0.18,0.19,0.20, 0.21" OMEinsum = "0.7, 0.8" +PythonCall = "0.9" Quac = "0.3" Random = "1.9" Reactant = "0.2" diff --git a/ext/TenetPythonCallExt.jl b/ext/TenetPythonCallExt.jl new file mode 100644 index 00000000..80e11da9 --- /dev/null +++ b/ext/TenetPythonCallExt.jl @@ -0,0 +1,54 @@ +module TenetPythonCallExt + +using Tenet +using PythonCall +using PythonCall.Core: pyisnone + +pyfullyqualname(pyobj) = join([pytype(pyobj).__module__, pytype(pyobj).__qualname__], '.') + +function Tenet.Quantum(pyobj::Py) + pyclassname = pyfullyqualname(pyobj) + if pyclassname != "qiskit.circuit.quantumcircuit.QuantumCircuit" + throw(ArgumentError("Expected a Qiskit's QuantumCircuit object, got $pyclassname")) + end + + n = length(pyobj.qregs[0]) + gen = Tenet.IndexCounter() + + wire = [[Tenet.nextindex!(gen)] for _ in 1:n] + tensors = Tensor[] + + for instr in pyobj + # if unassigned parameters, throw + matrix = instr.matrix + if pyisnone(matrix) + throw(ArgumentError("Expected parameters already assigned, but got $(pyobj.params)")) + end + + matrix = pyconvert(Array, matrix) + + qubits = map(x -> pyconvert(Int, x._index), instr.qubits) + array = reshape(matrix, fill(2, 2 * length(qubits))...) + + inds = (x -> collect(Iterators.flatten(zip(x...))))( + map(qubits) do l + l += 1 + from, to = last(wire[l]), Tenet.nextindex!(gen) + push!(wire[l], to) + (from, to) + end, + ) + + tensor = Tensor(array, Tuple(inds)) + push!(tensors, tensor) + end + + sites = merge( + Dict([Site(site; dual=true) => first(index) for (site, index) in enumerate(wire)]), + Dict([Site(site; dual=false) => last(index) for (site, index) in enumerate(wire)]), + ) + + return Quantum(Tenet.TensorNetwork(tensors), sites) +end + +end