
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:					Optional[int]     =torch.cuda.is_available()
_UpperCamelCase:					List[Any]     ={
    '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 	_a  (					__SCREAMING_SNAKE_CASE					:  Path		,				__SCREAMING_SNAKE_CASE					:  list    ):






  """simple docstring"""




  _lowerCAmelCase						=		'\n'.join(lowerCamelCase_    )
  Path(lowerCamelCase_    ).open('w'    ).writelines(lowerCamelCase_    )


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


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



def 	_a  (					__SCREAMING_SNAKE_CASE					:  int    ):






  """simple docstring"""




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





class 						__lowercase(     SCREAMING_SNAKE_CASE   ):


       """simple docstring"""







       @classmethod
       def SCREAMING_SNAKE_CASE_				(     cls					:			List[str]       )					->   str:
         logging.disable(logging.CRITICAL       )  # remove noisy download output from tracebacks
         return cls



       @slow
       @require_torch_gpu
       def SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   Any:
         _lowerCAmelCase						=		list_models()
         _lowerCAmelCase						=		'sshleifer'
         _lowerCAmelCase						=		[x.modelId for x in model_list if x.modelId.startswith(UpperCAmelCase__       )]
         _lowerCAmelCase						=		['sshleifer/blenderbot-3B', 'sshleifer/blenderbot-90M']
         _lowerCAmelCase						=		[]
         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 SCREAMING_SNAKE_CASE_				(     self					:			int       )					->   List[str]:
         _lowerCAmelCase						=		{'student_encoder_layers': 2, 'student_decoder_layers': 1, 'no_teacher': True}
         self._test_distiller_cli(UpperCAmelCase__       )



       def SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   Any:
         _lowerCAmelCase						=		{
             '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',
         }
         _lowerCAmelCase						=		self._test_distiller_cli(UpperCAmelCase__  ,      check_contents=UpperCAmelCase__       )

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

         _lowerCAmelCase						=		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 SCREAMING_SNAKE_CASE_				(     self					:			Dict       )					->   List[str]:
         _lowerCAmelCase						=		AutoModelForSeqaSeqLM.from_pretrained(UpperCAmelCase__       )
         _lowerCAmelCase	,       _lowerCAmelCase						=		model.dummy_inputs['input_ids'], model.dummy_inputs['attention_mask']
         _lowerCAmelCase						=		torch.tensor([[0, 4, 8, 2], [0, 8, 2, 1]]  ,      dtype=torch.long  ,      device=model.device       )
         _lowerCAmelCase						=		target_ids[:, :-1].contiguous()  # Why this line?
         _lowerCAmelCase						=		target_ids[:, 1:].clone()  # why clone?
         _lowerCAmelCase						=		model(
             UpperCAmelCase__  ,      attention_mask=UpperCAmelCase__  ,      decoder_input_ids=UpperCAmelCase__  ,      labels=UpperCAmelCase__  ,      use_cache=UpperCAmelCase__       ).loss

         _lowerCAmelCase						=		model(UpperCAmelCase__  ,      attention_mask=UpperCAmelCase__  ,      decoder_input_ids=UpperCAmelCase__  ,      use_cache=UpperCAmelCase__       ).logits

         _lowerCAmelCase						=		nn.functional.log_softmax(UpperCAmelCase__  ,      dim=-1       )
         _lowerCAmelCase	,       _lowerCAmelCase						=		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 SCREAMING_SNAKE_CASE_				(     self					:			Optional[Any]       )					->   Dict:
         _lowerCAmelCase						=		{
             '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',
         }
         _lowerCAmelCase						=		self._test_distiller_cli(UpperCAmelCase__  ,      check_contents=UpperCAmelCase__       )
         assert model.model.config.model_type == "mbart"

         _lowerCAmelCase						=		list(Path(model.output_dir       ).glob('*.ckpt'       )       )
         self.assertEqual(1  ,      len(UpperCAmelCase__       )       )
         _lowerCAmelCase						=		list(Path(model.output_dir       ).glob('**/*.bin'       )       )
         _lowerCAmelCase						=		list(Path(model.output_dir       ).glob('best_tfmr/*'       )       )
         assert len(UpperCAmelCase__       ) > 2
         self.assertEqual(len(UpperCAmelCase__       )  ,      2       )



       def SCREAMING_SNAKE_CASE_				(     self					:			str       )					->   Any:
         _lowerCAmelCase						=		{
             '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 SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   Union[str, Any]:
         _lowerCAmelCase						=		{
             'teacher': T5_TINY,
             'student': T5_TINIER,
             'model_name_or_path': T5_TINIER,
             'tokenizer_name': T5_TINIER,
         }
         self._test_distiller_cli(UpperCAmelCase__       )






       def SCREAMING_SNAKE_CASE_				(     self					:			Optional[int]  ,      _lowerCAmelCase					:			Union[str, Any]  ,      _lowerCAmelCase					:			Optional[Any]=True       )					->   str:
         _lowerCAmelCase						=		{
             '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__       )
         _lowerCAmelCase						=		CHEAP_ARGS.copy()
         _lowerCAmelCase						=		make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()       )
         _lowerCAmelCase						=		self.get_auto_remove_tmp_dir()

         args_d.update(data_dir=UpperCAmelCase__  ,      output_dir=UpperCAmelCase__  ,      **UpperCAmelCase__       )
         _lowerCAmelCase						=		distill_main(argparse.Namespace(**UpperCAmelCase__       )       )
         if not check_contents:
           return model
         _lowerCAmelCase						=		os.listdir(UpperCAmelCase__       )
         _lowerCAmelCase						=		{os.path.basename(UpperCAmelCase__       ) for p in contents}
         _lowerCAmelCase						=		[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__       )

         _lowerCAmelCase						=		load_json(model.metrics_save_path       )
         _lowerCAmelCase						=		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__       )
         _lowerCAmelCase						=		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(     SCREAMING_SNAKE_CASE   ):


       """simple docstring"""







       @parameterized.expand(
           [T5_TINY, BART_TINY, MBART_TINY, MARIAN_TINY, FSMT_TINY]  ,      )
       def SCREAMING_SNAKE_CASE_				(     self					:			List[Any]  ,      _lowerCAmelCase					:			List[Any]       )					->   Dict:
         _lowerCAmelCase						=		CHEAP_ARGS.copy()
         _lowerCAmelCase						=		'translation' if model in [MBART_TINY, MARIAN_TINY, FSMT_TINY] else 'summarization'
         _lowerCAmelCase						=		0.1 if task == 'translation' else 0

         _lowerCAmelCase						=		make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()       )
         _lowerCAmelCase						=		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
         _lowerCAmelCase						=		argparse.Namespace(**UpperCAmelCase__       )
         _lowerCAmelCase						=		main(UpperCAmelCase__       )

         _lowerCAmelCase						=		module.model.get_input_embeddings()
         assert not input_embeds.weight.requires_grad
         if model == T5_TINY:
           _lowerCAmelCase						=		module.model.lm_head
           assert not lm_head.weight.requires_grad
           assert (lm_head.weight == input_embeds.weight).all().item()
         elif model == FSMT_TINY:
           _lowerCAmelCase						=		module.model.model
           _lowerCAmelCase						=		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:
           _lowerCAmelCase						=		module.model.model
           _lowerCAmelCase						=		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

         _lowerCAmelCase						=		load_json(module.output_dir / 'text_batch.json'       )
         assert isinstance(UpperCAmelCase__  ,      UpperCAmelCase__       )
         assert len(UpperCAmelCase__       ) >= 4



       def SCREAMING_SNAKE_CASE_				(     self					:			Any       )					->   List[Any]:
         _lowerCAmelCase						=		CHEAP_ARGS.copy()

         _lowerCAmelCase						=		'summarization'
         _lowerCAmelCase						=		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
         _lowerCAmelCase						=		BART_TINY
         _lowerCAmelCase						=		self.get_auto_remove_tmp_dir()
         _lowerCAmelCase						=		args_d.copy()
         args_da.update(
             model_name_or_path=UpperCAmelCase__  ,      output_dir=UpperCAmelCase__  ,      )
         _lowerCAmelCase						=		('encoder_layerdrop', 'decoder_layerdrop', 'dropout', 'attention_dropout')
         for p in extra_model_params:
           _lowerCAmelCase						=		0.5
         _lowerCAmelCase						=		argparse.Namespace(**UpperCAmelCase__       )
         _lowerCAmelCase						=		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
         _lowerCAmelCase						=		T5_TINY
         _lowerCAmelCase						=		self.get_auto_remove_tmp_dir()
         _lowerCAmelCase						=		args_d.copy()
         args_da.update(
             model_name_or_path=UpperCAmelCase__  ,      output_dir=UpperCAmelCase__  ,      )
         _lowerCAmelCase						=		'encoder_layerdrop'
         _lowerCAmelCase						=		0.5
         _lowerCAmelCase						=		argparse.Namespace(**UpperCAmelCase__       )
         with pytest.raises(UpperCAmelCase__       ) as excinfo:
           _lowerCAmelCase						=		main(UpperCAmelCase__       )
         assert str(excinfo.value       ) == F'''model config doesn\'t have a `{unsupported_param}` attribute'''






       def SCREAMING_SNAKE_CASE_				(     self					:			List[str]       )					->   Any:
         _lowerCAmelCase						=		CHEAP_ARGS.copy()

         _lowerCAmelCase						=		'summarization'
         _lowerCAmelCase						=		make_test_data_dir(tmp_dir=self.get_auto_remove_tmp_dir()       )

         _lowerCAmelCase						=		BART_TINY
         _lowerCAmelCase						=		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
         _lowerCAmelCase						=		argparse.ArgumentParser()
         _lowerCAmelCase						=		pl.Trainer.add_argparse_args(UpperCAmelCase__       )
         _lowerCAmelCase						=		SummarizationModule.add_model_specific_args(UpperCAmelCase__  ,      os.getcwd()       )
         _lowerCAmelCase						=		{'--help': True}

         # --help test
         with pytest.raises(UpperCAmelCase__       ) as excinfo:
           with CaptureStdout() as cs:
             _lowerCAmelCase						=		parser.parse_args(UpperCAmelCase__       )
           assert False, "--help is expected to sys.exit"
         assert excinfo.type == SystemExit
         _lowerCAmelCase						=		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
         _lowerCAmelCase						=		'non_existing_scheduler'
         _lowerCAmelCase						=		{F'''--lr_scheduler={unsupported_param}'''}
         with pytest.raises(UpperCAmelCase__       ) as excinfo:
           with CaptureStderr() as cs:
             _lowerCAmelCase						=		parser.parse_args(UpperCAmelCase__       )
           assert False, "invalid argument is expected to sys.exit"
         assert excinfo.type == SystemExit
         _lowerCAmelCase						=		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
         _lowerCAmelCase						=		'cosine'
         _lowerCAmelCase						=		args_d.copy()
         _lowerCAmelCase						=		supported_param
         _lowerCAmelCase						=		argparse.Namespace(**UpperCAmelCase__       )
         _lowerCAmelCase						=		main(UpperCAmelCase__       )
         assert (
             getattr(model.hparams  ,      'lr_scheduler'       ) == supported_param
         ), F'''lr_scheduler={supported_param} shouldn\'t fail'''




