/* sobrecarga do operador * para coef * velocidade
  * trata em casos baseados no valor do coeficiente:
  *  -coef = 0: return {};
  *  -coef < 0: raise exception;
  *  -coef > 0: concatenar s por c vezes para a parte inteira
  *    e truncar s por (1-coef)*|v| para a parte decimal(?)
  */
 public static TSPVelocity operator *(double coef, TSPVelocity s)
 {
     /* cria uma variável para guardar o resultado */
     TSPVelocity final = null;
     /* cria o resultado a partir da comparação de coef com 0 */
     switch (coef.CompareTo(0))
     {
         //coef = 0
         case 0:
             //retorna um vetor vazio
             final = new TSPVelocity();
             break;
         //coef < 0
         case -1:
             //throws exception of d00m
             throw new Exception("Exception of d00m! Operação não suportada!");
         //coef > 0
         case 1:
             final = new TSPVelocity(s.transpositions);
             //concatena i vezes para a parte inteira de coef
             for (int i = 0; i < (int)coef; ++i)
                 final.transpositions.AddRange(s.transpositions);
             //trunca v por (1-c)*|v| e adiciona
             final.transpositions.AddRange(s.transpositions.GetRange(0, (int)Math.Floor(s.transpositions.Count*(coef%1))));
             break;
         default:
             //YOU'LL NEVER GET ME ALIVE !!!
             break;
     }
     /* retorna o objeto com o resultado */
     return final;
 }
        //Ha alguma garantia de que essas particulas aleatorias sejam circuitos hamiltonianos?

        public static TSPParticle RandomGenerate(TSPParticleSwarm containingSwarm, TravellingSalesmanMap Map)
        {
            TSPParticle newParticle = new TSPParticle(containingSwarm, Map);

            newParticle.Velocity = TSPVelocity.RandomGenerate(Map);
            newParticle.Position = new TSPPosition(Aleatoriety.GetRandomIntegerSequencePermutation(1, Map.CityCount).ToList());
            newParticle.EvaluateSelf();
            return(newParticle);
        }
        /*  sobrecarga do operador - para a classe Position
         *  retorna o vetor de transposições(speed) para transformar p1 em p2
         *  P1 - P2 = v => P1 = P2 + v
         */
        public static TSPVelocity operator -(TSPPosition p1, TSPPosition p2)
        {
            /* cria uma variável para carregar o resultado */
            TSPVelocity s = new TSPVelocity();

            //variável temporária para criar as transposições
            List<int> p2Clone = p2.Route.ToList();

            for (int idxP1 = 0; idxP1 < p1.Route.Count; ++idxP1) {
                if (p1.Route[idxP1] != p2Clone[idxP1]) {
                    int idxElem = p2Clone.IndexOf(p1.Route[idxP1]);
                    p2Clone.Swap(idxElem, idxP1);
                    //normalizando transposições equivalentes
                    s.transpositions.Add(idxElem > idxP1 ? new Tuple<int, int>(idxP1, idxElem) : new Tuple<int, int>(idxElem, idxP1));
                }
            }
            return s;
        }
        /*  sobrecarga do operador - para a classe Position
         *  retorna o vetor de transposições(speed) para transformar p1 em p2
         *  P1 - P2 = v => P1 = P2 + v
         */
        public static TSPVelocity operator -(TSPPosition p1, TSPPosition p2)
        {
            /* cria uma variável para carregar o resultado */
            TSPVelocity s = new TSPVelocity();

            //variável temporária para criar as transposições
            List <int> p2Clone = p2.Route.ToList();

            for (int idxP1 = 0; idxP1 < p1.Route.Count; ++idxP1)
            {
                if (p1.Route[idxP1] != p2Clone[idxP1])
                {
                    int idxElem = p2Clone.IndexOf(p1.Route[idxP1]);
                    p2Clone.Swap(idxElem, idxP1);
                    //normalizando transposições equivalentes
                    s.transpositions.Add(idxElem > idxP1 ? new Tuple <int, int>(idxP1, idxElem) : new Tuple <int, int>(idxElem, idxP1));
                }
            }
            return(s);
        }
        /* sobrecarga do operador * para coef * velocidade
         * trata em casos baseados no valor do coeficiente:
         *  -coef = 0: return {};
         *  -coef < 0: raise exception;
         *  -coef > 0: concatenar s por c vezes para a parte inteira
         *    e truncar s por (1-coef)*|v| para a parte decimal(?)
         */
        public static TSPVelocity operator *(double coef, TSPVelocity s)
        {
            /* cria uma variável para guardar o resultado */
            TSPVelocity final = null;

            /* cria o resultado a partir da comparação de coef com 0 */
            switch (coef.CompareTo(0))
            {
            //coef = 0
            case 0:
                //retorna um vetor vazio
                final = new TSPVelocity();
                break;

            //coef < 0
            case -1:
                //throws exception of d00m
                throw new Exception("Exception of d00m! Operação não suportada!");

            //coef > 0
            case 1:
                final = new TSPVelocity(s.transpositions);
                //concatena i vezes para a parte inteira de coef
                for (int i = 0; i < (int)coef; ++i)
                {
                    final.transpositions.AddRange(s.transpositions);
                }
                //trunca v por (1-c)*|v| e adiciona
                final.transpositions.AddRange(s.transpositions.GetRange(0, (int)Math.Floor(s.transpositions.Count * (coef % 1))));
                break;

            default:
                //YOU'LL NEVER GET ME ALIVE !!!
                break;
            }
            /* retorna o objeto com o resultado */
            return(final);
        }