

"""simple docstring"""






import inspect
import tempfile
import unittest

from huggingface_hub import hf_hub_download

from transformers import is_torch_available
from transformers.testing_utils import is_flaky, require_torch, slow, torch_device

from ...test_configuration_common import ConfigTester
from ...test_modeling_common import ModelTesterMixin, floats_tensor, ids_tensor
from ...test_pipeline_mixin import PipelineTesterMixin


snake_case_   :   Optional[int]        =       1E-4

if is_torch_available():
 import torch

 from transformers import AutoformerConfig, AutoformerForPrediction, AutoformerModel
 from transformers.models.autoformer.modeling_autoformer import AutoformerDecoder, AutoformerEncoder







@require_torch
class       snake_case__  :







   def __init__(			self			: Tuple			,  lowercase			: List[Any]			,  lowercase			: List[Any]=16			,  lowercase			: Dict=13			,  lowercase			: Any=7			,  lowercase			: Optional[Any]=14			,  lowercase			: List[Any]=10			,  lowercase			: List[Any]=19			,  lowercase			: Tuple=5			,  lowercase			: int=4			,  lowercase			: Optional[int]=True			,  lowercase			: Optional[int]=16			,  lowercase			: Optional[Any]=2			,  lowercase			: int=4			,  lowercase			: Dict=4			,  lowercase			: Tuple="gelu"			,  lowercase			: Optional[int]=0.1			,  lowercase			: Tuple=0.1			,  lowercase			: Dict=[1, 2, 3, 4, 5]			,  lowercase			: Union[str, Any]=25			,  lowercase			: Optional[Any]=5			,  ):





        '''simple docstring'''



        UpperCAmelCase			:   Union[str, Any]      =				d_model
        UpperCAmelCase			:   List[Any]      =				parent
        UpperCAmelCase			:   int      =				batch_size
        UpperCAmelCase			:   Tuple      =				prediction_length
        UpperCAmelCase			:   Optional[int]      =				context_length
        UpperCAmelCase			:   Tuple      =				cardinality
        UpperCAmelCase			:   Optional[Any]      =				num_time_features
        UpperCAmelCase			:   Any      =				lags_sequence
        UpperCAmelCase			:   int      =				embedding_dimension
        UpperCAmelCase			:   Union[str, Any]      =				is_training
        UpperCAmelCase			:   int      =				hidden_size
        UpperCAmelCase			:   Optional[int]      =				num_hidden_layers
        UpperCAmelCase			:   List[str]      =				num_attention_heads
        UpperCAmelCase			:   Union[str, Any]      =				intermediate_size
        UpperCAmelCase			:   str      =				hidden_act
        UpperCAmelCase			:   Optional[Any]      =				hidden_dropout_prob
        UpperCAmelCase			:   Any      =				attention_probs_dropout_prob

        UpperCAmelCase			:   List[Any]      =				context_length
        UpperCAmelCase			:   List[str]      =				prediction_length + label_length
        UpperCAmelCase			:   str      =				label_length

        UpperCAmelCase			:   List[Any]      =				moving_average
        UpperCAmelCase			:   Any      =				autocorrelation_factor







   def 			__lowerCAmelCase				(			self			: int  ):





        '''simple docstring'''



        return AutoformerConfig(
            d_model=self.d_model			,  encoder_layers=self.num_hidden_layers			,  decoder_layers=self.num_hidden_layers			,  encoder_attention_heads=self.num_attention_heads			,  decoder_attention_heads=self.num_attention_heads			,  encoder_ffn_dim=self.intermediate_size			,  decoder_ffn_dim=self.intermediate_size			,  dropout=self.hidden_dropout_prob			,  attention_dropout=self.attention_probs_dropout_prob			,  prediction_length=self.prediction_length			,  context_length=self.context_length			,  label_length=self.label_length			,  lags_sequence=self.lags_sequence			,  num_time_features=self.num_time_features			,  num_static_categorical_features=1			,  cardinality=[self.cardinality]			,  embedding_dimension=[self.embedding_dimension]			,  moving_average=self.moving_average			,  )







   def 			__lowerCAmelCase				(			self			: str			,  lowercase			: Dict  ):





        '''simple docstring'''



        UpperCAmelCase			:   Tuple      =				config.context_length + max(config.lags_sequence  )

        UpperCAmelCase			:   List[str]      =				ids_tensor([self.batch_size, 1]			,  config.cardinality[0]  )
        UpperCAmelCase			:   Tuple      =				floats_tensor([self.batch_size, _past_length, config.num_time_features]  )
        UpperCAmelCase			:   Union[str, Any]      =				floats_tensor([self.batch_size, _past_length]  )
        UpperCAmelCase			:   Optional[Any]      =				floats_tensor([self.batch_size, _past_length]  ) > 0.5

        # decoder inputs
        UpperCAmelCase			:   Optional[int]      =				floats_tensor([self.batch_size, config.prediction_length, config.num_time_features]  )
        UpperCAmelCase			:   Any      =				floats_tensor([self.batch_size, config.prediction_length]  )

        UpperCAmelCase			:   List[Any]      =				{
            "past_values": past_values,
            "static_categorical_features": static_categorical_features,
            "past_time_features": past_time_features,
            "past_observed_mask": past_observed_mask,
            "future_time_features": future_time_features,
            "future_values": future_values,
        }
        return inputs_dict







   def 			__lowerCAmelCase				(			self			: Optional[Any]  ):





        '''simple docstring'''



        UpperCAmelCase			:   List[str]      =				self.get_config()
        UpperCAmelCase			:   str      =				self.prepare_autoformer_inputs_dict(_a  )
        return config, inputs_dict







   def 			__lowerCAmelCase				(			self			: int  ):





        '''simple docstring'''



        UpperCAmelCase      ,							UpperCAmelCase			:   List[str]      =				self.prepare_config_and_inputs()
        return config, inputs_dict







   def 			__lowerCAmelCase				(			self			: Any			,  lowercase			: Optional[Any]			,  lowercase			: Tuple  ):





        '''simple docstring'''



        UpperCAmelCase			:   List[Any]      =				AutoformerModel(config=_a  ).to(_a  ).eval()
        UpperCAmelCase			:   str      =				model(**_a  )

        UpperCAmelCase			:   Any      =				outputs.encoder_last_hidden_state
        UpperCAmelCase			:   str      =				outputs.last_hidden_state

        with tempfile.TemporaryDirectory() as tmpdirname:
             UpperCAmelCase			:   Dict      =				model.get_encoder()
             encoder.save_pretrained(_a  )
             UpperCAmelCase			:   Union[str, Any]      =				AutoformerEncoder.from_pretrained(_a  ).to(_a  )

        UpperCAmelCase      ,							UpperCAmelCase      ,							UpperCAmelCase      ,							UpperCAmelCase      ,							UpperCAmelCase			:   Optional[int]      =				model.create_network_inputs(**_a  )
        UpperCAmelCase      ,							UpperCAmelCase			:   int      =				model.decomposition_layer(transformer_inputs[:, : config.context_length, ...]  )

        UpperCAmelCase			:   Any      =				torch.cat(
            (transformer_inputs[:, : config.context_length, ...], feature[:, : config.context_length, ...])			,  dim=-1			,  )
        UpperCAmelCase			:   Union[str, Any]      =				encoder(inputs_embeds=_a  )[0]
        self.parent.assertTrue((encoder_last_hidden_state_a - encoder_last_hidden_state).abs().max().item() < 1E-3  )

        UpperCAmelCase			:   Union[str, Any]      =				(
            torch.mean(transformer_inputs[:, : config.context_length, ...]			,  dim=1  )
            .unsqueeze(1  )
            .repeat(1			,  config.prediction_length			,  1  )
        )
        UpperCAmelCase			:   Optional[int]      =				torch.zeros(
            [transformer_inputs.shape[0], config.prediction_length, transformer_inputs.shape[2]]			,  device=enc_input.device			,  )

        UpperCAmelCase			:   int      =				torch.cat(
            (
                torch.cat((seasonal_input[:, -config.label_length :, ...], zeros)			,  dim=1  ),
                feature[:, config.context_length - config.label_length :, ...],
            )			,  dim=-1			,  )
        UpperCAmelCase			:   Optional[int]      =				torch.cat(
            (
                torch.cat((trend_input[:, -config.label_length :, ...], mean)			,  dim=1  ),
                feature[:, config.context_length - config.label_length :, ...],
            )			,  dim=-1			,  )

        with tempfile.TemporaryDirectory() as tmpdirname:
             UpperCAmelCase			:   int      =				model.get_decoder()
             decoder.save_pretrained(_a  )
             UpperCAmelCase			:   Tuple      =				AutoformerDecoder.from_pretrained(_a  ).to(_a  )

        UpperCAmelCase			:   Any      =				decoder(
            trend=_a			,  inputs_embeds=_a			,  encoder_hidden_states=_a			,  )[0]

        self.parent.assertTrue((last_hidden_state_a - last_hidden_state).abs().max().item() < 1E-3  )







