






"""simple docstring"""
from typing import List, Optional, Union

import numpy as np
import torch
import torchaudio.compliance.kaldi as ta_kaldi

from ...feature_extraction_sequence_utils import SequenceFeatureExtractor
from ...feature_extraction_utils import BatchFeature
from ...utils import PaddingStrategy, TensorType, logging


snake_case : Union[str, Any]     		=		logging.get_logger(__name__)



class        UpperCamelCase__ (				a_):







    """simple docstring"""
    __UpperCAmelCase           = ["""input_features""", """attention_mask"""]







    def __init__(		self :	Dict				,    UpperCamelCase_ :	Optional[Any]=8_0				,    UpperCamelCase_ :	Tuple=1_6_0_0_0				,    UpperCamelCase_ :	Dict=8_0				,    UpperCamelCase_ :	List[str]=0.0				,    UpperCamelCase_ :	Any=True				,    UpperCamelCase_ :	Any=True				,    UpperCamelCase_ :	Tuple=True				,    **UpperCamelCase_ :	List[Any]				,    ):





           '''simple docstring'''

           super().__init__(feature_size=UpperCamelCase_				,    sampling_rate=UpperCamelCase_				,    padding_value=UpperCamelCase_				,    **UpperCamelCase_ )
           __magic_name__      				=    num_mel_bins
           __magic_name__      				=    do_ceptral_normalize
           __magic_name__      				=    normalize_means
           __magic_name__      				=    normalize_vars
           __magic_name__      				=    True







    def 				a__			(		self :	List[str]				,    UpperCamelCase_ :	np.ndarray				,    ):





           '''simple docstring'''

           __magic_name__      				=    waveform * (2**1_5)  # Kaldi compliance: 16-bit signed integers
           __magic_name__      				=    torch.from_numpy(UpperCamelCase_ ).unsqueeze(0 )
           __magic_name__      				=    ta_kaldi.fbank(UpperCamelCase_				,    num_mel_bins=self.num_mel_bins				,    sample_frequency=self.sampling_rate )
           return features.numpy()







    @staticmethod
    def 				a__			(		UpperCamelCase_ :	np.ndarray				,    UpperCamelCase_ :	int				,    UpperCamelCase_ :	Optional[bool] = True				,    UpperCamelCase_ :	Optional[bool] = True				,    UpperCamelCase_ :	float = 0.0				,    ):





           '''simple docstring'''

           if normalize_means:
                  __magic_name__      				=    x[:input_length].mean(axis=0 )
                  __magic_name__      				=    np.subtract(UpperCamelCase_				,    UpperCamelCase_ )
           if normalize_vars:
                  __magic_name__      				=    x[:input_length].std(axis=0 )
                  __magic_name__      				=    np.divide(UpperCamelCase_				,    UpperCamelCase_ )

           if input_length < x.shape[0]:
                  __magic_name__      				=    padding_value

           # make sure array is in float32
           __magic_name__      				=    x.astype(np.floataa )

           return x







    def 				a__			(		self :	Any				,    UpperCamelCase_ :	List[np.ndarray]				,    UpperCamelCase_ :	Optional[np.ndarray] = None ):





           '''simple docstring'''

           __magic_name__      				=    attention_mask.sum(-1 ) if attention_mask is not None else [x.shape[0] for x in input_features]
           return [
               self.utterance_cmvn(UpperCamelCase_				,    UpperCamelCase_				,    self.normalize_means				,    self.normalize_vars				,    self.padding_value )
               for x, n in zip(UpperCamelCase_				,    UpperCamelCase_ )
           ]







    def __call__(		self :	List[Any]				,    UpperCamelCase_ :	Union[np.ndarray, List[float], List[np.ndarray], List[List[float]]]				,    UpperCamelCase_ :	Union[bool, str, PaddingStrategy] = False				,    UpperCamelCase_ :	Optional[int] = None				,    UpperCamelCase_ :	bool = False				,    UpperCamelCase_ :	Optional[int] = None				,    UpperCamelCase_ :	Optional[Union[str, TensorType]] = None				,    UpperCamelCase_ :	Optional[int] = None				,    UpperCamelCase_ :	Optional[bool] = None				,    **UpperCamelCase_ :	Union[str, Any]				,    ):





           '''simple docstring'''

           if sampling_rate is not None:
                  if sampling_rate != self.sampling_rate:
                         raise ValueError(
                             f"""The model corresponding to this feature extractor: {self} was trained using a sampling rate of"""
                             f""" {self.sampling_rate}. Please make sure that the provided `raw_speech` input was sampled with"""
                             f""" {self.sampling_rate} and not {sampling_rate}.""" )
           else:
                  logger.warning(
                      'It is strongly recommended to pass the `sampling_rate` argument to this function. '
                      'Failing to do so can result in silent errors that might be hard to debug.' )

           __magic_name__      				=    isinstance(UpperCamelCase_				,    np.ndarray ) and len(raw_speech.shape ) > 1
           if is_batched_numpy and len(raw_speech.shape ) > 2:
                  raise ValueError(f"""Only mono-channel audio is supported for input to {self}""" )
           __magic_name__      				=    is_batched_numpy or (
               isinstance(UpperCamelCase_				,    (list, tuple) ) and (isinstance(raw_speech[0]				,    (np.ndarray, tuple, list) ))
           )

           if is_batched:
                  __magic_name__      				=    [np.asarray(UpperCamelCase_				,    dtype=np.floataa ) for speech in raw_speech]
           elif not is_batched and not isinstance(UpperCamelCase_				,    np.ndarray ):
                  __magic_name__      				=    np.asarray(UpperCamelCase_				,    dtype=np.floataa )
           elif isinstance(UpperCamelCase_				,    np.ndarray ) and raw_speech.dtype is np.dtype(np.floataa ):
                  __magic_name__      				=    raw_speech.astype(np.floataa )

           # always return batch
           if not is_batched:
                  __magic_name__      				=    [raw_speech]

           # extract fbank features
           __magic_name__      				=    [self._extract_fbank_features(UpperCamelCase_ ) for waveform in raw_speech]

           # convert into correct format for padding
           __magic_name__      				=    BatchFeature({'input_features': features} )

           __magic_name__      				=    self.pad(
               UpperCamelCase_				,    padding=UpperCamelCase_				,    max_length=UpperCamelCase_				,    truncation=UpperCamelCase_				,    pad_to_multiple_of=UpperCamelCase_				,    return_attention_mask=UpperCamelCase_				,    **UpperCamelCase_				,    )

           # make sure list is in array format
           __magic_name__      				=    padded_inputs.get('input_features' )
           if isinstance(input_features[0]				,    UpperCamelCase_ ):
                  __magic_name__      				=    [np.asarray(UpperCamelCase_				,    dtype=np.floataa ) for feature in input_features]

           __magic_name__      				=    padded_inputs.get('attention_mask' )
           if attention_mask is not None:
                  __magic_name__      				=    [np.asarray(UpperCamelCase_				,    dtype=np.intaa ) for array in attention_mask]

           # Utterance-level cepstral mean and variance normalization
           if self.do_ceptral_normalize:
                  __magic_name__      				=    (
                      np.array(UpperCamelCase_				,    dtype=np.intaa )
                      if self._get_padding_strategies(UpperCamelCase_				,    max_length=UpperCamelCase_ ) is not PaddingStrategy.DO_NOT_PAD
                      else None
                  )
                  __magic_name__      				=    self.normalize(
                      padded_inputs['input_features']				,    attention_mask=UpperCamelCase_ )

           if return_tensors is not None:
                  __magic_name__      				=    padded_inputs.convert_to_tensors(UpperCamelCase_ )

           return padded_inputs







