#
# Copyright 2021 Keysight Technologies Inc.
#
"""
Gate synthesis
==============
"""
#%%
# This example demonstrates how the built-in compiler can be used to perform gate
# synthesis.
#%%
# Synthesizing Single-Qubit Gates
# -------------------------------
# We begin by generating a random gate in :math:`SU(2)`\; we will synthesize this gate
# later.
import trueq as tq
# create a Haar random SU(2) gate and print its matrix representation
U = tq.Gate.random(2)
U
#%%
# We can perform single qubit gate decomposition into a number of possible "modes".
# Here we decompose the gate ``U`` into a ZXZXZ decomposition, which is short hand
# for :math:`Z(\theta)X(90)Z(\phi)X(90)Z(\gamma)`\. See
# :py:class:`~trueq.math.decomposition.QubitMode` for a complete list of all available
# single qubit decompositions.
synthesized_gate = tq.math.QubitMode.ZXZXZ.decompose(U)
# print the synthesized gate as a list of single-qubit rotations about Z and X
synthesized_gate
#%%
# Synthesizing Two-Qubit Gates
# ----------------------------
# In the event that we want to express a two-qubit gate in terms of a different
# two-qubit gate, we can use the compiler to synthesize the desired gate.
# Here we decompose a random :math:`SU(4)` operation so that it can be implemented
# using iSWAP gates.
# define the gate to be synthesized
gate_to_be_synthesized = tq.Gate.random(4)
# re-express the gate using an iswap gate as the two-qubit gate
two_qubit_synthesized_gate = tq.math.decompose_unitary(
target_gate=gate_to_be_synthesized, given_gate=tq.Gate.iswap
)
# print the synthesized gate
two_qubit_synthesized_gate
#%%
# This circuit can be verified to reproduce the original random unitary using an ideal
# simulator:
matrix = tq.Simulator().operator(two_qubit_synthesized_gate).mat()
# This will result in an identity gate up to a global complex phase.
tq.visualization.plot_mat(matrix @ gate_to_be_synthesized.adj.mat)