






import inspect
import os
from argparse import ArgumentParser, Namespace
from importlib import import_module

import huggingface_hub
import numpy as np
from packaging import version

from .. import (
    FEATURE_EXTRACTOR_MAPPING,
    IMAGE_PROCESSOR_MAPPING,
    PROCESSOR_MAPPING,
    TOKENIZER_MAPPING,
    AutoConfig,
    AutoFeatureExtractor,
    AutoImageProcessor,
    AutoProcessor,
    AutoTokenizer,
    is_datasets_available,
    is_tf_available,
    is_torch_available,
)
from ..utils import TF2_WEIGHTS_INDEX_NAME, TF2_WEIGHTS_NAME, logging
from . import BaseTransformersCLICommand


if is_tf_available():
		import tensorflow as tf

		tf.config.experimental.enable_tensor_float_aa_execution(False)

if is_torch_available():
		import torch

if is_datasets_available():
		from datasets import load_dataset


__UpperCAmelCase										=		5E-5  # larger error tolerance than in our internal tests, to avoid flaky user-facing errors




def   lowercase__   (  __snake_case					:							Namespace						):


			'''simple docstring'''


			return PTtoTFCommand(
			    args.model_name  , args.local_dir  , args.max_error  , args.new_weights  , args.no_pr  , args.push  , args.extra_commit_description  , args.override_model_class  , )