@require_torch
class       snake_case__  ( __SCREAMING_SNAKE_CASE					,  __SCREAMING_SNAKE_CASE					,  unittest.TestCase     ):
   SCREAMING_SNAKE_CASE__     				=						(AutoformerModel, AutoformerForPrediction) if is_torch_available() else ()
   SCREAMING_SNAKE_CASE__     				=						(AutoformerForPrediction,) if is_torch_available() else ()
   SCREAMING_SNAKE_CASE__     				=						{'feature-extraction': AutoformerModel} if is_torch_available() else {}
   SCREAMING_SNAKE_CASE__     				=						False
   SCREAMING_SNAKE_CASE__     				=						False
   SCREAMING_SNAKE_CASE__     				=						False
   SCREAMING_SNAKE_CASE__     				=						False
   SCREAMING_SNAKE_CASE__     				=						False
   SCREAMING_SNAKE_CASE__     				=						False







   def 			__lowerCAmelCase				(			self			: str  ):





        '''simple docstring'''



        UpperCAmelCase			:   Any      =				AutoformerModelTester(self  )
        UpperCAmelCase			:   Optional[Any]      =				ConfigTester(self			,  config_class=_a			,  has_text_modality=_a  )







   def 			__lowerCAmelCase				(			self			: Union[str, Any]  ):





        '''simple docstring'''



        self.config_tester.run_common_tests()







   def 			__lowerCAmelCase				(			self			: List[str]  ):





        '''simple docstring'''



        UpperCAmelCase      ,							UpperCAmelCase			:   str      =				self.model_tester.prepare_config_and_inputs()
        for model_class in self.all_model_classes:
             UpperCAmelCase			:   Dict      =				model_class(_a  )

             with tempfile.TemporaryDirectory() as tmpdirname:
                  model.save_pretrained(_a  )
                  UpperCAmelCase      ,							UpperCAmelCase			:   Dict      =				model_class.from_pretrained(_a			,  output_loading_info=_a  )
             self.assertEqual(info["missing_keys"]			,  []  )







   def 			__lowerCAmelCase				(			self			: int  ):





        '''simple docstring'''



        UpperCAmelCase			:   List[Any]      =				self.model_tester.prepare_config_and_inputs_for_common()
        self.model_tester.check_encoder_decoder_model_standalone(*_a  )







   @unittest.skip(reason="Model has no tokens embeddings"  )
   def 			__lowerCAmelCase				(			self			: List[Any]  ):





        '''simple docstring'''



        pass







   def 			__lowerCAmelCase				(			self			: Optional[Any]  ):





        '''simple docstring'''



        UpperCAmelCase			:   Dict      =				inspect.signature(getattr(_a			,  "forward"  )  )
        # The main input is the name of the argument after `self`
        UpperCAmelCase			:   Any      =				list(model_signature.parameters.keys()  )[1]
        self.assertEqual(AutoformerModel.main_input_name			,  _a  )







   def 			__lowerCAmelCase				(			self			: Dict  ):





        '''simple docstring'''



        UpperCAmelCase      ,							UpperCAmelCase			:   Any      =				self.model_tester.prepare_config_and_inputs_for_common()

        for model_class in self.all_model_classes:
             UpperCAmelCase			:   Tuple      =				model_class(_a  )
             UpperCAmelCase			:   List[Any]      =				inspect.signature(model.forward  )
             # signature.parameters is an OrderedDict => so arg_names order is deterministic
             UpperCAmelCase			:   List[Any]      =				[*signature.parameters.keys()]

             UpperCAmelCase			:   List[str]      =				[
                 "past_values",
                 "past_time_features",
                 "past_observed_mask",
                 "static_categorical_features",
                 "static_real_features",
                 "future_values",
                 "future_time_features",
             ]

             if model.__class__.__name__ in ["AutoformerForPrediction"]:
                  expected_arg_names.append("future_observed_mask"  )

             expected_arg_names.extend(
                 [
                     "decoder_attention_mask",
                     "head_mask",
                     "decoder_head_mask",
                     "cross_attn_head_mask",
                     "encoder_outputs",
                     "past_key_values",
                     "output_hidden_states",
                     "output_attentions",
                     "use_cache",
                     "return_dict",
                 ]  )

             self.assertListEqual(arg_names[: len(_a  )]			,  _a  )







   def 			__lowerCAmelCase				(			self			: Tuple  ):





        '''simple docstring'''



        UpperCAmelCase      ,							UpperCAmelCase			:   Dict      =				self.model_tester.prepare_config_and_inputs_for_common()
        UpperCAmelCase			:   Tuple      =				True

        UpperCAmelCase			:   Tuple      =				getattr(self.model_tester			,  "seq_length"			,  _a  )
        UpperCAmelCase			:   str      =				getattr(self.model_tester			,  "decoder_seq_length"			,  _a  )
        UpperCAmelCase			:   Dict      =				getattr(self.model_tester			,  "encoder_seq_length"			,  _a  )
        UpperCAmelCase			:   Tuple      =				getattr(self.model_tester			,  "d_model"			,  _a  )
        UpperCAmelCase			:   Dict      =				getattr(self.model_tester			,  "num_attention_heads"			,  _a  )
        UpperCAmelCase			:   Tuple      =				d_model // num_attention_heads

        for model_class in self.all_model_classes:
             UpperCAmelCase			:   List[str]      =				True
             UpperCAmelCase			:   Optional[Any]      =				False
             UpperCAmelCase			:   int      =				True
             UpperCAmelCase			:   Dict      =				model_class(_a  )
             model.to(_a  )
             model.eval()
             with torch.no_grad():
                  UpperCAmelCase			:   Dict      =				model(**self._prepare_for_class(_a			,  _a  )  )
             UpperCAmelCase			:   List[str]      =				outputs.encoder_attentions if config.is_encoder_decoder else outputs.attentions
             self.assertEqual(len(_a  )			,  self.model_tester.num_hidden_layers  )

             # check that output_attentions also work using config
             del inputs_dict["output_attentions"]
             UpperCAmelCase			:   int      =				True
             UpperCAmelCase			:   int      =				model_class(_a  )
             model.to(_a  )
             model.eval()
             with torch.no_grad():
                  UpperCAmelCase			:   Optional[int]      =				model(**self._prepare_for_class(_a			,  _a  )  )
             UpperCAmelCase			:   Dict      =				outputs.encoder_attentions
             self.assertEqual(len(_a  )			,  self.model_tester.num_hidden_layers  )

             self.assertListEqual(
                 list(attentions[0].shape[-3:]  )			,  [self.model_tester.num_attention_heads, encoder_seq_length, dim]			,  )
             UpperCAmelCase			:   Any      =				len(_a  )

             UpperCAmelCase			:   Tuple      =				7

             if "last_hidden_state" in outputs:
                  correct_outlen += 1

             if "trend" in outputs:
                  correct_outlen += 1

             if "past_key_values" in outputs:
                  correct_outlen += 1  # past_key_values have been returned

             if "loss" in outputs:
                  correct_outlen += 1

             if "params" in outputs:
                  correct_outlen += 1

             self.assertEqual(_a			,  _a  )

             # decoder attentions
             UpperCAmelCase			:   Union[str, Any]      =				outputs.decoder_attentions
             self.assertIsInstance(_a			,  (list, tuple)  )
             self.assertEqual(len(_a  )			,  self.model_tester.num_hidden_layers  )
             self.assertListEqual(
                 list(decoder_attentions[0].shape[-3:]  )			,  [self.model_tester.num_attention_heads, decoder_seq_length, dim]			,  )

             # cross attentions
             UpperCAmelCase			:   Any      =				outputs.cross_attentions
             self.assertIsInstance(_a			,  (list, tuple)  )
             self.assertEqual(len(_a  )			,  self.model_tester.num_hidden_layers  )
             self.assertListEqual(
                 list(cross_attentions[0].shape[-3:]  )			,  [self.model_tester.num_attention_heads, decoder_seq_length, dim]			,  )

        # Check attention is always last and order is fine
        UpperCAmelCase			:   Tuple      =				True
        UpperCAmelCase			:   Union[str, Any]      =				True
        UpperCAmelCase			:   Dict      =				model_class(_a  )
        model.to(_a  )
        model.eval()
        with torch.no_grad():
             UpperCAmelCase			:   Dict      =				model(**self._prepare_for_class(_a			,  _a  )  )

        self.assertEqual(out_len + 2			,  len(_a  )  )

        UpperCAmelCase			:   int      =				outputs.encoder_attentions if config.is_encoder_decoder else outputs.attentions

        self.assertEqual(len(_a  )			,  self.model_tester.num_hidden_layers  )
        self.assertListEqual(
            list(self_attentions[0].shape[-3:]  )			,  [self.model_tester.num_attention_heads, encoder_seq_length, dim]			,  )







   @is_flaky()
   def 			__lowerCAmelCase				(			self			: int  ):





        '''simple docstring'''



        super().test_retain_grad_hidden_states_attentions()



