




from __future__ import annotations

import copy
import os
import tempfile
from importlib import import_module
from math import isnan

from transformers import is_tf_available
from transformers.models.auto import get_values
from transformers.testing_utils import _tf_gpu_memory_limit, require_tf, slow

from ..test_modeling_tf_common import ids_tensor


if is_tf_available():
     import numpy as np
     import tensorflow as tf

     from transformers import (
         TF_MODEL_FOR_CAUSAL_LM_MAPPING,
         TF_MODEL_FOR_IMAGE_CLASSIFICATION_MAPPING,
         TF_MODEL_FOR_MASKED_LM_MAPPING,
         TF_MODEL_FOR_MULTIPLE_CHOICE_MAPPING,
         TF_MODEL_FOR_NEXT_SENTENCE_PREDICTION_MAPPING,
         TF_MODEL_FOR_PRETRAINING_MAPPING,
         TF_MODEL_FOR_QUESTION_ANSWERING_MAPPING,
         TF_MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING,
         TF_MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING,
         TF_MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING,
         TFSharedEmbeddings,
     )

     if _tf_gpu_memory_limit is not None:
          __magic_name__           =					tf.config.list_physical_devices('''GPU''')
          for gpu in gpus:
               # Restrict TensorFlow to only allocate x GB of memory on the GPUs
               try:
                    tf.config.set_logical_device_configuration(
                        gpu, [tf.config.LogicalDeviceConfiguration(memory_limit=_tf_gpu_memory_limit)]
                    )
                    __magic_name__           =					tf.config.list_logical_devices('''GPU''')
                    print('''Logical GPUs''', logical_gpus)
               except RuntimeError as e:
                    # Virtual devices must be set before GPUs have been initialized
                    print(e)