"""simple docstring"""
import argparse
import copy


def 							A						(				__snake_case: Union[str, Any]  )    ->		Tuple:

       """simple docstring"""





       __magic_name__      				=    {}

       with open(__snake_case  ) as f:
              for line in f:
                     if line.split()[0] not in dict_of_neighbours:
                            __magic_name__      				=    []
                            _list.append([line.split()[1], line.split()[2]]  )
                            __magic_name__      				=    _list
                     else:
                            dict_of_neighbours[line.split()[0]].append(
                                [line.split()[1], line.split()[2]]  )
                     if line.split()[1] not in dict_of_neighbours:
                            __magic_name__      				=    []
                            _list.append([line.split()[0], line.split()[2]]  )
                            __magic_name__      				=    _list
                     else:
                            dict_of_neighbours[line.split()[1]].append(
                                [line.split()[0], line.split()[2]]  )

       return dict_of_neighbours


def 							A						(				__snake_case: Optional[Any] ,     __snake_case: str  )    ->		List[str]:

       """simple docstring"""





       with open(__snake_case  ) as f:
              __magic_name__      				=    f.read(1  )
       __magic_name__      				=    start_node

       __magic_name__      				=    []

       __magic_name__      				=    start_node

       __magic_name__      				=    0
       while visiting not in first_solution:
              __magic_name__      				=    1_0_0_0_0
              for k in dict_of_neighbours[visiting]:
                     if int(k[1]  ) < int(__snake_case  ) and k[0] not in first_solution:
                            __magic_name__      				=    k[1]
                            __magic_name__      				=    k[0]

              first_solution.append(__snake_case  )
              __magic_name__      				=    distance_of_first_solution + int(__snake_case  )
              __magic_name__      				=    best_node

       first_solution.append(__snake_case  )

       __magic_name__      				=    0
       for k in dict_of_neighbours[first_solution[-2]]:
              if k[0] == start_node:
                     break
              position += 1

       __magic_name__      				=    (
           distance_of_first_solution
           + int(dict_of_neighbours[first_solution[-2]][position][1]  )
           - 1_0_0_0_0
       )
       return first_solution, distance_of_first_solution