def   lowercase_	(    _lowercase       :		Optional[int]="train-batch.pt"	):




     '''simple docstring'''






     UpperCAmelCase			:   Optional[Any]      =				hf_hub_download(repo_id="hf-internal-testing/tourism-monthly-batch"							,      filename=lowerCAmelCase__							,      repo_type="dataset"	)
     UpperCAmelCase			:   Union[str, Any]      =				torch.load(lowerCAmelCase__							,      map_location=lowerCAmelCase__	)
     return batch







@require_torch
@slow
class       snake_case__  ( unittest.TestCase     ):







   def 			__lowerCAmelCase				(			self			: Any  ):





        '''simple docstring'''



        UpperCAmelCase			:   Tuple      =				AutoformerModel.from_pretrained("huggingface/autoformer-tourism-monthly"  ).to(_a  )
        UpperCAmelCase			:   Optional[Any]      =				prepare_batch()

        with torch.no_grad():
             UpperCAmelCase			:   Optional[Any]      =				model(
                 past_values=batch["past_values"]			,  past_time_features=batch["past_time_features"]			,  past_observed_mask=batch["past_observed_mask"]			,  static_categorical_features=batch["static_categorical_features"]			,  future_values=batch["future_values"]			,  future_time_features=batch["future_time_features"]			,  )[0]

        UpperCAmelCase			:   Optional[Any]      =				torch.Size(
            (64, model.config.prediction_length + model.config.label_length, model.config.feature_size)  )
        self.assertEqual(output.shape			,  _a  )

        UpperCAmelCase			:   Tuple      =				torch.tensor(
            [[0.3_5_9_3, -1.3_3_9_8, 0.6_3_3_0], [0.2_2_7_9, 1.5_3_9_6, -0.1_7_9_2], [0.0_4_5_0, 1.3_2_2_5, -0.2_3_3_5]]			,  device=_a  )
        self.assertTrue(torch.allclose(output[0, :3, :3]			,  _a			,  atol=_a  )  )







   def 			__lowerCAmelCase				(			self			: int  ):





        '''simple docstring'''



        UpperCAmelCase			:   Dict      =				AutoformerForPrediction.from_pretrained("huggingface/autoformer-tourism-monthly"  ).to(_a  )
        UpperCAmelCase			:   List[Any]      =				prepare_batch("val-batch.pt"  )
        with torch.no_grad():
             UpperCAmelCase			:   Any      =				model(
                 past_values=batch["past_values"]			,  past_time_features=batch["past_time_features"]			,  past_observed_mask=batch["past_observed_mask"]			,  static_categorical_features=batch["static_categorical_features"]			,  ).encoder_last_hidden_state
        UpperCAmelCase			:   Tuple      =				torch.Size((64, model.config.context_length, model.config.d_model)  )
        self.assertEqual(output.shape			,  _a  )

        UpperCAmelCase			:   str      =				torch.tensor(
            [[-0.0_7_3_4, -0.9_0_3_6, 0.8_3_5_8], [4.7_1_8_6, 2.4_1_1_3, 1.9_5_8_1], [1.7_9_5_3, 2.3_5_5_8, 1.2_9_7_0]]			,  device=_a  )
        self.assertTrue(torch.allclose(output[0, :3, :3]			,  _a			,  atol=_a  )  )







   def 			__lowerCAmelCase				(			self			: Optional[int]  ):





        '''simple docstring'''



        UpperCAmelCase			:   Optional[Any]      =				AutoformerForPrediction.from_pretrained("huggingface/autoformer-tourism-monthly"  ).to(_a  )
        UpperCAmelCase			:   str      =				prepare_batch("val-batch.pt"  )
        with torch.no_grad():
             UpperCAmelCase			:   Optional[Any]      =				model.generate(
                 static_categorical_features=batch["static_categorical_features"]			,  past_time_features=batch["past_time_features"]			,  past_values=batch["past_values"]			,  future_time_features=batch["future_time_features"]			,  past_observed_mask=batch["past_observed_mask"]			,  )
        UpperCAmelCase			:   str      =				torch.Size((64, model.config.num_parallel_samples, model.config.prediction_length)  )
        self.assertEqual(outputs.sequences.shape			,  _a  )

        UpperCAmelCase			:   List[Any]      =				torch.tensor([3_1_3_0.6_7_6_3, 4_0_5_6.5_2_9_3, 7_0_5_3.0_7_8_6]			,  device=_a  )
        UpperCAmelCase			:   Tuple      =				outputs.sequences.mean(dim=1  )
        self.assertTrue(torch.allclose(mean_prediction[0, -3:]			,  _a			,  rtol=1E-1  )  )