@require_tf
class    _SCREAMING_SNAKE_CASE					:
      _A  :						Optional[Any]      		=       None
      _A  :						List[str]      		=       ()
      _A  :						str      		=       ()
      _A  :						Union[str, Any]      		=       True
      _A  :						Any      		=       True
      _A  :						Any      		=       True
      _A  :						List[Any]      		=       False
      def A_     (     self						,		lowerCamelCase						,		lowerCamelCase						,		lowerCamelCase=False	):
          snake_case__  =			copy.deepcopy(lowerCamelCase	)

          if model_class in get_values(lowerCamelCase	):
              snake_case__  =			{
                  k: tf.tile(tf.expand_dims(lowerCamelCase						,		1	)						,		(1, self.model_tester.num_choices) + (1,) * (v.ndim - 1)	)
                  if isinstance(lowerCamelCase						,		tf.Tensor	) and v.ndim > 0
                  else v
                  for k, v in inputs_dict.items()
              }

          if return_labels:
              if model_class in get_values(lowerCamelCase	):
                  snake_case__  =			tf.ones(self.model_tester.batch_size						,		dtype=tf.intaa	)
              elif model_class in get_values(lowerCamelCase	):
                  snake_case__  =			tf.zeros(self.model_tester.batch_size						,		dtype=tf.intaa	)
                  snake_case__  =			tf.zeros(self.model_tester.batch_size						,		dtype=tf.intaa	)
              elif model_class in [
                  *get_values(lowerCamelCase	),
                  *get_values(lowerCamelCase	),
              ]:
                  snake_case__  =			tf.zeros(self.model_tester.batch_size						,		dtype=tf.intaa	)
              elif model_class in get_values(lowerCamelCase	):
                  snake_case__  =			tf.zeros(self.model_tester.batch_size						,		dtype=tf.intaa	)
              elif model_class in [
                  *get_values(lowerCamelCase	),
                  *get_values(lowerCamelCase	),
                  *get_values(lowerCamelCase	),
                  *get_values(lowerCamelCase	),
                  *get_values(lowerCamelCase	),
              ]:
                  snake_case__  =			tf.zeros(
                      (self.model_tester.batch_size, self.model_tester.seq_length)						,		dtype=tf.intaa	)
          return inputs_dict
      @slow
      def A_     (     self	):
          snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()
          for model_class in self.all_model_classes[:2]:
              snake_case__  =			self._prepare_for_class(lowerCamelCase						,		lowerCamelCase	)
              snake_case__  =			model_class(lowerCamelCase	)

              @tf.function
              def run_in_graph_mode():
                  return model(lowerCamelCase	)

              snake_case__  =			run_in_graph_mode()
              self.assertIsNotNone(lowerCamelCase	)
      @slow
      def A_     (     self	):
          snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()
          for model_class in self.all_model_classes[:2]:
              snake_case__  =			self._prepare_for_class(lowerCamelCase						,		lowerCamelCase	)
              snake_case__  =			model_class(lowerCamelCase	)

              @tf.function(experimental_compile=lowerCamelCase	)
              def run_in_graph_mode():
                  return model(lowerCamelCase	)

              snake_case__  =			run_in_graph_mode()
              self.assertIsNotNone(lowerCamelCase	)
      @slow
      def A_     (     self	):
          # This is a copy of the test_keras_fit method, but we use XLA compilation instead of eager
          snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()
          for model_class in self.all_model_classes[:2]:
              snake_case__  =			model_class(lowerCamelCase	)
              if getattr(lowerCamelCase						,		"hf_compute_loss"						,		lowerCamelCase	):
                  # Test that model correctly compute the loss with kwargs
                  snake_case__  =			self._prepare_for_class(inputs_dict.copy()						,		lowerCamelCase						,		return_labels=lowerCamelCase	)
                  # Is there a better way to remove these decoder inputs?
                  snake_case__  =			{
                      key: val
                      for key, val in prepared_for_class.items()
                      if key not in ("head_mask", "decoder_head_mask", "cross_attn_head_mask", "decoder_input_ids")
                  }

                  snake_case__  =			{
                      "labels",
                      "label",
                      "label_ids",
                      "start_positions",
                      "start_position",
                      "end_positions",
                      "end_position",
                      "next_sentence_label",
                  }
                  snake_case__  =			possible_label_cols.intersection(set(lowerCamelCase	)	)
                  self.assertGreater(len(lowerCamelCase	)						,		0						,		msg="No matching label names found!"	)
                  snake_case__  =			{key: val for key, val in prepared_for_class.items() if key in label_names}
                  snake_case__  =			{key: val for key, val in prepared_for_class.items() if key not in label_names}
                  self.assertGreater(len(lowerCamelCase	)						,		0	)

                  # Make sure it works with XLA!
                  model.compile(optimizer=tf.keras.optimizers.SGD(0.0	)						,		jit_compile=lowerCamelCase	)
                  # Make sure the model fits without crashing regardless of where we pass the labels
                  snake_case__  =			model.fit(
                      lowerCamelCase						,		validation_data=lowerCamelCase						,		steps_per_epoch=1						,		validation_steps=1						,		shuffle=lowerCamelCase						,		verbose=0						,		)
                  snake_case__  =			history.history["loss"][0]
                  self.assertTrue(not isnan(lowerCamelCase	)	)
                  snake_case__  =			history.history["val_loss"][0]
                  self.assertTrue(not isnan(lowerCamelCase	)	)

                  # Now test it with separate labels, to make sure that path works in XLA too.
                  snake_case__  =			model_class(lowerCamelCase	)
                  model.compile(optimizer=tf.keras.optimizers.SGD(0.0	)						,		jit_compile=lowerCamelCase	)
                  snake_case__  =			model.fit(
                      lowerCamelCase						,		lowerCamelCase						,		validation_data=(inputs_minus_labels, labels)						,		steps_per_epoch=1						,		validation_steps=1						,		shuffle=lowerCamelCase						,		verbose=0						,		)

                  snake_case__  =			history.history["loss"][0]
                  self.assertTrue(not isnan(lowerCamelCase	)	)
                  snake_case__  =			history.history["val_loss"][0]
                  self.assertTrue(not isnan(lowerCamelCase	)	)
      @slow
      def A_     (     self	):
          snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()
          snake_case__  =			True
          snake_case__  =			True

          if hasattr(lowerCamelCase						,		"use_cache"	):
              snake_case__  =			True

          snake_case__  =			getattr(self.model_tester						,		"encoder_seq_length"						,		self.model_tester.seq_length	)
          snake_case__  =			getattr(self.model_tester						,		"key_length"						,		lowerCamelCase	)

          for model_class in self.all_model_classes[:2]:
              snake_case__  =			self._prepare_for_class(lowerCamelCase						,		lowerCamelCase	)
              snake_case__  =			model_class(lowerCamelCase	)
              model.build()
              snake_case__  =			len(model(lowerCamelCase	)	)

              for key in list(class_inputs_dict.keys()	):
                  # Remove keys not in the serving signature, as the SavedModel will not be compiled to deal with them
                  if key not in model.input_signature:
                      del class_inputs_dict[key]
                  # Check it's a tensor, in case the inputs dict has some bools in it too
                  elif isinstance(class_inputs_dict[key]						,		tf.Tensor	) and class_inputs_dict[key].dtype.is_integer:
                      snake_case__  =			tf.cast(class_inputs_dict[key]						,		tf.intaa	)

              if set(class_inputs_dict.keys()	) != set(model.input_signature.keys()	):
                  continue  # Some models have inputs that the preparation functions don't create, we skip those

              with tempfile.TemporaryDirectory() as tmpdirname:
                  model.save_pretrained(lowerCamelCase						,		saved_model=lowerCamelCase	)
                  snake_case__  =			os.path.join(lowerCamelCase						,		"saved_model"						,		"1"	)
                  snake_case__  =			tf.keras.models.load_model(lowerCamelCase	)
                  snake_case__  =			model(lowerCamelCase	)

                  if self.is_encoder_decoder:
                      snake_case__  =			outputs["encoder_hidden_states"]
                      snake_case__  =			outputs["encoder_attentions"]
                  else:
                      snake_case__  =			outputs["hidden_states"]
                      snake_case__  =			outputs["attentions"]

                  self.assertEqual(len(lowerCamelCase	)						,		lowerCamelCase	)

                  snake_case__  =			getattr(
                      self.model_tester						,		"expected_num_hidden_layers"						,		self.model_tester.num_hidden_layers + 1	)

                  self.assertEqual(len(lowerCamelCase	)						,		lowerCamelCase	)
                  self.assertListEqual(
                      list(output_hidden_states[0].shape[-2:]	)						,		[self.model_tester.seq_length, self.model_tester.hidden_size]						,		)

                  self.assertEqual(len(lowerCamelCase	)						,		self.model_tester.num_hidden_layers	)
                  self.assertListEqual(
                      list(output_attentions[0].shape[-3:]	)						,		[self.model_tester.num_attention_heads, encoder_seq_length, encoder_key_length]						,		)
      @slow
      def A_     (     self	):
          tf.keras.mixed_precision.set_global_policy("mixed_float16"	)

          # try/finally block to ensure subsequent tests run in float32
          try:
              snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()
              for model_class in self.all_model_classes[:2]:
                  snake_case__  =			self._prepare_for_class(lowerCamelCase						,		lowerCamelCase	)
                  snake_case__  =			model_class(lowerCamelCase	)
                  snake_case__  =			model(lowerCamelCase	)

                  self.assertIsNotNone(lowerCamelCase	)
          finally:
              tf.keras.mixed_precision.set_global_policy("float32"	)
      @slow
      def A_     (     self	):
          snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()
          # head_mask and decoder_head_mask has different shapes than other input args
          if "head_mask" in inputs_dict:
              del inputs_dict["head_mask"]
          if "decoder_head_mask" in inputs_dict:
              del inputs_dict["decoder_head_mask"]
          if "cross_attn_head_mask" in inputs_dict:
              del inputs_dict["cross_attn_head_mask"]
          snake_case__  =			{
              module_member
              for model_class in self.all_model_classes
              for module in (import_module(model_class.__module__	),)
              for module_member_name in dir(lowerCamelCase	)
              if module_member_name.endswith("MainLayer"	)
              for module_member in (getattr(lowerCamelCase						,		lowerCamelCase	),)
              if isinstance(lowerCamelCase						,		lowerCamelCase	)
              and tf.keras.layers.Layer in module_member.__bases__
              and getattr(lowerCamelCase						,		"_keras_serializable"						,		lowerCamelCase	)
          }

          for main_layer_class in tf_main_layer_classes:
              # T5MainLayer needs an embed_tokens parameter when called without the inputs_embeds parameter
              if "T5" in main_layer_class.__name__:
                  # Take the same values than in TFT5ModelTester for this shared layer
                  snake_case__  =			TFSharedEmbeddings(self.model_tester.vocab_size						,		self.model_tester.hidden_size						,		name="shared"	)
                  snake_case__  =			False
                  snake_case__  =			main_layer_class(lowerCamelCase						,		embed_tokens=lowerCamelCase	)
              else:
                  snake_case__  =			main_layer_class(lowerCamelCase	)

              snake_case__  =			{
                  name: tf.keras.Input(tensor.shape[1:]						,		dtype=tensor.dtype	) for name, tensor in inputs_dict.items()
              }

              if hasattr(self.model_tester						,		"num_labels"	):
                  snake_case__  =			self.model_tester.num_labels
              else:
                  snake_case__  =			2

              snake_case__  =			tf.data.Dataset.from_tensor_slices(
                  (inputs_dict, np.ones((self.model_tester.batch_size, self.model_tester.seq_length, num_labels, 1)	))	).batch(1	)

              snake_case__  =			main_layer(lowerCamelCase	)[0]
              snake_case__  =			tf.keras.layers.Dense(lowerCamelCase						,		activation="softmax"						,		name="outputs"	)(lowerCamelCase	)
              snake_case__  =			tf.keras.models.Model(inputs=lowerCamelCase						,		outputs=[outputs]	)

              model.compile(loss="binary_crossentropy"						,		optimizer="adam"						,		metrics=["binary_accuracy"]	)
              model.fit(lowerCamelCase						,		epochs=1	)

              with tempfile.TemporaryDirectory() as tmpdirname:
                  snake_case__  =			os.path.join(lowerCamelCase						,		"keras_model.h5"	)
                  model.save(lowerCamelCase	)
                  if "T5" in main_layer_class.__name__:
                      snake_case__  =			tf.keras.models.load_model(
                          lowerCamelCase						,		custom_objects={
                              main_layer_class.__name__: main_layer_class,
                              "TFSharedEmbeddings": TFSharedEmbeddings,
                          }						,		)
                  else:
                      snake_case__  =			tf.keras.models.load_model(
                          lowerCamelCase						,		custom_objects={main_layer_class.__name__: main_layer_class}	)
                  assert isinstance(lowerCamelCase						,		tf.keras.Model	)
                  model(lowerCamelCase	)
      @slow
      def A_     (     self	):
          snake_case__  ,   snake_case__  =			self.model_tester.prepare_config_and_inputs_for_common()

          for model_class in self.all_model_classes[:2]:
              snake_case__  =			model_class(lowerCamelCase	)

              snake_case__  =			copy.deepcopy(lowerCamelCase	)

              if not self.is_encoder_decoder:
                  snake_case__  =			inputs["input_ids"]
                  del inputs["input_ids"]
              else:
                  snake_case__  =			inputs["input_ids"]
                  snake_case__  =			inputs.get("decoder_input_ids"						,		lowerCamelCase	)
                  del inputs["input_ids"]
                  inputs.pop("decoder_input_ids"						,		lowerCamelCase	)

              if not self.is_encoder_decoder:
                  snake_case__  =			model.get_input_embeddings()(lowerCamelCase	)
              else:
                  snake_case__  =			model.get_input_embeddings()(lowerCamelCase	)
                  snake_case__  =			model.get_input_embeddings()(lowerCamelCase	)

              snake_case__  =			self._prepare_for_class(lowerCamelCase						,		lowerCamelCase	)

              @tf.function
              def run_in_graph_mode():
                  return model(lowerCamelCase	)

              snake_case__  =			run_in_graph_mode()
              self.assertIsNotNone(lowerCamelCase	)
      def A_     (     self						,		lowerCamelCase						,		lowerCamelCase	):
          # special tokens cannot be bad tokens
          snake_case__  =			[]
          if model.config.bos_token_id is not None:
              special_tokens.append(model.config.bos_token_id	)
          if model.config.pad_token_id is not None:
              special_tokens.append(model.config.pad_token_id	)
          if model.config.eos_token_id is not None:
              special_tokens.append(model.config.eos_token_id	)

          # create random bad tokens that are not special tokens
          snake_case__  =			[]
          while len(lowerCamelCase	) < num_bad_tokens:
              snake_case__  =			tf.squeeze(ids_tensor((1, 1)						,		self.model_tester.vocab_size	)						,		0	).numpy()[0]
              if token not in special_tokens:
                  bad_tokens.append(lowerCamelCase	)
          return bad_tokens
      def A_     (     self						,		lowerCamelCase	):
          for token_id in output_ids[0].numpy().tolist():
              self.assertGreaterEqual(lowerCamelCase						,		0	)
              self.assertLess(lowerCamelCase						,		self.model_tester.vocab_size	)



      def A_     (     self						,		lowerCamelCase						,		lowerCamelCase	):
          # for all bad word tokens
          for bad_word_ids in bad_words_ids:
              # for all slices in batch
              for generated_ids_slice in generated_ids:
                  # for all word idx
                  for i in range(len(lowerCamelCase	)						,		len(lowerCamelCase	)	):
                      # if tokens match
                      if generated_ids_slice[i - len(lowerCamelCase	) : i] == bad_word_ids:
                          return True
          return False





