


'''simple docstring'''


import argparse
import logging
import os
import sys
import tempfile
from pathlib import Path

import lightning_base
import pytest
import pytorch_lightning as pl
import torch
from convert_pl_checkpoint_to_hf import convert_pl_to_hf
from distillation import distill_main
from finetune import SummarizationModule, main
from huggingface_hub import list_models
from parameterized import parameterized
from run_eval import generate_summaries_or_translations
from torch import nn

from transformers import AutoConfig, AutoModelForSeqaSeqLM
from transformers.testing_utils import CaptureStderr, CaptureStdout, TestCasePlus, require_torch_gpu, slow
from utils import label_smoothed_nll_loss, lmap, load_json


logging.basicConfig(level=logging.DEBUG)

UpperCAmelCase_	:     int							     =	logging.getLogger()
UpperCAmelCase_	:     Dict							     =	torch.cuda.is_available()
UpperCAmelCase_	:     int							     =	{
    "max_tokens_per_batch": None,
    "supervise_forward": True,
    "normalize_hidden": True,
    "label_smoothing": 0.2,
    "eval_max_gen_length": None,
    "eval_beams": 1,
    "val_metric": "loss",
    "save_top_k": 1,
    "adafactor": True,
    "early_stopping_patience": 2,
    "logger_name": "default",
    "length_penalty": 0.5,
    "cache_dir": "",
    "task": "summarization",
    "num_workers": 2,
    "alpha_hid": 0,
    "freeze_embeds": True,
    "enc_only": False,
    "tgt_suffix": "",
    "resume_from_checkpoint": None,
    "sortish_sampler": True,
    "student_decoder_layers": 1,
    "val_check_interval": 1.0,
    "output_dir": "",
    "fp16": False,  # TODO(SS): set this to CUDA_AVAILABLE if ci installs apex or start using native amp
    "no_teacher": False,
    "fp16_opt_level": "O1",
    "gpus": 1 if CUDA_AVAILABLE else 0,
    "n_tpu_cores": 0,
    "max_grad_norm": 1.0,
    "do_train": True,
    "do_predict": True,
    "accumulate_grad_batches": 1,
    "server_ip": "",
    "server_port": "",
    "seed": 42,
    "model_name_or_path": "sshleifer/bart-tiny-random",
    "config_name": "",
    "tokenizer_name": "facebook/bart-large",
    "do_lower_case": False,
    "learning_rate": 0.3,
    "lr_scheduler": "linear",
    "weight_decay": 0.0,
    "adam_epsilon": 1E-08,
    "warmup_steps": 0,
    "max_epochs": 1,
    "train_batch_size": 2,
    "eval_batch_size": 2,
    "max_source_length": 12,
    "max_target_length": 12,
    "val_max_target_length": 12,
    "test_max_target_length": 12,
    "fast_dev_run": False,
    "no_cache": False,
    "n_train": -1,
    "n_val": -1,
    "n_test": -1,
    "student_encoder_layers": 1,
    "freeze_encoder": False,
    "auto_scale_batch_size": False,
    "overwrite_output_dir": False,
    "student": None,
}







def     snake_case_     (						SCREAMING_SNAKE_CASE__							,   SCREAMING_SNAKE_CASE__  ):







				"""simple docstring"""





				_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   '''\n'''.join(snake_case_  )
				Path(snake_case_  ).open("""w"""  ).writelines(snake_case_  )


UpperCAmelCase_	:     Any							     =	[" Sam ate lunch today.", "Sams lunch ingredients."]
UpperCAmelCase_	:     List[str]							     =	["A very interesting story about what I ate for lunch.", "Avocado, celery, turkey, coffee"]
UpperCAmelCase_	:     Optional[Any]							     =	"patrickvonplaten/t5-tiny-random"
UpperCAmelCase_	:     int							     =	"sshleifer/t5-tinier-random"
UpperCAmelCase_	:     Any							     =	"sshleifer/bart-tiny-random"
UpperCAmelCase_	:     List[Any]							     =	"sshleifer/tiny-mbart"
UpperCAmelCase_	:     Optional[Any]							     =	"sshleifer/tiny-marian-en-de"
UpperCAmelCase_	:     Tuple							     =	"stas/tiny-wmt19-en-de"