"""simple docstring"""






from __future__ import annotations

snake_case_   :   str        =       list[list[int]]

# assigning initial values to the grid
snake_case_   :   Matrix        =       [
    [3, 0, 6, 5, 0, 8, 4, 0, 0],
    [5, 2, 0, 0, 0, 0, 0, 0, 0],
    [0, 8, 7, 0, 0, 0, 0, 3, 1],
    [0, 0, 3, 0, 1, 0, 0, 8, 0],
    [9, 0, 0, 8, 6, 3, 0, 0, 5],
    [0, 5, 0, 0, 9, 0, 6, 0, 0],
    [1, 3, 0, 0, 0, 0, 2, 5, 0],
    [0, 0, 0, 0, 0, 0, 0, 7, 4],
    [0, 0, 5, 2, 0, 6, 3, 0, 0],
]

# a grid with no solution
snake_case_   :   Matrix        =       [
    [5, 0, 6, 5, 0, 8, 4, 0, 3],
    [5, 2, 0, 0, 0, 0, 0, 0, 2],
    [1, 8, 7, 0, 0, 0, 0, 3, 1],
    [0, 0, 3, 0, 1, 0, 0, 8, 0],
    [9, 0, 0, 8, 6, 3, 0, 0, 5],
    [0, 5, 0, 0, 9, 0, 6, 0, 0],
    [1, 3, 0, 0, 0, 0, 2, 5, 0],
    [0, 0, 0, 0, 0, 0, 0, 7, 4],
    [0, 0, 5, 2, 0, 6, 3, 0, 0],
]



