


'''simple docstring'''






from importlib import import_module

from .logging import get_logger


__UpperCAmelCase					       =							get_logger(__name__)




class 	a__       :





							'''simple docstring'''






							def __init__(	self      ,					lowerCamelCase_      ,					lowerCamelCase_=None     ) ->							int:
														lowerCAmelCase__      =			attrs or []
														if module is not None:
																					for key in module.__dict__:
																												if key in attrs or not key.startswith('''__'''     ):
																																			setattr(self      ,					lowerCamelCase_      ,					getattr(lowerCamelCase_      ,					lowerCamelCase_     )     )
														lowerCAmelCase__      =			module._original_module if isinstance(lowerCamelCase_      ,					_PatchedModuleObj     ) else module




class 	a__       :





							'''simple docstring'''






							lowercase__    :     List[str]					=   []







							def __init__(	self      ,					lowerCamelCase_      ,					lowerCamelCase_      ,					lowerCamelCase_      ,					lowerCamelCase_=None     ) ->							str:
														lowerCAmelCase__      =			obj
														lowerCAmelCase__      =			target
														lowerCAmelCase__      =			new
														lowerCAmelCase__      =			target.split('''.'''     )[0]
														lowerCAmelCase__      =			{}
														lowerCAmelCase__      =			attrs or []







							def __enter__(	self     ) ->							Tuple:
														*lowerCAmelCase__     ,      lowerCAmelCase__      =			self.target.split('''.'''     )

														# Patch modules:
														# it's used to patch attributes of submodules like "os.path.join";
														# in this case we need to patch "os" and "os.path"

														for i in range(len(lowerCamelCase_     )     ):
																					try:
																												lowerCAmelCase__      =			import_module('''.'''.join(submodules[: i + 1]     )     )
																					except ModuleNotFoundError:
																												continue
																					# We iterate over all the globals in self.obj in case we find "os" or "os.path"
																					for attr in self.obj.__dir__():
																												lowerCAmelCase__      =			getattr(self.obj      ,					lowerCamelCase_     )
																												# We don't check for the name of the global, but rather if its value *is* "os" or "os.path".
																												# This allows to patch renamed modules like "from os import path as ospath".
																												if obj_attr is submodule or (
																												    (isinstance(lowerCamelCase_      ,					_PatchedModuleObj     ) and obj_attr._original_module is submodule)
																												):
																																			lowerCAmelCase__      =			obj_attr
																																			# patch at top level
																																			setattr(self.obj      ,					lowerCamelCase_      ,					_PatchedModuleObj(lowerCamelCase_      ,					attrs=self.attrs     )     )
																																			lowerCAmelCase__      =			getattr(self.obj      ,					lowerCamelCase_     )
																																			# construct lower levels patches
																																			for key in submodules[i + 1 :]:
																																										setattr(lowerCamelCase_      ,					lowerCamelCase_      ,					_PatchedModuleObj(getattr(lowerCamelCase_      ,					lowerCamelCase_      ,					lowerCamelCase_     )      ,					attrs=self.attrs     )     )
																																										lowerCAmelCase__      =			getattr(lowerCamelCase_      ,					lowerCamelCase_     )
																																			# finally set the target attribute
																																			setattr(lowerCamelCase_      ,					lowerCamelCase_      ,					self.new     )

        # Patch attribute itself:
        # it's used for builtins like "open",
        # and also to patch "os.path.join" we may also need to patch "join"
        # itself if it was imported as "from os.path import join".

														if submodules:  # if it's an attribute of a submodule like "os.path.join"
																					try:
																												lowerCAmelCase__      =			getattr(import_module('''.'''.join(lowerCamelCase_     )     )      ,					lowerCamelCase_     )
																					except (AttributeError, ModuleNotFoundError):
																												return
																					# We iterate over all the globals in self.obj in case we find "os.path.join"
																					for attr in self.obj.__dir__():
																												# We don't check for the name of the global, but rather if its value *is* "os.path.join".
																												# This allows to patch renamed attributes like "from os.path import join as pjoin".
																												if getattr(self.obj      ,					lowerCamelCase_     ) is attr_value:
																																			lowerCAmelCase__      =			getattr(self.obj      ,					lowerCamelCase_     )
																																			setattr(self.obj      ,					lowerCamelCase_      ,					self.new     )
														elif target_attr in globals()["__builtins__"]:  # if it'a s builtin like "open"
																					lowerCAmelCase__      =			globals()['''__builtins__'''][target_attr]
																					setattr(self.obj      ,					lowerCamelCase_      ,					self.new     )
														else:
																					raise RuntimeError(F"""Tried to patch attribute {target_attr} instead of a submodule."""     )







							def __exit__(	self      ,					*lowerCamelCase_     ) ->							Any:
														for attr in list(self.original     ):
																					setattr(self.obj      ,					lowerCamelCase_      ,					self.original.pop(lowerCamelCase_     )     )







							def 						__SCREAMING_SNAKE_CASE							(	self     ) ->							Optional[int]:
														self.__enter__()
														self._active_patches.append(self     )







							def 						__SCREAMING_SNAKE_CASE							(	self     ) ->							str:
														try:
																					self._active_patches.remove(self     )
														except ValueError:
																					# If the patch hasn't been started this will fail
																					return None

														return self.__exit__()



