Advertisement
Guest User

Untitled

a guest
Nov 27th, 2014
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.90 KB | None | 0 0
  1. /*******************************************************************
  2. * Problema de decodificación de señal discreta,
  3. solución con ascensión de colinas
  4. *********************************************************************/
  5.  
  6. #include <string.h>  // Funcion memset
  7. #include <stdlib.h>
  8. #include <iostream>
  9. #include <omp.h>
  10. #include <time.h>
  11. using namespace std;
  12.  
  13. //#define NUMGENALE 10000000
  14. #define NUMGENALE 150000
  15. //#define NUMGENALE 20
  16.  
  17.  
  18.  
  19.  
  20. long unsigned int generar_siguiente_vecino(int nt, int nr, int*x, int *tA, int **A, int *SOA, int VOA, int *H) {
  21.     int **hijos = (int**) malloc(sizeof(int)*nt);
  22.  
  23.     long unsigned int mejorValor = -1;
  24.     /* Para generar los vecinos iteramos sobre el vector solución actual cambiando cada
  25.     una de las componentes, así tendremos tantos vecinos como número de componentes tiene
  26.     el vector de envío. Almacenaremos en la variable hijos */
  27.     for(int i = 0; i < nt;i++) {
  28.         hijos[i] = (int*) malloc(sizeof(int)*nt);
  29.         // Copio la solución actual en cada uno de los vecinos,
  30.         // ya que solo va a cambiar un valor.
  31.         copiar(hijos[i], SOA, nt);
  32.         // Relacion de vecindad, cambio un valor de cada vector de forma aleatoria.
  33.         // Cojo un número aleatorio entre 0 y el tamaño del alfabeto de la componente actual.
  34.         int valorCambiado = rand() % tA[i];
  35.    
  36.         // Si da la casualidad de que el valor cambiado es el mismo que ya tengo, cojo el
  37.         // siguiente
  38.         if (A[i][valorCambiado] == hijos[i][i]) {
  39.             valorCambiado = (valorCambiado + 1) % tA[i];       
  40.         }
  41.  
  42.         // Cambio el valor por el nuevo.
  43.         hijos[i][i] = A[i][valorCambiado];
  44.    
  45.         // Calculo su fitness.
  46.         long unsigned int valor = calcularvalor(hijos[i], x, A, H, nt, nr);
  47.  
  48.         // Si es mejor que el valor óptimo actual lo cambio y me quedo con esta solución,
  49.         if (valor < VOA) {
  50.             VOA = valor;
  51.             mejorValor = VOA;
  52.             copiar(SOA, hijos[i], nt);
  53.         }
  54.         free(hijos[i]);
  55.     }
  56.     free(hijos);
  57.     // Devuelvo el mejor valor fitness y en SOA tendremos el mejor vecino al pasarlo por referencia.
  58.     // En caso de que no hayamos encontrado una mejor solución devolveremos -1.
  59.     // -1 será nuestra señal de que la ascensión se ha estancado.
  60.     return mejorValor;
  61.  
  62. }
  63.  
  64. long unsigned int ascensionColinas(int nt,int nr,int *x,int **A,int *tA,int *H,int *SOA, int np)
  65. {
  66.     long int VOA;
  67.    
  68.     // Genero un aleatorio inicial.
  69.     generaraleatorio(SOA,nt,A,tA);
  70.     // Calculo su fitness.
  71.     VOA=calcularvalor(SOA,x,A,H,nt,nr);
  72.     bool fin = false;
  73.     while (!fin) {
  74.         /* Con este método genero, de todos los vecinos el mejor o si la función
  75.         devuelve -1 es simbolo de estancamiento. */
  76.         long unsigned int nextVOA = generar_siguiente_vecino(nt, nr, x, tA, A, SOA, VOA, H);
  77.         // Si nos devuelven -1 terminamos el procedimiento
  78.         // Si no, nos quedamos con el valor devuelto por la función anterior y seguimos.
  79.         if (nextVOA != -1) VOA = nextVOA;
  80.         else fin = true;
  81.     }
  82.     return VOA;
  83. }
  84.  
  85.  
  86. int main (void)
  87. {
  88.     int  nt,nr; //número de componentes de la señal transmitida y recibida
  89.     int *x; //vector recibido
  90.     int **A; //Alfabetos para los datos a transferir
  91.     int *tA; //tamaños de los alfabetos
  92.     int *H; //matriz de transferencia
  93.     long unsigned int valsol = -1; //valor de la solución
  94.     int numReinicios; // Numero de reinicios de la ascension de colinas.
  95.     int *sol;
  96.     int *solpart;
  97.     leer(&nt,&nr,&x,&A,&tA,&H);
  98.     // El numero de reinicios es la variable que venía con el modelo NUMGENALE
  99.     numReinicios = NUMGENALE;
  100.  
  101.     // Cojo el número de threads que se van a generar.
  102.     int numThreads = omp_get_max_threads();
  103.     // Si tengo mas procesadores que reinicios pongo un hilo por reinicio.
  104.     if (numThreads > numReinicios) {
  105.         numThreads = numReinicios;
  106.         omp_set_num_threads(numThreads);
  107.     }
  108.  
  109.     /* Inicializo el espacio de memoria compartida, en estos
  110.     vectores los threads colocarán la mejor solución que se va
  111.     encontrando. Tanto el valor fitness como la solucion en si. */
  112.     int *VOAS = (int*) malloc(sizeof(int)*numThreads);
  113.     int **SOAS = (int**)malloc(sizeof(int)*numThreads);
  114.     for(int i = 0; i < numThreads; i++) SOAS[i] =(int*) malloc(sizeof(int)*nt);
  115.  
  116.     // A partir de aquí se hace en paralelo.
  117.     #pragma omp parallel private(valsol, sol, solpart)
  118.     {
  119.  
  120.     // En este vector irá la mejor solución encontrada por cada hilo.
  121.     sol = (int*) malloc(sizeof(int)*nt);
  122.     // En este vector guardaremos la mejor solución encontrada por cada hilo en cada reinicio.
  123.     solpart = (int *) malloc(sizeof(int)*nt);
  124.     int np = omp_get_thread_num();
  125.     /* Cambio la semilla de generación aleatoria utilizando el tiempo
  126.     actual y para que cada hilo explore una zona distinta utilizo el identificador de proceso */
  127.     srand(time(NULL)  + np);
  128.  
  129.     // Inicializo SOA.
  130.     for(int j=0;j<nt;j++)
  131.     {
  132.          sol[j]=-1;
  133.     }
  134.  
  135.     // Calculo para cada hilo, los reinicios que le tocan
  136.     /* Ejemplo: son 15 reinicios y tenemos 4 hilos.
  137.     Hilo 1: Iteraciones 0-3
  138.     Hilo 2: Iteraciones 4-8
  139.     Hilo 3: Iteraciones 9-11
  140.     Hilo 4: Iteraciones 12-14
  141.     */
  142.     int range = numReinicios / numThreads;
  143.     int rest = numReinicios % numThreads;
  144.     int myStart = np*range;
  145.     int myEnd = (np+1)*range;
  146.  
  147.     if (np < rest) {
  148.         myStart += (np);
  149.         myEnd += (np+1);
  150.     } else {
  151.         myStart += rest;
  152.         myEnd += rest;
  153.     }
  154.  
  155.     // Inicializo VOA a un valor muy alto.
  156.     valsol = -1;
  157.  
  158.     // Cada hilo hace su rango de reinicios.
  159.     for (int i = myStart; i < myEnd ;i++) {
  160.         // Método principal de la ascensión de colinas.
  161.         long unsigned int valsolreinicio = ascensionColinas(nt,nr,x,A,tA,H,solpart, np);
  162.         // Tras terminar el procedimiento tendremos en solpart el máximo local.
  163.         // En valsolreinicio tendremos el valor fitness de solpart.
  164.         // Si valsolreinicio (maximo local) es menor que valsol (maximo global)
  165.         // cambio valsolreinicio por valsol ya que es mejor solución global.
  166.         // y además copio en sol (la mejor solución global) solpart (mejor solución local).
  167.         if (valsolreinicio < valsol || valsol == -1) {
  168.             valsol = valsolreinicio;
  169.             copiar(sol, solpart, nt);
  170.         }
  171.     }
  172.     // Al terminar las iteraciones que le toca a cada hilo guardamos en el vector
  173.     // que inicializamos antes de entrar a iterar tanto la mejor solución como el valor de la misma.
  174.     VOAS[np] = valsol;
  175.     SOAS[np] = sol;
  176.     }
  177.  
  178.     // Al final tenemos dos vectores, uno con los valores de las mejores soluciones encontradas.
  179.     // y otro con las soluciones en sí.
  180.     // El hilo maestro de las soluciones de cada proceso busca la mejor.
  181.     valsol = VOAS[0];
  182.     sol = (int*) malloc(sizeof(int)*nt);
  183.  
  184.     copiar(sol, SOAS[0], nt);
  185.     escribirVector(sol, nt);
  186.     // en este bucle simplemente buscamos la mejor solución
  187.     for(int i = 1; i < numThreads; i++) {
  188.         if (VOAS[i] < valsol) {
  189.             valsol = VOAS[i];
  190.             copiar(sol, SOAS[i], nt);
  191.         }
  192.         free(SOAS[i]);
  193.     }
  194.     free(SOAS[0]);
  195.     free(SOAS);
  196.     free(VOAS);
  197.     // Imprimimos el resultado.
  198.     cout << valsol << endl;
  199.     for(int j=0;j<nt-1;j++)
  200.     {
  201.          cout << sol[j] << " ";
  202.     }  
  203.     cout <<sol[nt-1]<<endl;
  204.     free(sol);
  205.     liberar(nt,nr,&x,&A,&tA,&H);
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement