Haiqu.fourier_loading(fourier_coefficients, num_qubits=None, min_freqs=None, long_range=False, num_layers=2, truncation_cutoff=1e-06, fine_tuning_iterations=20, max_time=900, name=None, job_description=None)
Generate a quantum circuit that prepares a band-limited multidimensional state from its Fourier coefficients. Given the Fourier coefficients of a state, this method creates a Data Loading job that runs in the Haiqu cloud. The coefficients are synthesized on the smallest register that fits them, and an optimized quantum Fourier transform per dimension expands them onto the output grid. The result of this job is a circuit which can be used to supply the state to a quantum algorithm for processing. It pays off only for spectra concentrated in few frequencies, so the state is assumed to represent a periodic function; symmetrizing a dimension can make a non-periodic target more periodic. The coefficients are normally obtained withcompute_fourier_coefficients(), which takes an array of
values on a uniform grid and returns fourier_coefficients and min_freqs in exactly the form this method expects.
The complexity and quality of the generated circuit can be controlled by the num_layers,
truncation_cutoff, and fine_tuning_iterations parameters.
NOTE
Frequency layout.fourier_coefficients[i0, i1, ...] is the weight of the harmonic
exp(2j*pi*((min_freqs[0] + i0)*x0 + (min_freqs[1] + i1)*x1 + ...)), so coefficients ascend in
frequency along every axis — the layout compute_fourier_coefficients() returns.
np.fft.fftn does not produce this order: it wraps the negative frequencies onto the end, returning a
length-4 axis as [0, 1, -2, -1] rather than [-2, -1, 0, 1]. Pass a raw FFT result through
np.fft.fftshift first, after which index 0 carries -(n // 2) — the min_freqs default.
min_freqs is applied as a frequency-shift layer, not just as bookkeeping. A value that does not match
how the coefficients were obtained encodes the wrong complex exponential, whose amplitude magnitudes may
still look plausible. Slicing a narrower band out of a shifted spectrum moves the first frequency, so pass
the min_freqs that compute_fourier_coefficients() returns.
NOTE
Grid indexing. The encoded array is recovered from the statevector by reshaping it onto the per-dimension grid,Statevector(circuit).data.reshape([2**n for n in job.info["num_qubits_per_dimension"]]), up to a
global phase left behind by the frequency-shift layer. The first array dimension occupies the
highest-index qubits, and grid point m along dimension d corresponds to
x_d = m / 2**num_qubits_per_dimension[d].
Unlike vector_loading(), where qubits beyond the data size are dead zero padding, every output
qubit above the per-dimension minimum performs band-limited Fourier interpolation onto a finer grid, at
the cost of a Fourier layer rather than a wider state preparation. Resolution is therefore almost free:
the same 9x9 block of coefficients reaches the same fidelity on a 32x32 grid (10 qubits) as on a 256x256
grid (16 qubits). A dimension holding a single frequency needs no qubit to embed it,
so its entry in num_qubits_per_dimension may be 0 when num_qubits is None; such a
dimension carries a constant, and giving it output qubits spreads that constant over its grid.
NOTE
“job.quality“ excludes the truncation error. It is the fidelity of synthesizing the coefficients you supplied, which are taken as the exact target, so how they were obtained does not enter it. Discarding frequencies is a separate, purely classical approximation, measured by the fidelity thatcompute_fourier_coefficients() returns. The fidelity of the final state against your original
array is approximately the product of the two.
- Parameters:
- fourier_coefficients (Sequence *[*Number ] | np.ndarray) — The multidimensional array of Fourier coefficients,
ascending in frequency along every axis, which is not the order
np.fft.fftnreturns (see the frequency-layout note above). May be real or complex, and is normalized in the process. This is the layout thatcompute_fourier_coefficients()returns, which is the recommended way to obtain it; an analytically known spectrum can equally be written down directly. - num_qubits (int | Sequence *[*int ] | None) — The number of output qubits per dimension. An integer is shared by all
dimensions, a sequence sets them individually in the order of the coefficient array’s
axes. Each entry must be at least
ceil(log2(n))for a dimension holdingnfrequencies; every qubit above that minimum interpolates the state onto a finer grid. IfNone(default), the minimum that fits the coefficients is used, which performs no interpolation. - min_freqs (int | Sequence *[*int ] | None) — The integer frequency that the first coefficient of each dimension
carries. An integer is shared by all dimensions, a sequence sets them individually
in the order of the coefficient array’s axes. If
None(default), each dimension is assumed to hold a band centred on zero and takes-(n // 2)for its lengthn. It is applied as a frequency-shift layer, so a value that disagrees with how the coefficients were obtained silently encodes the wrong state — see the frequency-layout note above. - long_range (bool) — Whether to allow long-range gates in the Fourier part of the circuit. The prepared state is
the same either way, while
False(default) keeps the gates on a linear chain. - num_layers (int) — The number of layers used to synthesize the coefficients (from 1 to 100 layers). More layers can improve the quality of the output at the cost of a deeper circuit. Defaults to 2.
- truncation_cutoff (Real) — The entanglement cutoff for later layers. Increasing this threshold may result in a
smaller (but more approximate) circuit. Defaults to
1e-6. - fine_tuning_iterations (int) — The maximum number of fine-tuning iterations to perform after each layer is added. Increasing this limit may improve the quality of the circuit by using more classical resources. Defaults to 20, maximal is 500.
- max_time (int | float) — Soft time limit for the job (in seconds). The data loading job will first always produce the initial result and then limit the fine-tuning stage by the remaining time left. If time limit exceeds during the fine-tuning - the best current result will be returned. Defaults to 900 (15 min). Max allowed job time is 15 min. The job can take more wall clock time than user specified max_time due to latency, initialization overheads or if the initial result already takes more time.
- name (str | None) — The name for the job and the produced circuit. If
None(default), a name will be automatically generated. - job_description (str | None) — The description for the job.
- fourier_coefficients (Sequence *[*Number ] | np.ndarray) — The multidimensional array of Fourier coefficients,
ascending in frequency along every axis, which is not the order
- Returns:
The Data Loading job that will generate the circuit for the band-limited state.
: Call
job.result()to retrieve a Qiskit-compatible gate (HaiquCircuitGate) that prepares the state.job.qualityis the achieved state fidelity vs. the supplied coefficients;job.infoexposes loader metadata (fidelity,num_qubits_per_dimension). Runhelp(job.result)for the full description of result andinfocontents. - Return type: DataLoadingJobModel
Examples
An exact finite Fourier series.cos(2*pi*3*x) has only the -3 and +3 harmonics, so retaining the band
(-3, 3) discards nothing and both fidelities are 1:
haiqu.sdk.utils.compute_fourier_coefficients(state, freq_ranges, return_fidelity=False)
Compute truncated, normalized Fourier coefficients of an n-dimensional array. The returned values are the input thathaiqu.sdk.quantum_haiqu.Haiqu.fourier_loading() expects: the coefficients ascend in
frequency along every axis, which is not the order np.fft.fftn returns, and min_freqs
records which frequency the first coefficient of each axis carries.
Keeping only a few frequencies per axis is what makes Fourier loading cheap, and it is also
the only lossy step performed here. The optional fidelity quantifies exactly that loss. It is
a purely classical quantity computed locally and for free, and it is not part of the loading
job’s quality, which measures how well the cloud reproduces whatever coefficients it is
given. The fidelity of the final state against the original state is approximately the
product of the two.
- Parameters:
- state (np.ndarray | Sequence) — Values of the target on a (possibly coarse) uniform grid. The array is treated as periodic on that grid, so a non-periodic target may need many frequencies; symmetrizing it along a dimension can help.
- freq_ranges (Sequence *[*Sequence *[*int ] ]) — One
(min_freq, max_freq)pair per dimension, giving the inclusive frequency band to retain. Each band must lie inside the range the grid resolves,[-(n // 2), n - n // 2 - 1]for an axis of lengthn. - return_fidelity (bool) — Whether to also return the retained fraction of the spectral
energy. Defaults to
False.
- Returns:
The complex
coefficient array of shape
max_freq - min_freq + 1per dimension, normalized to unit norm, and the per-dimensionmin_freqvalues. Withreturn_fidelitya third value is appended: the squared overlap between the reconstruction from the retained frequencies andstate. It is1.0when the bands cover the whole resolved spectrum, and also when they cover the entire support of a finite Fourier series, however few frequencies that is. - Return type: tuple[np.ndarray, list[int]] | tuple[np.ndarray, list[int], float]
- Raises:
ValueError — If the number of bands does not match the number of dimensions, a band is not
a pair,
min_freqexceedsmax_freq, or a band falls outside the resolved range.