def   lowercase_	(    _lowercase       :		Matrix							,      _lowercase       :		int							,      _lowercase       :		int							,      _lowercase       :		int	):




					'''simple docstring'''






					for i in range(9	):
										if grid[row][i] == n or grid[i][column] == n:
															return False

					for i in range(3	):
										for j in range(3	):
															if grid[(row - row % 3) + i][(column - column % 3) + j] == n:
																				return False

					return True



def   lowercase_	(    _lowercase       :		Matrix	):




					'''simple docstring'''






					for i in range(9	):
										for j in range(9	):
															if grid[i][j] == 0:
																				return i, j
					return None



def   lowercase_	(    _lowercase       :		Matrix	):




					'''simple docstring'''






					if location := find_empty_location(_lowercase	):
										UpperCAmelCase      ,							UpperCAmelCase			:   List[str]      =				location
					else:
										# If the location is ``None``, then the grid is solved.
										return grid

					for digit in range(1							,      10	):
										if is_safe(_lowercase							,      _lowercase							,      _lowercase							,      _lowercase	):
															UpperCAmelCase			:   int      =				digit

															if sudoku(_lowercase	) is not None:
																				return grid

															UpperCAmelCase			:   Optional[Any]      =				0

					return None



def   lowercase_	(    _lowercase       :		Matrix	):




					'''simple docstring'''






					for row in grid:
										for cell in row:
															print(_lowercase							,      end=" "	)
										print()


if __name__ == "__main__":
	# make a copy of grid so that you can compare with the unmodified grid
	for example_grid in (initial_grid, no_solution):
		print("""\nExample grid:\n""" + """=""" * 2_0)
		print_solution(example_grid)
		print("""\nExample grid solution:""")
		snake_case_   :   Dict        =       sudoku(example_grid)
		if solution is not None:
			print_solution(solution)
		else:
			print("""Cannot find a solution.""")


