"""simple docstring"""


import math
import sys




class 					UpperCamelCase   :







       def __init__(					self) -> str:
            snake_case_   			=   0
            snake_case_   			=   []
            snake_case_   			=   {}  # To store the pos of node in array







       def 						a_		(					self) -> List[str]:
            return self.cur_size == 0







       def 						a_		(					self,				lowerCAmelCase__) -> Optional[int]:
            snake_case_   			=   self.left(lowercase__)
            snake_case_   			=   self.right(lowercase__)
            if lc < self.cur_size and self.array(lowercase__)[0] < self.array(lowercase__)[0]:
                 snake_case_   			=   lc
            else:
                 snake_case_   			=   idx
            if rc < self.cur_size and self.array(lowercase__)[0] < self.array(lowercase__)[0]:
                 snake_case_   			=   rc
            if smallest != idx:
                 self.swap(lowercase__,				lowercase__)
                 self.min_heapify(lowercase__)







       def 						a_		(					self,				lowerCAmelCase__) -> List[Any]:
            snake_case_   			=   self.cur_size
            self.cur_size += 1
            self.array.append((sys.maxsize, tup[1]))
            self.decrease_key((sys.maxsize, tup[1]),				tup[0])







       def 						a_		(					self) -> List[str]:
            snake_case_   			=   self.array[0][1]
            snake_case_   			=   self.array[self.cur_size - 1]
            self.cur_size -= 1
            self.min_heapify(1)
            del self.pos[min_node]
            return min_node







       def 						a_		(					self,				lowerCAmelCase__) -> List[str]:
            return 2 * i + 1







       def 						a_		(					self,				lowerCAmelCase__) -> List[Any]:
            return 2 * i + 2







       def 						a_		(					self,				lowerCAmelCase__) -> List[str]:
            return math.floor(i / 2)







       def 						a_		(					self,				lowerCAmelCase__,				lowerCAmelCase__) -> List[Any]:
            snake_case_   			=   j
            snake_case_   			=   i
            snake_case_   			=   self.array[i]
            snake_case_   			=   self.array[j]
            snake_case_   			=   temp







       def 						a_		(					self,				lowerCAmelCase__,				lowerCAmelCase__) -> Optional[int]:
            snake_case_   			=   self.pos[tup[1]]
            # assuming the new_d is atmost old_d
            snake_case_   			=   (new_d, tup[1])
            while idx > 0 and self.array[self.par(lowercase__)][0] > self.array[idx][0]:
                 self.swap(lowercase__,				self.par(lowercase__))
                 snake_case_   			=   self.par(lowercase__)




class 					UpperCamelCase   :







       def __init__(					self,				lowerCAmelCase__) -> Dict:
            snake_case_   			=   {}  # To store graph: u -> (v,w)
            snake_case_   			=   num  # Number of nodes in graph
            # To store the distance from source vertex
            snake_case_   			=   [0] * self.num_nodes
            snake_case_   			=   [-1] * self.num_nodes  # To store the path







       def 						a_		(					self,				lowerCAmelCase__,				lowerCAmelCase__,				lowerCAmelCase__) -> Union[str, Any]:







            if u in self.adjList:
                 self.adjList[u].append((v, w))
            else:
                 snake_case_   			=   [(v, w)]

            # Assuming undirected graph
            if v in self.adjList:
                 self.adjList[v].append((u, w))
            else:
                 snake_case_   			=   [(u, w)]







       def 						a_		(					self) -> Dict:







            for u in self.adjList:
                 print(lowercase__,				'->',				' -> '.join(str(f'{v}({w})') for v, w in self.adjList[u]))







       def 						a_		(					self,				lowerCAmelCase__) -> int:
            snake_case_   			=   [-1] * self.num_nodes
            # src is the source node
            snake_case_   			=   0
            snake_case_   			=   PriorityQueue()
            q.insert((0, src))  # (dist from src, node)
            for u in self.adjList:
                 if u != src:
                      snake_case_   			=   sys.maxsize  # Infinity
                      snake_case_   			=   -1

            while not q.is_empty():
                 snake_case_   			=   q.extract_min()  # Returns node with the min dist from source
                 # Update the distance of all the neighbours of u and
                 # if their prev dist was INFINITY then push them in Q
                 for v, w in self.adjList[u]:
                      snake_case_   			=   self.dist[u] + w
                      if self.dist[v] > new_dist:
                           if self.dist[v] == sys.maxsize:
                                q.insert((new_dist, v))
                           else:
                                q.decrease_key((self.dist[v], v),				lowercase__)
                           snake_case_   			=   new_dist
                           snake_case_   			=   u

        # Show the shortest distances from src
            self.show_distances(lowercase__)







       def 						a_		(					self,				lowerCAmelCase__) -> List[Any]:
            print(f'Distance from node: {src}')
            for u in range(self.num_nodes):
                 print(f'Node {u} has distance: {self.dist[u]}')







       def 						a_		(					self,				lowerCAmelCase__,				lowerCAmelCase__) -> List[str]:
            snake_case_   			=   []
            snake_case_   			=   0
            snake_case_   			=   dest
            # Backtracking from dest to src
            while self.par[temp] != -1:
                 path.append(lowercase__)
                 if temp != src:
                      for v, w in self.adjList[temp]:
                           if v == self.par[temp]:
                                cost += w
                                break
                 snake_case_   			=   self.par[temp]
            path.append(lowercase__)
            path.reverse()

            print(f'----Path to reach {dest} from {src}----')
            for u in path:
                 print(f'{u}',				end=' ')
                 if u != dest:
                      print('-> ',				end='')

            print('\nTotal cost of path: ',				lowercase__)