class 						lowerCamelCase   (_snake_case    ):







		'''simple docstring'''



		@staticmethod
		def       __UpperCAmelCase    (							_UpperCamelCase     )			->							Union[str, Any]:
					UpperCAmelCase_					:   List[str]   =		parser.add_parser(
					    'pt-to-tf'       ,	help=(
					        'CLI tool to run convert a transformers model from a PyTorch checkpoint to a TensorFlow checkpoint.'
					        ' Can also be used to validate existing weights without opening PRs, with --no-pr.'
					    )       ,	)
					train_parser.add_argument(
					    '--model-name'       ,	type=_UpperCamelCase       ,	required=_UpperCamelCase       ,	help='The model name, including owner/organization, as seen on the hub.'       ,	)
					train_parser.add_argument(
					    '--local-dir'       ,	type=_UpperCamelCase       ,	default=''       ,	help='Optional local directory of the model repository. Defaults to /tmp/{model_name}'       ,	)
					train_parser.add_argument(
					    '--max-error'       ,	type=_UpperCamelCase       ,	default=_UpperCamelCase       ,	help=(
					        f"Maximum error tolerance. Defaults to {MAX_ERROR}. This flag should be avoided, use at your own risk."
					    )       ,	)
					train_parser.add_argument(
					    '--new-weights'       ,	action='store_true'       ,	help='Optional flag to create new TensorFlow weights, even if they already exist.'       ,	)
					train_parser.add_argument(
					    '--no-pr'       ,	action='store_true'       ,	help='Optional flag to NOT open a PR with converted weights.'     )
					train_parser.add_argument(
					    '--push'       ,	action='store_true'       ,	help='Optional flag to push the weights directly to `main` (requires permissions)'       ,	)
					train_parser.add_argument(
					    '--extra-commit-description'       ,	type=_UpperCamelCase       ,	default=''       ,	help='Optional additional commit description to use when opening a PR (e.g. to tag the owner).'       ,	)
					train_parser.add_argument(
					    '--override-model-class'       ,	type=_UpperCamelCase       ,	default=_UpperCamelCase       ,	help='If you think you know better than the auto-detector, you can specify the model class here. '
					    'Can be either an AutoModel class or a specific model class like BertForSequenceClassification.'       ,	)
					train_parser.set_defaults(func=_UpperCamelCase     )



		@staticmethod
		def       __UpperCAmelCase    (							_UpperCamelCase       ,	_UpperCamelCase     )			->							str:
					UpperCAmelCase_					:   str   =		set(pt_outputs.keys()     )
					UpperCAmelCase_					:   int   =		set(tf_outputs.keys()     )
					if pt_out_attrs != tf_out_attrs:
								raise ValueError(
								    f"The model outputs have different attributes, aborting. (Pytorch: {pt_out_attrs}, TensorFlow:"
								    f" {tf_out_attrs})"     )

					# 2. For each output attribute, computes the difference
					def _find_pt_tf_differences(_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase=""     ):
								# If the current attribute is a tensor, it is a leaf and we make the comparison. Otherwise, we will dig in
								# recursivelly, keeping the name of the attribute.
								if isinstance(_UpperCamelCase       ,	torch.Tensor     ):
											UpperCAmelCase_					:   List[Any]   =		np.max(np.abs(pt_out.numpy() - tf_out.numpy()     )     )
											UpperCAmelCase_					:   str   =		tensor_difference
								else:
											UpperCAmelCase_					:   Dict   =		attr_name
											for i, pt_item in enumerate(_UpperCamelCase     ):
														# If it is a named attribute, we keep the name. Otherwise, just its index.
														if isinstance(_UpperCamelCase       ,	_UpperCamelCase     ):
																	UpperCAmelCase_					:   Tuple   =		root_name + pt_item
																	UpperCAmelCase_					:   Dict   =		tf_out[pt_item]
																	UpperCAmelCase_					:   List[str]   =		pt_out[pt_item]
														else:
																	UpperCAmelCase_					:   Optional[Any]   =		root_name + f"[{i}]"
																	UpperCAmelCase_					:   List[str]   =		tf_out[i]
														UpperCAmelCase_					:   List[Any]   =		_find_pt_tf_differences(_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase     )

								return differences

					return _find_pt_tf_differences(_UpperCamelCase       ,	_UpperCamelCase       ,	{}     )



		def __init__(							self       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	*_UpperCamelCase       ,	)			->							str:
					UpperCAmelCase_					:   str   =		logging.get_logger('transformers-cli/pt_to_tf'     )
					UpperCAmelCase_					:   Any   =		model_name
					UpperCAmelCase_					:   Union[str, Any]   =		local_dir if local_dir else os.path.join('/tmp'       ,	_UpperCamelCase     )
					UpperCAmelCase_					:   Dict   =		max_error
					UpperCAmelCase_					:   str   =		new_weights
					UpperCAmelCase_					:   Optional[Any]   =		no_pr
					UpperCAmelCase_					:   Any   =		push
					UpperCAmelCase_					:   int   =		extra_commit_description
					UpperCAmelCase_					:   str   =		override_model_class



		def       __UpperCAmelCase    (							self       ,	_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase     )			->							List[str]:

					def _get_audio_input():
								UpperCAmelCase_					:   Optional[int]   =		load_dataset('hf-internal-testing/librispeech_asr_dummy'       ,	'clean'       ,	split='validation'     )
								UpperCAmelCase_					:   Union[str, Any]   =		ds.sort('id'     ).select(range(2     )     )[:2]['audio']
								UpperCAmelCase_					:   Optional[Any]   =		[x['array'] for x in speech_samples]
								return raw_samples

					UpperCAmelCase_					:   Tuple   =		type(pt_model.config     )
					if model_config_class in PROCESSOR_MAPPING:
								UpperCAmelCase_					:   List[Any]   =		AutoProcessor.from_pretrained(self._local_dir     )
								if model_config_class in TOKENIZER_MAPPING and processor.tokenizer.pad_token is None:
											UpperCAmelCase_					:   Dict   =		processor.tokenizer.eos_token
					elif model_config_class in IMAGE_PROCESSOR_MAPPING:
								UpperCAmelCase_					:   List[str]   =		AutoImageProcessor.from_pretrained(self._local_dir     )
					elif model_config_class in FEATURE_EXTRACTOR_MAPPING:
								UpperCAmelCase_					:   Tuple   =		AutoFeatureExtractor.from_pretrained(self._local_dir     )
					elif model_config_class in TOKENIZER_MAPPING:
								UpperCAmelCase_					:   int   =		AutoTokenizer.from_pretrained(self._local_dir     )
								if processor.pad_token is None:
											UpperCAmelCase_					:   Tuple   =		processor.eos_token
					else:
								raise ValueError(f"Unknown data processing type (model config type: {model_config_class})"     )

					UpperCAmelCase_					:   List[Any]   =		set(inspect.signature(pt_model.forward     ).parameters.keys()     )
					UpperCAmelCase_					:   List[Any]   =		{}
					if "input_ids" in model_forward_signature:
								processor_inputs.update(
								    {
								        'text': ['Hi there!', 'I am a batch with more than one row and different input lengths.'],
								        'padding': True,
								        'truncation': True,
								    }     )
					if "pixel_values" in model_forward_signature:
								UpperCAmelCase_					:   Union[str, Any]   =		load_dataset('cifar10'       ,	'plain_text'       ,	split='test'     )[:2]['img']
								processor_inputs.update({'images': sample_images}     )
					if "input_features" in model_forward_signature:
								UpperCAmelCase_					:   str   =		inspect.signature(processor.feature_extractor     ).parameters
								# Pad to the largest input length by default but take feature extractor default
								# padding value if it exists e.g. "max_length" and is not False or None
								if "padding" in feature_extractor_signature:
											UpperCAmelCase_					:   List[Any]   =		feature_extractor_signature['padding'].default
											if default_strategy is not False and default_strategy is not None:
														UpperCAmelCase_					:   Optional[Any]   =		default_strategy
											else:
														UpperCAmelCase_					:   Any   =		True
								else:
											UpperCAmelCase_					:   Optional[Any]   =		True
								processor_inputs.update({'audio': _get_audio_input(), 'padding': padding_strategy}     )
					if "input_values" in model_forward_signature:  # Wav2Vec2 audio input
								processor_inputs.update({'audio': _get_audio_input(), 'padding': True}     )
					UpperCAmelCase_					:   Optional[Any]   =		processor(**_UpperCamelCase       ,	return_tensors='pt'     )
					UpperCAmelCase_					:   Union[str, Any]   =		processor(**_UpperCamelCase       ,	return_tensors='tf'     )

					# Extra input requirements, in addition to the input modality
					if (
					    config.is_encoder_decoder
					    or (hasattr(_UpperCamelCase       ,	'encoder'     ) and hasattr(_UpperCamelCase       ,	'decoder'     ))
					    or "decoder_input_ids" in tf_dummy_inputs
					):
								UpperCAmelCase_					:   Optional[Any]   =		np.asarray([[1], [1]]       ,	dtype=_UpperCamelCase     ) * (pt_model.config.decoder_start_token_id or 0)
								pt_input.update({'decoder_input_ids': torch.tensor(_UpperCamelCase     )}     )
								tf_input.update({'decoder_input_ids': tf.convert_to_tensor(_UpperCamelCase     )}     )

					return pt_input, tf_input



		def       __UpperCAmelCase    (							self     )			->							Any:
					# hub version 0.9.0 introduced the possibility of programmatically opening PRs with normal write tokens.
					if version.parse(huggingface_hub.__version__     ) < version.parse('0.9.0'     ):
								raise ImportError(
								    'The huggingface_hub version must be >= 0.9.0 to use this command. Please update your huggingface_hub'
								    ' installation.'     )
					else:
								from huggingface_hub import Repository, create_commit
								from huggingface_hub._commit_api import CommitOperationAdd

					# Fetch remote data
					UpperCAmelCase_					:   List[Any]   =		Repository(local_dir=self._local_dir       ,	clone_from=self._model_name     )

					# Load config and get the appropriate architecture -- the latter is needed to convert the head's weights
					UpperCAmelCase_					:   Optional[Any]   =		AutoConfig.from_pretrained(self._local_dir     )
					UpperCAmelCase_					:   int   =		config.architectures
					if self._override_model_class is not None:
								if self._override_model_class.startswith('TF'     ):
											UpperCAmelCase_					:   Any   =		[self._override_model_class[2:]]
								else:
											UpperCAmelCase_					:   Optional[int]   =		[self._override_model_class]
								try:
											UpperCAmelCase_					:   Tuple   =		getattr(import_module('transformers'     )       ,	architectures[0]     )
								except AttributeError:
											raise ValueError(f"Model class {self._override_model_class} not found in transformers."     )
								try:
											UpperCAmelCase_					:   Dict   =		getattr(import_module('transformers'     )       ,	'TF' + architectures[0]     )
								except AttributeError:
											raise ValueError(f"TF model class TF{self._override_model_class} not found in transformers."     )
					elif architectures is None:  # No architecture defined -- use auto classes
								UpperCAmelCase_					:   str   =		getattr(import_module('transformers'     )       ,	'AutoModel'     )
								UpperCAmelCase_					:   Union[str, Any]   =		getattr(import_module('transformers'     )       ,	'TFAutoModel'     )
								self._logger.warning('No detected architecture, using AutoModel/TFAutoModel'     )
					else:  # Architecture defined -- use it
								if len(_UpperCamelCase     ) > 1:
											raise ValueError(f"More than one architecture was found, aborting. (architectures = {architectures})"     )
								self._logger.warning(f"Detected architecture: {architectures[0]}"     )
								UpperCAmelCase_					:   Dict   =		getattr(import_module('transformers'     )       ,	architectures[0]     )
								try:
											UpperCAmelCase_					:   Dict   =		getattr(import_module('transformers'     )       ,	'TF' + architectures[0]     )
								except AttributeError:
											raise AttributeError(f"The TensorFlow equivalent of {architectures[0]} doesn't exist in transformers."     )

        # Check the TF dummy inputs to see what keys we need in the forward pass
					UpperCAmelCase_					:   Optional[Any]   =		tf_class.from_config(_UpperCamelCase     )
					UpperCAmelCase_					:   str   =		tf_from_pt_model.dummy_inputs

					del tf_from_pt_model  # Try to keep only one model in memory at a time

					# Load the model and get some basic inputs
					UpperCAmelCase_					:   Optional[int]   =		pt_class.from_pretrained(self._local_dir     )
					pt_model.eval()

					UpperCAmelCase_					:   str   =		self.get_inputs(_UpperCamelCase       ,	_UpperCamelCase       ,	_UpperCamelCase     )

					with torch.no_grad():
								UpperCAmelCase_					:   Tuple   =		pt_model(**_UpperCamelCase       ,	output_hidden_states=_UpperCamelCase     )
					del pt_model  # will no longer be used, and may have a large memory footprint

					UpperCAmelCase_					:   List[str]   =		tf_class.from_pretrained(self._local_dir       ,	from_pt=_UpperCamelCase     )
					UpperCAmelCase_					:   Any   =		tf_from_pt_model(**_UpperCamelCase       ,	output_hidden_states=_UpperCamelCase       ,	training=_UpperCamelCase     )

					# Confirms that cross loading PT weights into TF worked.
					UpperCAmelCase_					:   Optional[Any]   =		self.find_pt_tf_differences(_UpperCamelCase       ,	_UpperCamelCase     )
					UpperCAmelCase_					:   List[Any]   =		{k: v for k, v in crossload_differences.items() if 'hidden' not in k}
					UpperCAmelCase_					:   Tuple   =		{k: v for k, v in crossload_differences.items() if 'hidden' in k}
					if len(_UpperCamelCase     ) == 0 and architectures is not None:
								raise ValueError(
								    f"Something went wrong -- the config file has architectures ({architectures}), but no model head"
								    ' output was found. All outputs start with \'hidden\''     )
					UpperCAmelCase_					:   int   =		max(output_differences.values()     ) if output_differences else 0.0
					UpperCAmelCase_					:   str   =		max(hidden_differences.values()     )
					if max_crossload_output_diff > self._max_error or max_crossload_hidden_diff > self._max_error:
								raise ValueError(
								    'The cross-loaded TensorFlow model has different outputs, something went wrong!\n'
								    + f"\nList of maximum output differences above the threshold ({self._max_error}):\n"
								    + '\n'.join([f"{k}: {v:.3e}" for k, v in output_differences.items() if v > self._max_error]     )
								    + f"\n\nList of maximum hidden layer differences above the threshold ({self._max_error}):\n"
								    + '\n'.join([f"{k}: {v:.3e}" for k, v in hidden_differences.items() if v > self._max_error]     )     )

					# Save the weights in a TF format (if needed) and confirms that the results are still good
					UpperCAmelCase_					:   Optional[Any]   =		os.path.join(self._local_dir       ,	_UpperCamelCase     )
					UpperCAmelCase_					:   List[str]   =		os.path.join(self._local_dir       ,	_UpperCamelCase     )
					if (not os.path.exists(_UpperCamelCase     ) and not os.path.exists(_UpperCamelCase     )) or self._new_weights:
								tf_from_pt_model.save_pretrained(self._local_dir     )
					del tf_from_pt_model  # will no longer be used, and may have a large memory footprint

					UpperCAmelCase_					:   str   =		tf_class.from_pretrained(self._local_dir     )
					UpperCAmelCase_					:   Dict   =		tf_model(**_UpperCamelCase       ,	output_hidden_states=_UpperCamelCase     )

					UpperCAmelCase_					:   List[Any]   =		self.find_pt_tf_differences(_UpperCamelCase       ,	_UpperCamelCase     )
					UpperCAmelCase_					:   Optional[Any]   =		{k: v for k, v in conversion_differences.items() if 'hidden' not in k}
					UpperCAmelCase_					:   int   =		{k: v for k, v in conversion_differences.items() if 'hidden' in k}
					if len(_UpperCamelCase     ) == 0 and architectures is not None:
								raise ValueError(
								    f"Something went wrong -- the config file has architectures ({architectures}), but no model head"
								    ' output was found. All outputs start with \'hidden\''     )
					UpperCAmelCase_					:   Tuple   =		max(output_differences.values()     ) if output_differences else 0.0
					UpperCAmelCase_					:   Optional[int]   =		max(hidden_differences.values()     )
					if max_conversion_output_diff > self._max_error or max_conversion_hidden_diff > self._max_error:
								raise ValueError(
								    'The converted TensorFlow model has different outputs, something went wrong!\n'
								    + f"\nList of maximum output differences above the threshold ({self._max_error}):\n"
								    + '\n'.join([f"{k}: {v:.3e}" for k, v in output_differences.items() if v > self._max_error]     )
								    + f"\n\nList of maximum hidden layer differences above the threshold ({self._max_error}):\n"
								    + '\n'.join([f"{k}: {v:.3e}" for k, v in hidden_differences.items() if v > self._max_error]     )     )

					UpperCAmelCase_					:   Optional[Any]   =		'Update TF weights' if self._new_weights else 'Add TF weights'
					if self._push:
								repo.git_add(auto_lfs_track=_UpperCamelCase     )
								repo.git_commit(_UpperCamelCase     )
								repo.git_push(blocking=_UpperCamelCase     )  # this prints a progress bar with the upload
								self._logger.warning(f"TF weights pushed into {self._model_name}"     )
					elif not self._no_pr:
								self._logger.warning('Uploading the weights into a new PR...'     )
								UpperCAmelCase_					:   Any   =		(
								    'Model converted by the [`transformers`\' `pt_to_tf`'
								    ' CLI](https://github.com/huggingface/transformers/blob/main/src/transformers/commands/pt_to_tf.py). '
								    'All converted model outputs and hidden layers were validated against its PyTorch counterpart.\n\n'
								    f"Maximum crossload output difference={max_crossload_output_diff:.3e}; "
								    f"Maximum crossload hidden layer difference={max_crossload_hidden_diff:.3e};\n"
								    f"Maximum conversion output difference={max_conversion_output_diff:.3e}; "
								    f"Maximum conversion hidden layer difference={max_conversion_hidden_diff:.3e};\n"
								)
								if self._max_error > MAX_ERROR:
											commit_descrition += (
											    f"\n\nCAUTION: The maximum admissible error was manually increased to {self._max_error}!"
											)
								if self._extra_commit_description:
											commit_descrition += "\n\n" + self._extra_commit_description

								# sharded model -> adds all related files (index and .h5 shards)
								if os.path.exists(_UpperCamelCase     ):
											UpperCAmelCase_					:   Dict   =		[
											    CommitOperationAdd(path_in_repo=_UpperCamelCase       ,	path_or_fileobj=_UpperCamelCase     )
											]
											for shard_path in tf.io.gfile.glob(self._local_dir + '/tf_model-*.h5'     ):
														operations += [
														    CommitOperationAdd(path_in_repo=os.path.basename(_UpperCamelCase     )       ,	path_or_fileobj=_UpperCamelCase     )
														]
								else:
											UpperCAmelCase_					:   Any   =		[CommitOperationAdd(path_in_repo=_UpperCamelCase       ,	path_or_fileobj=_UpperCamelCase     )]

								UpperCAmelCase_					:   Optional[Any]   =		create_commit(
								    repo_id=self._model_name       ,	operations=_UpperCamelCase       ,	commit_message=_UpperCamelCase       ,	commit_description=_UpperCamelCase       ,	repo_type='model'       ,	create_pr=_UpperCamelCase       ,	).pr_url
								self._logger.warning(f"PR open in {hub_pr_url}"     )