from collections.abc import Callable
from math import log
from os import name, system
from random import gauss, seed
from typing import TypeVar





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase							):
    seed(1							)
    return [gauss(__lowerCAmelCase      ,						__lowerCAmelCase							) for _ in range(__lowerCAmelCase							)]





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase							):
    return [k for k in range(__lowerCAmelCase							) for _ in range(instance_count[k]							)]





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase							):
    return sum(__lowerCAmelCase							) / instance_count





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase							):
    return instance_count / total_count





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase							):
    snake_case__  =			[]  # An empty list to store all squared differences
    # iterate over number of elements in items
    for i in range(len(__lowerCAmelCase							)							):
        # for loop iterates over number of elements in inner layer of items
        for j in range(len(items[i]							)							):
            # appending squared differences to 'squared_diff' list
            squared_diff.append((items[i][j] - means[i]) ** 2							)

    # one divided by (the number of all instances - number of classes) multiplied by
    # sum of all squared differences
    snake_case__  =			len(__lowerCAmelCase							)  # Number of classes in dataset
    return 1 / (total_count - n_classes) * sum(__lowerCAmelCase							)





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase							):
    snake_case__  =			[]
    # for loop iterates over number of elements in list
    for i in range(len(__lowerCAmelCase							)							):
        # for loop iterates over number of inner items of each element
        for j in range(len(x_items[i]							)							):
            snake_case__  =			[]  # to store all discriminant values of each item as a list
            # for loop iterates over number of classes we have in our dataset
            for k in range(len(__lowerCAmelCase							)							):
                # appending values of discriminants for each class to 'temp' list
                temp.append(
                    x_items[i][j] * (means[k] / variance)
                    - (means[k] ** 2 / (2 * variance))
                    + log(probabilities[k]							)							)
            # appending discriminant values of each item to 'results' list
            results.append(__lowerCAmelCase							)

    return [result.index(max(__lowerCAmelCase							)							) for result in results]





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase							):
    snake_case__  =			sum(1 for i, j in zip(__lowerCAmelCase      ,						__lowerCAmelCase							) if i == j							)
    # percentage of accuracy equals to number of correct predictions divided by number
    # of all data and multiplied by 100
    return (correct / len(__lowerCAmelCase							)) * 100


