

'''simple docstring'''



from dataclasses import dataclass
from typing import Optional, Tuple, Union

import torch
import torch.nn as nn

from ..configuration_utils import ConfigMixin, register_to_config
from ..utils import BaseOutput, apply_forward_hook
from .modeling_utils import ModelMixin
from .vae import Decoder, DecoderOutput, Encoder, VectorQuantizer




@dataclass
class   UpperCAmelCase_					(		lowerCAmelCase_			):






						'''simple docstring'''






						_lowercase		:				torch.FloatTensor






class   UpperCAmelCase_					(		lowerCAmelCase_	,							lowerCAmelCase_			):






						'''simple docstring'''






						@register_to_config
						def __init__( self   ,       _lowercase = 3   ,       _lowercase = 3   ,       _lowercase = ("DownEncoderBlock2D",)   ,       _lowercase = ("UpDecoderBlock2D",)   ,       _lowercase = (64,)   ,       _lowercase = 1   ,       _lowercase = "silu"   ,       _lowercase = 3   ,       _lowercase = 32   ,       _lowercase = 256   ,       _lowercase = 32   ,       _lowercase = None   ,       _lowercase = 0.1_8215   ,       _lowercase = "group"   ,       ):

												"""simple docstring"""



												super().__init__()

												# pass init params to Encoder
												_lowerCAmelCase  						=			Encoder(
												    in_channels=__SCREAMING_SNAKE_CASE   ,       out_channels=__SCREAMING_SNAKE_CASE   ,       down_block_types=__SCREAMING_SNAKE_CASE   ,       block_out_channels=__SCREAMING_SNAKE_CASE   ,       layers_per_block=__SCREAMING_SNAKE_CASE   ,       act_fn=__SCREAMING_SNAKE_CASE   ,       norm_num_groups=__SCREAMING_SNAKE_CASE   ,       double_z=__SCREAMING_SNAKE_CASE   ,       )

												_lowerCAmelCase  						=			vq_embed_dim if vq_embed_dim is not None else latent_channels

												_lowerCAmelCase  						=			nn.Convad(__SCREAMING_SNAKE_CASE   ,       __SCREAMING_SNAKE_CASE   ,       1				)
												_lowerCAmelCase  						=			VectorQuantizer(__SCREAMING_SNAKE_CASE   ,       __SCREAMING_SNAKE_CASE   ,       beta=0.25   ,       remap=__SCREAMING_SNAKE_CASE   ,       sane_index_shape=__SCREAMING_SNAKE_CASE				)
												_lowerCAmelCase  						=			nn.Convad(__SCREAMING_SNAKE_CASE   ,       __SCREAMING_SNAKE_CASE   ,       1				)

												# pass init params to Decoder
												_lowerCAmelCase  						=			Decoder(
												    in_channels=__SCREAMING_SNAKE_CASE   ,       out_channels=__SCREAMING_SNAKE_CASE   ,       up_block_types=__SCREAMING_SNAKE_CASE   ,       block_out_channels=__SCREAMING_SNAKE_CASE   ,       layers_per_block=__SCREAMING_SNAKE_CASE   ,       act_fn=__SCREAMING_SNAKE_CASE   ,       norm_num_groups=__SCREAMING_SNAKE_CASE   ,       norm_type=__SCREAMING_SNAKE_CASE   ,       )




						@apply_forward_hook
						def  _lowercase     ( self   ,       _lowercase   ,       _lowercase = True				):

												"""simple docstring"""



												_lowerCAmelCase  						=			self.encoder(__SCREAMING_SNAKE_CASE				)
												_lowerCAmelCase  						=			self.quant_conv(__SCREAMING_SNAKE_CASE				)

												if not return_dict:
																		return (h,)

												return VQEncoderOutput(latents=__SCREAMING_SNAKE_CASE				)




						@apply_forward_hook
						def  _lowercase     ( self   ,       _lowercase   ,       _lowercase = False   ,       _lowercase = True				):

												"""simple docstring"""



												if not force_not_quantize:
																		_lowerCAmelCase						,   _lowerCAmelCase						,   _lowerCAmelCase  						=			self.quantize(__SCREAMING_SNAKE_CASE				)
												else:
																		_lowerCAmelCase  						=			h
												_lowerCAmelCase  						=			self.post_quant_conv(__SCREAMING_SNAKE_CASE				)
												_lowerCAmelCase  						=			self.decoder(__SCREAMING_SNAKE_CASE   ,       quant if self.config.norm_type == """spatial""" else None				)

												if not return_dict:
																		return (dec,)

												return DecoderOutput(sample=__SCREAMING_SNAKE_CASE				)




						def  _lowercase     ( self   ,       _lowercase   ,       _lowercase = True				):

												"""simple docstring"""



												_lowerCAmelCase  						=			sample
												_lowerCAmelCase  						=			self.encode(__SCREAMING_SNAKE_CASE				).latents
												_lowerCAmelCase  						=			self.decode(__SCREAMING_SNAKE_CASE				).sample

												if not return_dict:
																		return (dec,)

												return DecoderOutput(sample=__SCREAMING_SNAKE_CASE				)


'''simple docstring'''



import numpy as np
import qiskit


def A				(__lowerCamelCase				:int = 8			,     __lowerCamelCase				:int | None = None		):
						_lowerCAmelCase  						=			np.random.default_rng(seed=__lowerCamelCase		)

						# 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=__lowerCamelCase		)
						# The set of states Alice will prepare.
						_lowerCAmelCase  						=			rng.integers(2			,     size=__lowerCamelCase		)
						# Measurement basis for Bob's qubits.
						_lowerCAmelCase  						=			rng.integers(2			,     size=__lowerCamelCase		)

						# Quantum Circuit to simulate BB84
						_lowerCAmelCase  						=			qiskit.QuantumCircuit(__lowerCamelCase			,     name="""BB84"""		)

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

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

						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(__lowerCamelCase			,     __lowerCamelCase			,     shots=1			,     seed_simulator=__lowerCamelCase		)
						# Returns the result of measurement.
						_lowerCAmelCase  						=			job.result().get_counts(__lowerCamelCase		).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(
						            __lowerCamelCase			,     __lowerCamelCase			,     __lowerCamelCase		)
						        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(__lowerCamelCase		) >= key_len else gen_key.ljust(__lowerCamelCase			,     """0"""		)
						return key


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

						testmod()