"""simple docstring"""






class       lowerCamelCase_		:





				"""simple docstring"""







				def __init__(    self  ):
								SCREAMING_SNAKE_CASE__  				=					[0]
								SCREAMING_SNAKE_CASE__  				=					0



				def 	lowerCAmelCase__		(    self							,		UpperCAmelCase__  ):
								SCREAMING_SNAKE_CASE__  				=					self.__heap[i]
								while i // 2 > 0:
												if self.__heap[i] > self.__heap[i // 2]:
																SCREAMING_SNAKE_CASE__  				=					self.__heap[i // 2]
																SCREAMING_SNAKE_CASE__  				=					temporary
												i //= 2



				def 	lowerCAmelCase__		(    self							,		UpperCAmelCase__  ):
								self.__heap.append(UpperCAmelCase__  )
								self.__size += 1
								self.__swap_up(self.__size  )



				def 	lowerCAmelCase__		(    self							,		UpperCAmelCase__  ):
								while self.__size >= 2 * i:
												if 2 * i + 1 > self.__size:
																SCREAMING_SNAKE_CASE__  				=					2 * i
												else:
																if self.__heap[2 * i] > self.__heap[2 * i + 1]:
																				SCREAMING_SNAKE_CASE__  				=					2 * i
																else:
																				SCREAMING_SNAKE_CASE__  				=					2 * i + 1
												SCREAMING_SNAKE_CASE__  				=					self.__heap[i]
												if self.__heap[i] < self.__heap[bigger_child]:
																SCREAMING_SNAKE_CASE__  				=					self.__heap[bigger_child]
																SCREAMING_SNAKE_CASE__  				=					temporary
												SCREAMING_SNAKE_CASE__  				=					bigger_child



				def 	lowerCAmelCase__		(    self  ):
								SCREAMING_SNAKE_CASE__  				=					self.__heap[1]
								SCREAMING_SNAKE_CASE__  				=					self.__heap[self.__size]
								self.__size -= 1
								self.__heap.pop()
								self.__swap_down(1  )
								return max_value



				@property
				def 	lowerCAmelCase__		(    self  ):
								return self.__heap[1:]






				def __len__(    self  ):
								return self.__size


if __name__ == "__main__":
	import doctest

	doctest.testmod()
	# create an instance of BinaryHeap
	_lowerCamelCase  =	BinaryHeap()
	binary_heap.insert(6)
	binary_heap.insert(10)
	binary_heap.insert(15)
	binary_heap.insert(12)
	# pop root(max-values because it is max heap)
	print(binary_heap.pop())  # 15
	print(binary_heap.pop())  # 12
	# get the list and size after operations
	print(binary_heap.get_list)
	print(len(binary_heap))