def 							A						(				__snake_case: Union[str, Any] ,     __snake_case: Optional[Any]  )    ->		Dict:

       """simple docstring"""





       __magic_name__      				=    []

       for n in solution[1:-1]:
              __magic_name__      				=    solution.index(__snake_case  )
              for kn in solution[1:-1]:
                     __magic_name__      				=    solution.index(__snake_case  )
                     if n == kn:
                            continue

                     __magic_name__      				=    copy.deepcopy(__snake_case  )
                     __magic_name__      				=    kn
                     __magic_name__      				=    n

                     __magic_name__      				=    0

                     for k in _tmp[:-1]:
                            __magic_name__      				=    _tmp[_tmp.index(__snake_case  ) + 1]
                            for i in dict_of_neighbours[k]:
                                   if i[0] == next_node:
                                          __magic_name__      				=    distance + int(i[1]  )
                     _tmp.append(__snake_case  )

                     if _tmp not in neighborhood_of_solution:
                            neighborhood_of_solution.append(_tmp  )

       __magic_name__      				=    len(neighborhood_of_solution[0]  ) - 1

       neighborhood_of_solution.sort(key=lambda __snake_case  : x[index_of_last_item_in_the_list]  )
       return neighborhood_of_solution


def 							A						(				__snake_case: List[str] ,     __snake_case: Union[str, Any] ,     __snake_case: List[str] ,     __snake_case: Optional[int] ,     __snake_case: List[str]  )    ->		Dict:

       """simple docstring"""





       __magic_name__      				=    1
       __magic_name__      				=    first_solution
       __magic_name__      				=    []
       __magic_name__      				=    distance_of_first_solution
       __magic_name__      				=    solution

       while count <= iters:
              __magic_name__      				=    find_neighborhood(__snake_case ,     __snake_case  )
              __magic_name__      				=    0
              __magic_name__      				=    neighborhood[index_of_best_solution]
              __magic_name__      				=    len(__snake_case  ) - 1

              __magic_name__      				=    False
              while not found:
                     __magic_name__      				=    0
                     while i < len(__snake_case  ):
                            if best_solution[i] != solution[i]:
                                   __magic_name__      				=    best_solution[i]
                                   __magic_name__      				=    solution[i]
                                   break
                            __magic_name__      				=    i + 1

                     if [first_exchange_node, second_exchange_node] not in tabu_list and [
                         second_exchange_node,
                         first_exchange_node,
                     ] not in tabu_list:
                            tabu_list.append([first_exchange_node, second_exchange_node]  )
                            __magic_name__      				=    True
                            __magic_name__      				=    best_solution[:-1]
                            __magic_name__      				=    neighborhood[index_of_best_solution][best_cost_index]
                            if cost < best_cost:
                                   __magic_name__      				=    cost
                                   __magic_name__      				=    solution
                     else:
                            __magic_name__      				=    index_of_best_solution + 1
                            __magic_name__      				=    neighborhood[index_of_best_solution]

              if len(__snake_case  ) >= size:
                     tabu_list.pop(0  )

              __magic_name__      				=    count + 1

       return best_solution_ever, best_cost


def 							A						(				__snake_case: Union[str, Any]=None  )    ->		Tuple:

       """simple docstring"""





       __magic_name__      				=    generate_neighbours(args.File  )

       __magic_name__				,  __magic_name__      				=    generate_first_solution(
           args.File ,     __snake_case  )

       __magic_name__				,  __magic_name__      				=    tabu_search(
           __snake_case ,     __snake_case ,     __snake_case ,     args.Iterations ,     args.Size ,     )

       print(F"""Best solution: {best_sol}, with total distance: {best_cost}."""  )


if __name__ == "__main__":
 snake_case : str     		=		argparse.ArgumentParser(description="""Tabu Search""")
 parser.add_argument(
     """-f""",
     """--File""",
     type=str,
     help="""Path to the file containing the data""",
     required=True,
 )
 parser.add_argument(
     """-i""",
     """--Iterations""",
     type=int,
     help="""How many iterations the algorithm should perform""",
     required=True,
 )
 parser.add_argument(
     """-s""", """--Size""", type=int, help="""Size of the tabu list""", required=True
 )

 # Pass the arguments to main method
 main(parser.parse_args())