'''simple docstring'''






import numpy as np
import qiskit


def       _snake_case     (  A = 8				,					A = None )		->					str:
							lowerCAmelCase__      =			np.random.default_rng(seed=A )

							# Roughly 25% of the qubits will contribute to the key.
							# So we take more than we need.
							lowerCAmelCase__      =			6 * key_len
							# Measurement basis for Alice's qubits.
							lowerCAmelCase__      =			rng.integers(2				,					size=A )
							# The set of states Alice will prepare.
							lowerCAmelCase__      =			rng.integers(2				,					size=A )
							# Measurement basis for Bob's qubits.
							lowerCAmelCase__      =			rng.integers(2				,					size=A )

							# Quantum Circuit to simulate BB84
							lowerCAmelCase__      =			qiskit.QuantumCircuit(A				,					name='''BB84''' )

							# Alice prepares her qubits according to rules above.
							for index, _ in enumerate(A ):
														if alice_state[index] == 1:
																					bbaa_circ.x(A )
														if alice_basis[index] == 1:
																					bbaa_circ.h(A )
							bbaa_circ.barrier()

							# Bob measures the received qubits according to rules above.
							for index, _ in enumerate(A ):
														if bob_basis[index] == 1:
																					bbaa_circ.h(A )

							bbaa_circ.barrier()
							bbaa_circ.measure_all()

							# Simulate the quantum circuit.
							lowerCAmelCase__      =			qiskit.Aer.get_backend('''aer_simulator''' )
							# We only need to run one shot because the key is unique.
							# Multiple shots will produce the same key.
							lowerCAmelCase__      =			qiskit.execute(A				,					A				,					shots=1				,					seed_simulator=A )
							# Returns the result of measurement.
							lowerCAmelCase__      =			job.result().get_counts(A ).most_frequent()

							# Extracting the generated key from the simulation results.
							# Only keep measurement results where Alice and Bob chose the same basis.
							lowerCAmelCase__      =			''''''.join(
							    [
							        result_bit
							        for alice_basis_bit, bob_basis_bit, result_bit in zip(
							            A				,					A				,					A )
							        if alice_basis_bit == bob_basis_bit
							    ] )

							# Get final key. Pad with 0 if too short, otherwise truncate.
							lowerCAmelCase__      =			gen_key[:key_len] if len(A ) >= key_len else gen_key.ljust(A				,					'''0''' )
							return key


if __name__ == "__main__":
		print(f"""The generated key is : {bbaa(8, seed=0)}""")
		from doctest import testmod

		testmod()