__magic_name__           =					TypeVar('''num''')





def 		SCREAMING_SNAKE_CASE__      ( __lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase = lambda __lowerCAmelCase							: True      ,						__lowerCAmelCase = None      ,						):
    while True:
        try:
            snake_case__  =			input_type(input(__lowerCAmelCase							).strip() or default							)
            if condition(__lowerCAmelCase							):
                return user_input
            else:
                print(F"""{user_input}: {err_msg}"""							)
                continue
        except ValueError:
            print(
                F"""{user_input}: Incorrect input type, expected {input_type.__name__!r}"""							)





def 		SCREAMING_SNAKE_CASE__      ( ):
    while True:
        print(" Linear Discriminant Analysis ".center(50      ,						"*"							)							)
        print("*" * 50      ,						"\n"							)
        print("First of all we should specify the number of classes that"							)
        print("we want to generate as training dataset"							)
        # Trying to get number of classes
        snake_case__  =			valid_input(
            input_type=__lowerCAmelCase      ,						condition=lambda __lowerCAmelCase							: x > 0      ,						input_msg="Enter the number of classes (Data Groupings): "      ,						err_msg="Number of classes should be positive!"      ,						)

        print("-" * 100							)

        # Trying to get the value of standard deviation
        snake_case__  =			valid_input(
            input_type=__lowerCAmelCase      ,						condition=lambda __lowerCAmelCase							: x >= 0      ,						input_msg=(
                "Enter the value of standard deviation"
                "(Default value is 1.0 for all classes): "
            )      ,						err_msg="Standard deviation should not be negative!"      ,						default="1.0"      ,						)

        print("-" * 100							)

        # Trying to get number of instances in classes and theirs means to generate
        # dataset
        snake_case__  =			[]  # An empty list to store instance counts of classes in dataset
        for i in range(__lowerCAmelCase							):
            snake_case__  =			valid_input(
                input_type=__lowerCAmelCase      ,						condition=lambda __lowerCAmelCase							: x > 0      ,						input_msg=(F"""Enter The number of instances for class_{i+1}: """)      ,						err_msg="Number of instances should be positive!"      ,						)
            counts.append(__lowerCAmelCase							)
        print("-" * 100							)

        # An empty list to store values of user-entered means of classes
        snake_case__  =			[]
        for a in range(__lowerCAmelCase							):
            snake_case__  =			valid_input(
                input_type=__lowerCAmelCase      ,						input_msg=(F"""Enter the value of mean for class_{a+1}: """)      ,						err_msg="This is an invalid value."      ,						)
            user_means.append(__lowerCAmelCase							)
        print("-" * 100							)

        print("Standard deviation: "      ,						__lowerCAmelCase							)
        # print out the number of instances in classes in separated line
        for i, count in enumerate(__lowerCAmelCase      ,						1							):
            print(F"""Number of instances in class_{i} is: {count}"""							)
        print("-" * 100							)

        # print out mean values of classes separated line
        for i, user_mean in enumerate(__lowerCAmelCase      ,						1							):
            print(F"""Mean of class_{i} is: {user_mean}"""							)
        print("-" * 100							)

        # Generating training dataset drawn from gaussian distribution
        snake_case__  =			[
            gaussian_distribution(user_means[j]      ,						__lowerCAmelCase      ,						counts[j]							)
            for j in range(__lowerCAmelCase							)
        ]
        print("Generated Normal Distribution: \n"      ,						__lowerCAmelCase							)
        print("-" * 100							)

        # Generating Ys to detecting corresponding classes
        snake_case__  =			y_generator(__lowerCAmelCase      ,						__lowerCAmelCase							)
        print("Generated Corresponding Ys: \n"      ,						__lowerCAmelCase							)
        print("-" * 100							)

        # Calculating the value of actual mean for each class
        snake_case__  =			[calculate_mean(counts[k]      ,						x[k]							) for k in range(__lowerCAmelCase							)]
        # for loop iterates over number of elements in 'actual_means' list and print
        # out them in separated line
        for i, actual_mean in enumerate(__lowerCAmelCase      ,						1							):
            print(F"""Actual(Real) mean of class_{i} is: {actual_mean}"""							)
        print("-" * 100							)

        # Calculating the value of probabilities for each class
        snake_case__  =			[
            calculate_probabilities(counts[i]      ,						sum(__lowerCAmelCase							)							) for i in range(__lowerCAmelCase							)
        ]

        # for loop iterates over number of elements in 'probabilities' list and print
        # out them in separated line
        for i, probability in enumerate(__lowerCAmelCase      ,						1							):
            print(F"""Probability of class_{i} is: {probability}"""							)
        print("-" * 100							)

        # Calculating the values of variance for each class
        snake_case__  =			calculate_variance(__lowerCAmelCase      ,						__lowerCAmelCase      ,						sum(__lowerCAmelCase							)							)
        print("Variance: "      ,						__lowerCAmelCase							)
        print("-" * 100							)

        # Predicting Y values
        # storing predicted Y values in 'pre_indexes' variable
        snake_case__  =			predict_y_values(__lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase      ,						__lowerCAmelCase							)
        print("-" * 100							)

        # Calculating Accuracy of the model
        print(F"""Accuracy: {accuracy(__lowerCAmelCase      ,						__lowerCAmelCase							)}"""							)
        print("-" * 100							)
        print(" DONE ".center(100      ,						"+"							)							)

        if input("Press any key to restart or 'q' for quit: "							).strip().lower() == "q":
            print("\n" + "GoodBye!".center(100      ,						"-"							) + "\n"							)
            break
        system("cls" if name == "nt" else "clear"							)  # noqa: S605


if __name__ == "__main__":
     main()