UpperCAmelCase_	:     Dict							     =	logging.StreamHandler(sys.stdout)
logger.addHandler(stream_handler)
logging.disable(logging.CRITICAL)  # remove noisy download output from tracebacks







def     snake_case_     (						SCREAMING_SNAKE_CASE__  ):







				"""simple docstring"""





				for split in ["train", "val", "test"]:
								_dump_articles(os.path.join(snake_case_							,   f"""{split}.source"""  )							,   snake_case_  )
								_dump_articles(os.path.join(snake_case_							,   f"""{split}.target"""  )							,   snake_case_  )
				return tmp_dir





class 					lowercase__						(		UpperCamelCase_      ):





							'''simple docstring'''


							@classmethod
							def UpperCAmelCase_			(					cls						):
											logging.disable(logging.CRITICAL						)  # remove noisy download output from tracebacks
											return cls






							@slow
							@require_torch_gpu
							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   list_models()
											_SCREAMING_SNAKE_CASE				: List[Any]  	=   '''sshleifer'''
											_SCREAMING_SNAKE_CASE				: Tuple  	=   [x.modelId for x in model_list if x.modelId.startswith(__UpperCamelCase						)]
											_SCREAMING_SNAKE_CASE				: str  	=   ['''sshleifer/blenderbot-3B''', '''sshleifer/blenderbot-90M''']
											_SCREAMING_SNAKE_CASE				: Any  	=   []
											for m in model_ids:
															if m in allowed_to_be_broken:
																			continue
															try:
																			AutoConfig.from_pretrained(__UpperCamelCase						)
															except Exception:
																			failures.append(__UpperCamelCase						)
											assert not failures, f"""The following models could not be loaded through AutoConfig: {failures}"""






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   {'''student_encoder_layers''': 2, '''student_decoder_layers''': 1, '''no_teacher''': True}
											self._test_distiller_cli(__UpperCamelCase						)






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   {
											    '''student_encoder_layers''': 2,
											    '''student_decoder_layers''': 1,
											    '''max_epochs''': 4,
											    '''val_check_interval''': 0.25,
											    '''alpha_hid''': 2.0,
											    '''model_name_or_path''': '''IGNORE_THIS_IT_DOESNT_GET_USED''',
											}
											_SCREAMING_SNAKE_CASE				: int  	=   self._test_distiller_cli(__UpperCamelCase					,      check_contents=__UpperCamelCase						)

											_SCREAMING_SNAKE_CASE				: Any  	=   list(Path(model.output_dir						).glob("""*.ckpt"""						)						)
											self.assertEqual(1					,      len(__UpperCamelCase						)						)
											_SCREAMING_SNAKE_CASE				: int  	=   list(Path(model.output_dir						).glob("""**/*.bin"""						)						)
											self.assertEqual(len(__UpperCamelCase						)					,      2						)
											_SCREAMING_SNAKE_CASE				: Dict  	=   lmap(str.strip					,      Path(model.hparams.data_dir						).joinpath("""test.source"""						).open().readlines()						)
											_SCREAMING_SNAKE_CASE				: int  	=   tempfile.mktemp()  # XXX: not being cleaned up
											generate_summaries_or_translations(__UpperCamelCase					,      __UpperCamelCase					,      str(model.output_dir / """best_tfmr"""						)						)
											self.assertTrue(Path(__UpperCamelCase						).exists()						)

											_SCREAMING_SNAKE_CASE				: int  	=   self.get_auto_remove_tmp_dir()
											convert_pl_to_hf(ckpts[0]					,      transformer_ckpts[0].parent					,      __UpperCamelCase						)
											assert os.path.exists(os.path.join(__UpperCamelCase					,      """pytorch_model.bin"""						)						)






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: int  	=   AutoModelForSeqaSeqLM.from_pretrained(__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: int  	=   model.dummy_inputs['''input_ids'''], model.dummy_inputs['''attention_mask''']
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   torch.tensor([[0, 4, 8, 2], [0, 8, 2, 1]]					,      dtype=torch.long					,      device=model.device						)
											_SCREAMING_SNAKE_CASE				: int  	=   target_ids[:, :-1].contiguous()  # Why this line?
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   target_ids[:, 1:].clone()  # why clone?
											_SCREAMING_SNAKE_CASE				: str  	=   model(
											    __UpperCamelCase					,      attention_mask=__UpperCamelCase					,      decoder_input_ids=__UpperCamelCase					,      labels=__UpperCamelCase					,      use_cache=__UpperCamelCase						).loss

											_SCREAMING_SNAKE_CASE				: int  	=   model(__UpperCamelCase					,      attention_mask=__UpperCamelCase					,      decoder_input_ids=__UpperCamelCase					,      use_cache=__UpperCamelCase						).logits

											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   nn.functional.log_softmax(__UpperCamelCase					,      dim=-1						)
											_SCREAMING_SNAKE_CASE				: Dict  	=   label_smoothed_nll_loss(
											    __UpperCamelCase					,      __UpperCamelCase					,      0.1					,      ignore_index=model.config.pad_token_id						)
											with self.assertRaises(__UpperCamelCase						):
															# TODO: understand why this breaks
															self.assertEqual(__UpperCamelCase					,      __UpperCamelCase						)






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: Tuple  	=   {
											    '''student_encoder_layers''': 2,
											    '''student_decoder_layers''': 1,
											    '''num_train_epochs''': 4,
											    '''val_check_interval''': 0.25,
											    '''alpha_hid''': 2.0,
											    '''task''': '''translation''',
											    '''model_name_or_path''': '''IGNORE_THIS_IT_DOESNT_GET_USED''',
											    '''tokenizer_name''': MBART_TINY,
											    '''teacher''': MBART_TINY,
											    '''src_lang''': '''en_XX''',
											    '''tgt_lang''': '''ro_RO''',
											}
											_SCREAMING_SNAKE_CASE				: int  	=   self._test_distiller_cli(__UpperCamelCase					,      check_contents=__UpperCamelCase						)
											assert model.model.config.model_type == "mbart"

											_SCREAMING_SNAKE_CASE				: List[Any]  	=   list(Path(model.output_dir						).glob("""*.ckpt"""						)						)
											self.assertEqual(1					,      len(__UpperCamelCase						)						)
											_SCREAMING_SNAKE_CASE				: List[Any]  	=   list(Path(model.output_dir						).glob("""**/*.bin"""						)						)
											_SCREAMING_SNAKE_CASE				: int  	=   list(Path(model.output_dir						).glob("""best_tfmr/*"""						)						)
											assert len(__UpperCamelCase						) > 2
											self.assertEqual(len(__UpperCamelCase						)					,      2						)






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: str  	=   {
											    '''student_encoder_layers''': 1,
											    '''student_decoder_layers''': 1,
											    '''alpha_hid''': 2.0,
											    '''teacher''': T5_TINY,
											    '''model_name_or_path''': T5_TINY,
											    '''tokenizer_name''': T5_TINY,
											}
											self._test_distiller_cli(__UpperCamelCase						)






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: int  	=   {
											    '''teacher''': T5_TINY,
											    '''student''': T5_TINIER,
											    '''model_name_or_path''': T5_TINIER,
											    '''tokenizer_name''': T5_TINIER,
											}
											self._test_distiller_cli(__UpperCamelCase						)






							def UpperCAmelCase_			(					self					,      __snake_case					,      __snake_case=True						):
											_SCREAMING_SNAKE_CASE				: Tuple  	=   {
											    '''label_smoothing''': 0.0,
											    '''early_stopping_patience''': -1,
											    '''train_batch_size''': 1,
											    '''eval_batch_size''': 2,
											    '''max_epochs''': 2,
											    '''alpha_mlm''': 0.2,
											    '''alpha_ce''': 0.8,
											    '''do_predict''': True,
											    '''model_name_or_path''': '''sshleifer/tinier_bart''',
											    '''teacher''': CHEAP_ARGS['''model_name_or_path'''],
											    '''val_check_interval''': 0.5,
											}
											default_updates.update(__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: dict  	=   CHEAP_ARGS.copy()
											_SCREAMING_SNAKE_CASE				: str  	=   make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()						)
											_SCREAMING_SNAKE_CASE				: Any  	=   self.get_auto_remove_tmp_dir()

											args_d.update(data_dir=__UpperCamelCase					,      output_dir=__UpperCamelCase					,      **__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: List[str]  	=   distill_main(argparse.Namespace(**__UpperCamelCase						)						)
											if not check_contents:
															return model
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   os.listdir(__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   {os.path.basename(__UpperCamelCase						) for p in contents}
											_SCREAMING_SNAKE_CASE				: int  	=   [p for p in contents if p.endswith("""ckpt"""						)]
											assert len(__UpperCamelCase						) > 0

											self.assertIn("""test_generations.txt"""					,      __UpperCamelCase						)
											self.assertIn("""test_results.txt"""					,      __UpperCamelCase						)

											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   load_json(model.metrics_save_path						)
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   metrics['''val'''][-1]
											self.assertGreaterEqual(last_step_stats["""val_avg_gen_time"""]					,      0.01						)
											self.assertGreaterEqual(1.0					,      last_step_stats["""val_avg_gen_time"""]						)
											self.assertIsInstance(last_step_stats[f"""val_avg_{model.val_metric}"""]					,      __UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   int(args_d["""max_epochs"""] * (1 / args_d["""val_check_interval"""]) + 1						)
											self.assertEqual(len(metrics["""val"""]						)					,      __UpperCamelCase						)
											self.assertEqual(len(metrics["""test"""]						)					,      1						)
											return model





class 					lowercase__						(		UpperCamelCase_      ):





							'''simple docstring'''


							@parameterized.expand(
							    [T5_TINY, BART_TINY, MBART_TINY, MARIAN_TINY, FSMT_TINY]					,      )
							def UpperCAmelCase_			(					self					,      __snake_case						):
											_SCREAMING_SNAKE_CASE				: dict  	=   CHEAP_ARGS.copy()
											_SCREAMING_SNAKE_CASE				: List[Any]  	=   '''translation''' if model in [MBART_TINY, MARIAN_TINY, FSMT_TINY] else '''summarization'''
											_SCREAMING_SNAKE_CASE				: List[Any]  	=   0.1 if task == '''translation''' else 0

											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()						)
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   self.get_auto_remove_tmp_dir()
											args_d.update(
											    data_dir=__UpperCamelCase					,      model_name_or_path=__UpperCamelCase					,      tokenizer_name=__UpperCamelCase					,      train_batch_size=2					,      eval_batch_size=2					,      output_dir=__UpperCamelCase					,      do_predict=__UpperCamelCase					,      task=__UpperCamelCase					,      src_lang="""en_XX"""					,      tgt_lang="""ro_RO"""					,      freeze_encoder=__UpperCamelCase					,      freeze_embeds=__UpperCamelCase					,      )
											assert "n_train" in args_d
											_SCREAMING_SNAKE_CASE				: Tuple  	=   argparse.Namespace(**__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   main(__UpperCamelCase						)

											_SCREAMING_SNAKE_CASE				: List[str]  	=   module.model.get_input_embeddings()
											assert not input_embeds.weight.requires_grad
											if model == T5_TINY:
															_SCREAMING_SNAKE_CASE				: Optional[int]  	=   module.model.lm_head
															assert not lm_head.weight.requires_grad
															assert (lm_head.weight == input_embeds.weight).all().item()
											elif model == FSMT_TINY:
															_SCREAMING_SNAKE_CASE				: str  	=   module.model.model
															_SCREAMING_SNAKE_CASE				: Optional[int]  	=   fsmt.decoder.embed_positions
															assert not embed_pos.weight.requires_grad
															assert not fsmt.decoder.embed_tokens.weight.requires_grad
															# check that embeds are not the same
															assert fsmt.decoder.embed_tokens != fsmt.encoder.embed_tokens
											else:
															_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   module.model.model
															_SCREAMING_SNAKE_CASE				: List[Any]  	=   bart.decoder.embed_positions
															assert not embed_pos.weight.requires_grad
															assert not bart.shared.weight.requires_grad
															# check that embeds are the same
															assert bart.decoder.embed_tokens == bart.encoder.embed_tokens
															assert bart.decoder.embed_tokens == bart.shared

											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   load_json(module.output_dir / """text_batch.json"""						)
											assert isinstance(__UpperCamelCase					,      __UpperCamelCase						)
											assert len(__UpperCamelCase						) >= 4






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: dict  	=   CHEAP_ARGS.copy()

											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   '''summarization'''
											_SCREAMING_SNAKE_CASE				: int  	=   make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()						)

											args_d.update(
											    data_dir=__UpperCamelCase					,      tokenizer_name=__UpperCamelCase					,      train_batch_size=2					,      eval_batch_size=2					,      do_predict=__UpperCamelCase					,      task=__UpperCamelCase					,      src_lang="""en_XX"""					,      tgt_lang="""ro_RO"""					,      freeze_encoder=__UpperCamelCase					,      freeze_embeds=__UpperCamelCase					,      )

											# test models whose config includes the extra_model_args
											_SCREAMING_SNAKE_CASE				: int  	=   BART_TINY
											_SCREAMING_SNAKE_CASE				: Tuple  	=   self.get_auto_remove_tmp_dir()
											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   args_d.copy()
											args_da.update(
											    model_name_or_path=__UpperCamelCase					,      output_dir=__UpperCamelCase					,      )
											_SCREAMING_SNAKE_CASE				: str  	=   ('''encoder_layerdrop''', '''decoder_layerdrop''', '''dropout''', '''attention_dropout''')
											for p in extra_model_params:
															_SCREAMING_SNAKE_CASE				: Any  	=   0.5
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   argparse.Namespace(**__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: Optional[Any]  	=   main(__UpperCamelCase						)
											for p in extra_model_params:
															assert getattr(model.config					,      __UpperCamelCase						) == 0.5, f"""failed to override the model config for param {p}"""

											# test models whose config doesn't include the extra_model_args
											_SCREAMING_SNAKE_CASE				: Dict  	=   T5_TINY
											_SCREAMING_SNAKE_CASE				: Any  	=   self.get_auto_remove_tmp_dir()
											_SCREAMING_SNAKE_CASE				: Dict  	=   args_d.copy()
											args_da.update(
											    model_name_or_path=__UpperCamelCase					,      output_dir=__UpperCamelCase					,      )
											_SCREAMING_SNAKE_CASE				: Dict  	=   '''encoder_layerdrop'''
											_SCREAMING_SNAKE_CASE				: Any  	=   0.5
											_SCREAMING_SNAKE_CASE				: str  	=   argparse.Namespace(**__UpperCamelCase						)
											with pytest.raises(__UpperCamelCase						) as excinfo:
															_SCREAMING_SNAKE_CASE				: List[Any]  	=   main(__UpperCamelCase						)
											assert str(excinfo.value						) == f"""model config doesn\'t have a `{unsupported_param}` attribute"""






							def UpperCAmelCase_			(					self						):
											_SCREAMING_SNAKE_CASE				: dict  	=   CHEAP_ARGS.copy()

											_SCREAMING_SNAKE_CASE				: Tuple  	=   '''summarization'''
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()						)

											_SCREAMING_SNAKE_CASE				: List[str]  	=   BART_TINY
											_SCREAMING_SNAKE_CASE				: Tuple  	=   self.get_auto_remove_tmp_dir()

											args_d.update(
											    data_dir=__UpperCamelCase					,      model_name_or_path=__UpperCamelCase					,      output_dir=__UpperCamelCase					,      tokenizer_name=__UpperCamelCase					,      train_batch_size=2					,      eval_batch_size=2					,      do_predict=__UpperCamelCase					,      task=__UpperCamelCase					,      src_lang="""en_XX"""					,      tgt_lang="""ro_RO"""					,      freeze_encoder=__UpperCamelCase					,      freeze_embeds=__UpperCamelCase					,      )

											# emulate finetune.py
											_SCREAMING_SNAKE_CASE				: str  	=   argparse.ArgumentParser()
											_SCREAMING_SNAKE_CASE				: List[Any]  	=   pl.Trainer.add_argparse_args(__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: Any  	=   SummarizationModule.add_model_specific_args(__UpperCamelCase					,      os.getcwd()						)
											_SCREAMING_SNAKE_CASE				: Optional[int]  	=   {'''--help''': True}

											# --help test
											with pytest.raises(__UpperCamelCase						) as excinfo:
															with CaptureStdout() as cs:
																			_SCREAMING_SNAKE_CASE				: str  	=   parser.parse_args(__UpperCamelCase						)
															assert False, "--help is expected to sys.exit"
											assert excinfo.type == SystemExit
											_SCREAMING_SNAKE_CASE				: List[Any]  	=   lightning_base.arg_to_scheduler_metavar
											assert expected in cs.out, "--help is expected to list the supported schedulers"

											# --lr_scheduler=non_existing_scheduler test
											_SCREAMING_SNAKE_CASE				: int  	=   '''non_existing_scheduler'''
											_SCREAMING_SNAKE_CASE				: int  	=   {f"""--lr_scheduler={unsupported_param}"""}
											with pytest.raises(__UpperCamelCase						) as excinfo:
															with CaptureStderr() as cs:
																			_SCREAMING_SNAKE_CASE				: int  	=   parser.parse_args(__UpperCamelCase						)
															assert False, "invalid argument is expected to sys.exit"
											assert excinfo.type == SystemExit
											_SCREAMING_SNAKE_CASE				: Dict  	=   f"""invalid choice: \'{unsupported_param}\'"""
											assert expected in cs.err, f"""should have bailed on invalid choice of scheduler {unsupported_param}"""

											# --lr_scheduler=existing_scheduler test
											_SCREAMING_SNAKE_CASE				: Any  	=   '''cosine'''
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   args_d.copy()
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   supported_param
											_SCREAMING_SNAKE_CASE				: str  	=   argparse.Namespace(**__UpperCamelCase						)
											_SCREAMING_SNAKE_CASE				: Union[str, Any]  	=   main(__UpperCamelCase						)
											assert (
											    getattr(model.hparams					,      """lr_scheduler"""						) == supported_param
											), f"""lr_scheduler={supported_param} shouldn\'t fail"""








'''simple docstring'''


def     snake_case_     (						SCREAMING_SNAKE_CASE__							,   SCREAMING_SNAKE_CASE__  ):







				"""simple docstring"""





				return (input_a, input_a).count(0  ) % 2







def     snake_case_     (						):







				"""simple docstring"""





				assert xor_gate(0							,   0  ) == 0
				assert xor_gate(0							,   1  ) == 1
				assert xor_gate(1							,   0  ) == 1
				assert xor_gate(1							,   1  ) == 0


if __name__ == "__main__":
				print(xor_gate(0, 0))
				print(xor_gate(0, 1))




