graphix icon indicating copy to clipboard operation
graphix copied to clipboard

Unitary from pattern

Open FlorianFuerrutter opened this issue 2 years ago • 2 comments

Describe the feature you'd like

Hey all, I'm interested if there is any (efficient) way to get the unitary implemented from a given pattern. I did not find any direct function but I think this could be done easily if one can set the input state arbitrarily (issue #53) and check for flow of a pattern.

Additional context

I would propose a (pseudo) code in that direction:

def get_unitary_from_pattern(pattern):
		
	# check if given pattern has flow, i.e. it implements indeed a unitary
	assert has_flow(pattern)

	# num_qubits .. defined via input/ouput nodes
	assert pattern.num_input_nodes == pattern.num_output_nodes
	
	num_qubits = pattern.num_input_nodes
	N          = 2**num_qubits

	#----- get unitary -----
	# do <i|U|j>=U_ij, where |n>=(0, .., 1, .., 0) std-basis
	# maybe the lib (tensornetwork) allows a more efficient way?

	U = np.zeros((N, N), dtype=np.complex128)
	
	for j in range(N): #can be async

		# set |j> input
		state_j    = np.zeros((N), dtype=np.complex128) 
		state_j[j] = 1
		pattern.set_input(state_j)

		# get matrix elements
		tn        = pattern.simulate_pattern(backend='tensornetwork')
		state_U_j = tn.to_statevector()

		U[:, j] = state_U_j

		#same as
		#for i in range(N): U[i, j] = state_U_j[i]

	return U

Maybe there is a better way to do this? Maybe even with the current code base?

FlorianFuerrutter avatar Dec 04 '23 12:12 FlorianFuerrutter

Hey, thanks for the suggestion. Direct unitary extraction from a pattern would certainly be a good feature (we don't have that yet)!

For pattens with flow (only XY-plane measurements), it might be easier to directly translate into a gate network with CZ (edges connecting different flow paths) and

J(\alpha) = 
\begin{pmatrix} 
1 & e^{i\alpha} \\  
1 & -e^{i\alpha} 
\end{pmatrix}

(for XY-plane measurements with angle $\alpha$ along flow paths) gates and work out the unitary directly. For pattens with gflow, as you suggest, it's likely best to do simulations. TN simulation without inputs may give you the unitary (if memory allows).

cc: @masa10-f - would you agree or not? lmk what you think.

shinich1 avatar Dec 05 '23 15:12 shinich1

Thanks for the good comments! @shinich1 @FlorianFuerrutter

As far as I understand, direct construction from tensornetwork seems to be the most efficient method, no matter the type of flow(causal flow / generalize flow / pauli flow). First off, we create a tensornetwork by turning each measurement command into its tensor equivalent(e.g. N -> |+>, E -> 4-rank CZ tensor, M -> projection vector). Then, we contract all the inner edges. After that, we end up with a 2n-rank tensor, which can be reshaped into an n-qubit Unitary matrix. In this approach, we don't have to compute each matrix element one by one; we get them all in one go.

Regarding the implementation, we'll need to modify tensornet.py. It is not hard but may need some tensornetwork know-how.

If you're just looking at patterns with causal flow, @shinich1 's idea is pretty straightforward. We can apply the same techniques used in various quantum circuit libraries.

Just a reminder, the existence of Pauli flow is the weakest condition of Unitary embedding for a given pattern. So what we have to check here is pauli flow :)

masa10-f avatar Dec 07 '23 12:12 masa10-f