mitkonikov

MaxCut

May 14th, 2023
908
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.72 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <mpi.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5.  
  6. #define max_nodes 30
  7. #define max_edges 500
  8. #define send_data_tag 2001
  9. #define return_data_tag 2002
  10.  
  11.  
  12. int edge_u[max_edges];
  13. int edge_v[max_edges];
  14. int edge_c[max_edges];
  15.  
  16.  
  17. int edge2_u[max_edges];
  18. int edge2_v[max_edges];
  19. int edge2_c[max_edges];
  20.  
  21.  
  22. inline long long cut(long long mask, int num_edges, int *edge_u, int *edge_v, int *edge_c) {
  23.     int result = 0;
  24.     for (int i = 0; i < num_edges; i++) {
  25.         if ((mask & (1LL << edge_u[i])) != (mask & (1LL << edge_v[i]))) {
  26.             result += edge_c[i];
  27.         }
  28.     }
  29.     return result;
  30. }
  31.  
  32. int main(int argc, char *argv[]) {
  33.     long long best, partial_best;
  34.     MPI_Status status;
  35.     int my_id, root_process, ierr, i, num_nodes, num_edges, num_procs,
  36.         an_id, start_mask, end_mask, num_masks;
  37.  
  38.     // Razdeli na vec procesov
  39.     ierr = MPI_Init(&argc, &argv);
  40.  
  41.     root_process = 0;
  42.  
  43.     // Najdi id mojega procesa in koliko procesov je bilo zacetih
  44.  
  45.     ierr = MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
  46.     ierr = MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
  47.  
  48.     if(my_id == root_process) {
  49.  
  50.         // Sem zacetni/glavni procesor (MASTER)
  51.  
  52.         printf("Vpisi stevilo zaporednih stevilk da jih sestejem: ");
  53.         scanf("%i", &num_nodes);
  54.         scanf("%i", &num_edges);
  55.  
  56.         if(num_nodes > max_nodes || num_edges > max_edges) {
  57.             printf("Graf je prevelik! \n");
  58.             exit(1);
  59.         }
  60.  
  61.         num_masks = (1LL << num_nodes);
  62.  
  63.         for(i = 0; i < num_edges; i++) {
  64.             scanf("%i", &edge_u);
  65.             scanf("%i", &edge_v);
  66.             scanf("%i", &edge_c);
  67.         }
  68.  
  69.  
  70.  
  71.         // Povprecno stevilo podmnozic, ki jih en proces obdeluje
  72.         long long avg_masks_per_process = num_masks / num_procs;
  73.  
  74.  
  75.         for(an_id = 1; an_id < num_procs; an_id++) {
  76.             //Mnozica, ki jo proces obdela se zacne pri tem ideksu
  77.             start_mask = an_id * avg_masks_per_process;
  78.             //in se konca pri tem indeksu
  79.             end_mask   = (an_id + 1) * avg_masks_per_process - 1;
  80.  
  81.  
  82.             if((num_masks - end_mask) < avg_masks_per_process)
  83.             end_mask = num_masks - 1;
  84.  
  85.  
  86.             ierr = MPI_Send( &start_mask, 1 , MPI_LONG,
  87.                 an_id, send_data_tag, MPI_COMM_WORLD);
  88.             ierr = MPI_Send( &end_mask, 1 , MPI_LONG,
  89.                 an_id, send_data_tag, MPI_COMM_WORLD);
  90.  
  91.  
  92.             ierr = MPI_Send( &num_edges, 1 , MPI_INT,
  93.                 an_id, send_data_tag, MPI_COMM_WORLD);
  94.             ierr = MPI_Send( edge_u, num_edges, MPI_INT,
  95.                 an_id, send_data_tag, MPI_COMM_WORLD);
  96.             ierr = MPI_Send( edge_v, num_edges, MPI_INT,
  97.                 an_id, send_data_tag, MPI_COMM_WORLD);
  98.             ierr = MPI_Send( edge_c, num_edges, MPI_INT,
  99.                 an_id, send_data_tag, MPI_COMM_WORLD);
  100.         }
  101.  
  102.         // Izracunamo se del za MASTERA
  103.  
  104.         best = 0;
  105.         for (long long mask = 0; mask < avg_masks_per_process + 1; mask++) {
  106.             best = std::max(best, cut(mask, num_edges, edge_u, edge_v, edge_c));
  107.         }
  108.  
  109.         // Prejmi max-cut iz vsakega procesa
  110.  
  111.         for(an_id = 1; an_id < num_procs; an_id++) {
  112.  
  113.             ierr = MPI_Recv( &partial_best, 1, MPI_LONG, MPI_ANY_SOURCE,
  114.                 return_data_tag, MPI_COMM_WORLD, &status);
  115.  
  116.             best = std::max(best, partial_best);
  117.         }
  118.  
  119.         printf("Vse skupaj je: %ld\n", best);
  120.     }
  121.  
  122.     else {
  123.  
  124.         // Nisem glavni proces (SLAVE)
  125.  
  126.         ierr = MPI_Recv( &start_mask, 1 , MPI_LONG,
  127.             root_process, send_data_tag, MPI_COMM_WORLD, &status);
  128.         ierr = MPI_Recv( &end_mask, 1 , MPI_LONG,
  129.             root_process, send_data_tag, MPI_COMM_WORLD, &status);
  130.  
  131.  
  132.         ierr = MPI_Recv( &num_edges, 1 , MPI_INT,
  133.             root_process, send_data_tag, MPI_COMM_WORLD, &status);
  134.         ierr = MPI_Recv( edge2_u, num_edges, MPI_INT,
  135.             root_process, send_data_tag, MPI_COMM_WORLD, &status);
  136.         ierr = MPI_Recv( edge2_v, num_edges, MPI_INT,
  137.             root_process, send_data_tag, MPI_COMM_WORLD, &status);
  138.         ierr = MPI_Recv( edge2_c, num_edges, MPI_INT,
  139.             root_process, send_data_tag, MPI_COMM_WORLD, &status);
  140.  
  141.         // Izracunaj max-cut za vsak proces
  142.         partial_best = 0;
  143.         for (long long mask = start_mask; mask <= end_mask; mask++) {
  144.             partial_best = std::max(partial_best, cut(mask, num_edges, edge2_u, edge2_v, edge2_c));
  145.         }
  146.  
  147.         // Poslji max-cut nazaj k glavnemu procesu
  148.         ierr = MPI_Send( &partial_best, 1, MPI_LONG, root_process,
  149.             return_data_tag, MPI_COMM_WORLD);
  150.     }
  151.     ierr = MPI_Finalize();
  152. }
Advertisement
Add Comment
Please, Sign In to add comment