from __future__ import annotations

from typing import Any




def   lowercase__   (  *__snake_case					:							list[list[int]]						):


					'''simple docstring'''


					if all(_check_not_integer(__snake_case						) for m in matrix_s						):
										for i in matrix_s[1:]:
															_verify_matrix_sizes(matrix_s[0]  , __snake_case						)
										return [[sum(__snake_case						) for t in zip(*__snake_case						)] for m in zip(*__snake_case						)]
					raise TypeError('Expected a matrix, got int/list instead'						)




def   lowercase__   (  __snake_case					:							list[list[int]]  , __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					if (
					    _check_not_integer(__snake_case						)
					    and _check_not_integer(__snake_case						)
					    and _verify_matrix_sizes(__snake_case  , __snake_case						)
					):
										return [[i - j for i, j in zip(*__snake_case						)] for m in zip(__snake_case  , __snake_case						)]
					raise TypeError('Expected a matrix, got int/list instead'						)




def   lowercase__   (  __snake_case					:							list[list[int]]  , __snake_case					:							int | float						):


					'''simple docstring'''


					return [[x * n for x in row] for row in matrix]




def   lowercase__   (  __snake_case					:							list[list[int]]  , __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					if _check_not_integer(__snake_case						) and _check_not_integer(__snake_case						):
										UpperCAmelCase_ ,						UpperCAmelCase_					:   str   =		_verify_matrix_sizes(__snake_case  , __snake_case						)

					if cols[0] != rows[1]:
										UpperCAmelCase_					:   Dict   =		(
										    'Cannot multiply matrix of dimensions '
										    F"({rows[0]},{cols[0]}) and ({rows[1]},{cols[1]})"
										)
										raise ValueError(__snake_case						)
					return [
					    [sum(m * n for m, n in zip(__snake_case  , __snake_case						)						) for j in zip(*__snake_case						)] for i in matrix_a
					]




def   lowercase__   (  __snake_case					:							int						):


					'''simple docstring'''


					UpperCAmelCase_					:   Optional[Any]   =		int(__snake_case						)
					return [[int(row == column						) for column in range(__snake_case						)] for row in range(__snake_case						)]




def   lowercase__   (  __snake_case					:							list[list[int]]  , __snake_case					:							bool = True						):


					'''simple docstring'''


					if _check_not_integer(__snake_case						):
										if return_map:
															return map(__snake_case  , zip(*__snake_case						)						)
										else:
															return list(map(__snake_case  , zip(*__snake_case						)						)						)
					raise TypeError('Expected a matrix, got int/list instead'						)




def   lowercase__   (  __snake_case					:							list[list[int]]  , __snake_case					:							int  , __snake_case					:							int						):


					'''simple docstring'''


					UpperCAmelCase_					:   Any   =		matrix[:row] + matrix[row + 1 :]
					return [row[:column] + row[column + 1 :] for row in minor]




def   lowercase__   (  __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					if len(__snake_case						) == 1:
										return matrix[0][0]

					return sum(
					    x * determinant(minor(__snake_case  , 0  , __snake_case						)						) * (-1) ** i
					    for i, x in enumerate(matrix[0]						)						)




def   lowercase__   (  __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					UpperCAmelCase_					:   Optional[int]   =		determinant(__snake_case						)
					if det == 0:
										return None

					UpperCAmelCase_					:   List[str]   =		[
					    [determinant(minor(__snake_case  , __snake_case  , __snake_case						)						) for j in range(len(__snake_case						)						)]
					    for i in range(len(__snake_case						)						)
					]

					UpperCAmelCase_					:   List[str]   =		[
					    [x * (-1) ** (row + col) for col, x in enumerate(matrix_minor[row]						)]
					    for row in range(len(__snake_case						)						)
					]
					UpperCAmelCase_					:   Tuple   =		list(transpose(__snake_case						)						)
					return scalar_multiply(__snake_case  , 1 / det						)




def   lowercase__   (  __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					return not isinstance(__snake_case  , __snake_case						) and not isinstance(matrix[0]  , __snake_case						)




def   lowercase__   (  __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					return len(__snake_case						), len(matrix[0]						)




def   lowercase__   (  __snake_case					:							list[list[int]]  , __snake_case					:							list[list[int]]						):


					'''simple docstring'''


					UpperCAmelCase_					:   Optional[Any]   =		_shape(__snake_case						) + _shape(__snake_case						)
					if shape[0] != shape[3] or shape[1] != shape[2]:
										UpperCAmelCase_					:   Optional[int]   =		(
										    'operands could not be broadcast together with shape '
										    F"({shape[0], shape[1]}), ({shape[2], shape[3]})"
										)
										raise ValueError(__snake_case						)
					return (shape[0], shape[2]), (shape[1], shape[3])




def   lowercase__   (  ):


					'''simple docstring'''


					UpperCAmelCase_					:   Tuple   =		[[12, 10], [3, 9]]
					UpperCAmelCase_					:   Optional[int]   =		[[3, 4], [7, 4]]
					UpperCAmelCase_					:   List[str]   =		[[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34], [41, 42, 43, 44]]
					UpperCAmelCase_					:   str   =		[[3, 0, 2], [2, 0, -2], [0, 1, 1]]
					print(F"Add Operation, {add(__snake_case  , __snake_case						) = } \n"						)
					print(
					    F"Multiply Operation, {multiply(__snake_case  , __snake_case						) = } \n"  , )
					print(F"Identity: {identity(5						)}\n"						)
					print(F"Minor of {matrix_c} = {minor(__snake_case  , 1  , 2						)} \n"						)
					print(F"Determinant of {matrix_b} = {determinant(__snake_case						)} \n"						)
					print(F"Inverse of {matrix_d} = {inverse(__snake_case						)}\n"						)


if __name__ == "__main__":
		import doctest

		doctest.testmod()
		main()