if __name__ == "__main__":
    __UpperCamelCase										=     Graph(9)
    graph.add_edge(0, 1, 4)
    graph.add_edge(0, 7, 8)
    graph.add_edge(1, 2, 8)
    graph.add_edge(1, 7, 11)
    graph.add_edge(2, 3, 7)
    graph.add_edge(2, 8, 2)
    graph.add_edge(2, 5, 4)
    graph.add_edge(3, 4, 9)
    graph.add_edge(3, 5, 14)
    graph.add_edge(4, 5, 10)
    graph.add_edge(5, 6, 2)
    graph.add_edge(6, 7, 1)
    graph.add_edge(6, 8, 6)
    graph.add_edge(7, 8, 7)
    graph.show_graph()
    graph.dijkstra(0)
    graph.show_path(0, 4)

# OUTPUT
# 0 -> 1(4) -> 7(8)
# 1 -> 0(4) -> 2(8) -> 7(11)
# 7 -> 0(8) -> 1(11) -> 6(1) -> 8(7)
# 2 -> 1(8) -> 3(7) -> 8(2) -> 5(4)
# 3 -> 2(7) -> 4(9) -> 5(14)
# 8 -> 2(2) -> 6(6) -> 7(7)
# 5 -> 2(4) -> 3(14) -> 4(10) -> 6(2)
# 4 -> 3(9) -> 5(10)
# 6 -> 5(2) -> 7(1) -> 8(6)
# Distance from node: 0
# Node 0 has distance: 0
# Node 1 has distance: 4
# Node 2 has distance: 12
# Node 3 has distance: 19
# Node 4 has distance: 21
# Node 5 has distance: 11
# Node 6 has distance: 9
# Node 7 has distance: 8
# Node 8 has distance: 14
# ----Path to reach 4 from 0----
# 0 -> 7 -> 6 -> 5 -> 4
# Total cost of path:  21



"""simple docstring"""




import numpy as np
import qiskit
from qiskit import Aer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute

def     UpperCamelCase_    (						SCREAMING_SNAKE_CASE_ = np.pi / 2,	SCREAMING_SNAKE_CASE_ = np.pi / 2,	SCREAMING_SNAKE_CASE_ = np.pi / 2     ):
					SCREAMING_SNAKE_CASE           =      QuantumRegister(3,	'qr'     )  # Define the number of quantum bits
					SCREAMING_SNAKE_CASE           =      ClassicalRegister(1,	'cr'     )  # Define the number of classical bits

					SCREAMING_SNAKE_CASE           =      QuantumCircuit(SCREAMING_SNAKE_CASE_,	SCREAMING_SNAKE_CASE_     )  # Define the quantum circuit.

					# Build the circuit
					quantum_circuit.u(SCREAMING_SNAKE_CASE_,	SCREAMING_SNAKE_CASE_,	SCREAMING_SNAKE_CASE_,	0     )  # Quantum State to teleport
					quantum_circuit.h(1     )  # add hadamard gate
					quantum_circuit.cx(
					    1,	2     )  # add control gate with qubit 1 as control and 2 as target.
					quantum_circuit.cx(0,	1     )
					quantum_circuit.h(0     )
					quantum_circuit.cz(0,	2     )  # add control z gate.
					quantum_circuit.cx(1,	2     )

					quantum_circuit.measure([2],	[0]     )  # measure the qubit.

					# Simulate the circuit using qasm simulator
					SCREAMING_SNAKE_CASE           =      Aer.get_backend('aer_simulator'     )
					SCREAMING_SNAKE_CASE           =      execute(SCREAMING_SNAKE_CASE_,	SCREAMING_SNAKE_CASE_,	shots=1_0_0_0     )

					return job.result().get_counts(SCREAMING_SNAKE_CASE_     )


if __name__ == "__main__":
	print(
	    'Total count for teleported state is: '
	    f'{quantum_teleportation(np.pi/2, np.pi/2, np.pi/2)}'
	)
