"""\********************************************************************************* Copyright (c) 2025 the Qrisp authors** This program and the accompanying materials are made available under the* terms of the Eclipse Public License 2.0 which is available at* http://www.eclipse.org/legal/epl-2.0.** This Source Code may also be made available under the following Secondary* Licenses when the conditions for such availability set forth in the Eclipse* Public License, v. 2.0 are satisfied: GNU General Public License, version 2* with the GNU Classpath Exception which is* available at https://www.gnu.org/software/classpath/license.html.** SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0********************************************************************************/"""importnumpyasnpfromqrisp.coreimportp,h,cp,cx,x,s,swapfromqrisp.jaspimportqache,jrange,check_for_tracing_modedefQFT_inner(qv,exec_swap=True,qiskit_endian=True,inplace_mult=1,use_gms=False,inpl_adder=None):fromqrisp.miscimportis_invqv=list(qv)n=len(qv)ifqiskit_endian:qv=qv[::-1]ifnotuse_gms:fromqrisp.environments.quantum_environmentsimportQuantumEnvironmentenv=QuantumEnvironmentelse:fromqrisp.environments.GMS_environmentimportGMSEnvironmentenv=GMSEnvironmentifnotis_inv(inplace_mult,n):raiseException("Tried to perform non-invertible inplace multiplication""during Fourier-Transform")ifinpl_adderisNone:accumulated_phases=np.zeros(n)foriinrange(n):ifaccumulated_phases[i]andnotuse_gms:p(accumulated_phases[i],qv[i])accumulated_phases[i]=0h(qv[i])ifi==n-1:breakwithenv():forkinrange(n-i-1):# cp(inplace_mult * 2 * np.pi / 2 ** (k + 2), qv[k + i + 1], qv[i])ifuse_gms:cp(inplace_mult*2*np.pi/2**(k+2),qv[i],qv[k+i+1])else:phase=inplace_mult*2*np.pi/2**(k+2)# cx(qv[k + i + 1], qv[i])# p(-phase/2, qv[i])# cx(qv[k + i + 1], qv[i])cx(qv[i],qv[k+i+1])p(-phase/2,qv[k+i+1])cx(qv[i],qv[k+i+1])accumulated_phases[i]+=phase/2accumulated_phases[k+i+1]+=phase/2foriinrange(n):ifaccumulated_phases[i]andnotuse_gms:p(accumulated_phases[i],qv[i])accumulated_phases[i]=0else:fromqrispimportQuantumFloat,conjugatereservoir=QuantumFloat(n+1)defprepare_reservoir(reservoir):n=len(reservoir)h(reservoir)foriinrange(n):p(np.pi*2**(i-n+1),reservoir[i])withconjugate(prepare_reservoir)(reservoir):foriinrange(n):h(qv[i])ifi==n-1:breakphase_qubits=[]forkinrange(n-i-1):cx(qv[i],qv[k+i+1])phase_qubits.append(qv[k+i+1])inpl_adder(phase_qubits[::-1],reservoir[-len(phase_qubits)-2:])forkinrange(n-i-1):cx(qv[i],qv[k+i+1])x(reservoir)inpl_adder(phase_qubits[::-1],reservoir[-len(phase_qubits)-2:])x(reservoir)s(qv)inpl_adder(qv,reservoir[-n-1:])reservoir.delete()ifexec_swap:foriinrange(n//2):swap(qv[i],qv[n-i-1])returnqv
[docs]defQFT(qv,inv=False,exec_swap=True,qiskit_endian=True,inplace_mult=1,use_gms=False,inpl_adder=None):""" Performs the quantum fourier transform on the input. Parameters ---------- qv : QuantumVariable QuantumVariable to transform (in-place). inv : bool, optional If set to True, the inverse transform will be applied. The default is False. exec_swap : bool, optional If set to False, the swaps at the end of the transformation will be skipped. The default is True. qiskit_endian : bool, optional If set to False the order of bits will be reversed. The default is True. inplace_mult : int, optional Allows multiplying the QuantumVariable with an extra factor during the transformation. For more information check `the publication <https://ieeexplore.ieee.org/document/9815035>`_. The default is 1. use_gms : bool, optional If set to True, the QFT will be compiled using only GMS gates as entangling gates. The default is False. inpl_adder : callable, optional Uses an adder and a reservoir state to perform the QFT. Read more about it :ref:`here <adder_based_qft>`. The default is None """fromqrispimportgate_wrap,invertname="QFT"ifnotexec_swap:name+=" no swap"ifinplace_mult!=1:name+=" inpl mult "+str(inplace_mult)ifinpl_adderisnotNone:name+="_adder_supported"ifinv:withinvert():ifcheck_for_tracing_mode():jasp_qft(qv,exec_swap)else:gate_wrap(permeability=[],is_qfree=False,name=name)(QFT_inner)(qv,exec_swap=exec_swap,qiskit_endian=qiskit_endian,inplace_mult=inplace_mult,use_gms=use_gms,inpl_adder=inpl_adder)else:ifcheck_for_tracing_mode():jasp_qft(qv,exec_swap)else:gate_wrap(permeability=[],is_qfree=False,name=name)(QFT_inner)(qv,exec_swap=exec_swap,qiskit_endian=qiskit_endian,inplace_mult=inplace_mult,use_gms=use_gms,inpl_adder=inpl_adder)returnqv
@qache(static_argnums=[1])defjasp_qft(qv,exec_swap):"""Performs qft on the first n qubits in circuit (without swaps)"""ifisinstance(qv,list):n=len(qv)else:n=qv.sizeforiinjrange(n):# passh(qv[n-1-i])forkinjrange(n-i-1):cp(2.*np.pi/pow(2.,(k+2)),qv[n-1-(k+i+1)],qv[n-1-i])ifexec_swap:foriinjrange(n//2):swap(qv[i],qv[n-i-1])
Get in touch!
If you are interested in Qrisp or high-level quantum algorithm research in general connect with us on our
Slack workspace.