Soving knapsack problem

Dependencies:   mbed mbed-rtos

main.cpp

Committer:
vferman
Date:
2022-03-28
Revision:
1:39e36a5c11e0
Parent:
0:1ea8993f6b18

File content as of revision 1:39e36a5c11e0:

#include "mbed.h"
#include "rtos.h"
#include <queue>


//#define DELAY_INSIDE
//#define DELAY_BTWN
#define DELAY_DISPLAY

#define DELAY_INSIDE_TIME  1000    
#define DELAY_BTWN_TIME   311   
#define DELAY_DISPLAY_TIME   100   


#define ARRAY_SIZE   16
#define THREAD_ARRAY_SIZE   10
 
typedef struct{
   int tid;
   int pid;
   int cap;
   int weights[ARRAY_SIZE];
   int values[ARRAY_SIZE];
   int ts_begin;   
   int ts_end;
   int proc_time;
   int n;
}problema;

typedef struct{
   int tid;
   int pid;
   int cap;
   int weights[ARRAY_SIZE];
   int values[ARRAY_SIZE];
   int ts_begin;   
   int ts_end;
   int proc_time;
   int opt;  
}solucion;


Timer t;
DigitalOut led1(LED1);  // Red
DigitalOut led2(LED2);  // Green
DigitalOut led3(LED3);  // Blue

osMutexDef (mutex_leds);//mutex for LEDs
osMutexDef (mutex_p);   //problem queue mutex
osMutexDef (mutex_s);   //solution queue mutex 


osMutexId  (mutex_leds_id); // LED mutex ID
osMutexId  (mutex_p_id);    // problem queue mutex ID
osMutexId  (mutex_s_id);    // solution queue mutex ID


queue <problema> problem_q;
queue <solucion> solution_q;

Serial pc(USBTX, USBRX);

#ifdef DEBUG 
int printP(problema p){
    int i;
    printf("\n#P \t#T \tCap \t#items");
    printf("\n%i \t%i \t%i \t%i\n",p.pid,p.tid,p.cap,p.n);
    printf("  Weights \tValues\n");
    printf("  ------- \t------\n");
    i=0;
    while (p.weights[i]>-5 && p.values[i]>-5 && i<30){ 
        printf("%i.    %i \t%i\n", i+1, p.weights[i],p.values[i]);
        i++;
    }
    printf("\n");
    return 1;
}

int printS(solucion s){
    int i;
    printf("\n#S \t#T \tCap \tOpt Val \tBegin \t\tEnd \t\tProc");
    printf("\n%i \t%i \t%i \t%i \t\t%ius \t%ius \t%ius\n", s.pid, s.tid, s.cap, s.opt, s.ts_begin, s.ts_end, s.proc_time);
    printf("  Weights \tValues \t(included items)\n");
    printf("  ------- \t------\n");
    i=0;
    while (s.weights[i]>-5 && s.values[i]>-5 && i<30){ 
        printf("%i.    %i \t%i\n", i+1, s.weights[i],s.values[i]);
        i++;
    }
    printf("\n");
    return 1;
}

#else
#endif

int printF(solucion s){
    int i;
    printf("\n#");
    printf("%i,", s.tid);
    printf("%i,", s.pid);
    printf("%i", s.cap);
    i=0;
    while (s.weights[i]>=0 && s.values[i]>=0 && i<30){ 
        printf(",%i,%i", s.weights[i],s.values[i]);
        i++;
    }
    printf(",%i", s.ts_begin);
    printf(",%i", s.ts_end);
    printf(",%i", s.proc_time);
    printf("*");
    return 1;
}

int my_atoi(char *str) {
    int res = 0; // Initialize result
    // Iterate through all characters of input string and update result
    for (int i = 0; str[i] != '\0'; ++i)
        res = res*10 + str[i] - '0';
    return res;
}

// A utility function that returns maximum of two integers
int max(int a, int b) { return (a > b)? a : b; }

// Returns the maximum value that can be put in a knapsack of capacity W
solucion knapSackP(problema p, int t){
   solucion s;
   s.ts_begin=t;//t.read_us();
   int i, w,index=0;
   int K[p.n+1][p.cap+1];
   // Build table K[][] in bottom up manner
   for (i = 0; i <= p.n; i++){
       for (w = 0; w <= p.cap; w++){
           if (i==0 || w==0)
               K[i][w] = 0;
           else if (p.weights[i-1] <= w)
               K[i][w] = max(p.values[i-1] + K[i-1][w-p.weights[i-1]],  K[i-1][w]);
           else
                 K[i][w] = K[i-1][w];
       }
   }
   s.opt = K[p.n][p.cap];
     
   w = p.cap;
   for (i=p.n; i>0; i--){
       if(K[i][w] != K[i-1][w]){
          //printf("(p.weights=%i,val=%i)-> ",p.weights[i-1],val[i-1]);
          s.weights[index]=p.weights[i-1];
          s.values[index++]=p.values[i-1];
          w=w-p.weights[i-1];
       }
   }
   s.weights[index]=-5;
   s.values[index]=-5;
   
   
   return s;
}
 
void led_func(uint32_t n){
    uint32_t temp = ~((n%7)+1);
    led3 = temp&(uint32_t)1;
    led2 = (temp&(uint32_t)2)>>1;
    led1 = (temp&(uint32_t)4)>>2;   
}

void led_thread(void const *argument)
{
    uint32_t cont =0;
    while (true) {
        osMutexWait(mutex_leds_id, osWaitForever); //request lock
        led_func(cont);
        osMutexRelease(mutex_leds_id);              //unlock
        Thread::wait((uint32_t)argument );
        cont++;
    }
}

void worker_thread(void const *argument){
     problema p;
     solucion s;    
     
     while (true) {
        osMutexWait(mutex_p_id, 1000);
        if (!problem_q.empty()){
                p = problem_q.front();
                problem_q.pop();
                osMutexRelease(mutex_p_id);
                
                #ifdef DEBUG 
                    p.tid = (uint32_t)argument;
                    printf("-------------------------------------------------------");
                    printP(p);
                #endif
                
                //printf("\nT1:%i\n",t.read_us()); 
                s = knapSackP(p,t.read_us());
                s.ts_end=t.read_us();
                //printf("\nT2:%i\n",t.read_us());
                s.proc_time=s.ts_end-s.ts_begin;
                s.tid = (uint32_t)argument;
                s.pid = p.pid;
                s.cap = p.cap;
                
                #ifdef DEBUG 
                    printS(s);
                #endif

                osMutexWait(mutex_s_id, 1000);
                    solution_q.push(s);
                osMutexRelease(mutex_s_id);  
                
                osMutexWait(mutex_leds_id, 1000); //request lock
                    led_func((uint32_t)argument);
                osMutexRelease(mutex_leds_id);    //unlock     
                
            }else{
                osMutexRelease(mutex_p_id);
            }
        
        osThreadYield();
        #ifdef DELAY_INSIDE
            Thread::wait(DELAY_INSIDE_TIME);
        #endif
    }
}

int main(){
    t.start();
    problema *problemas_array;          //array to store the parsed problems
    Thread *threads_array[THREAD_ARRAY_SIZE]; //array to instance the threads
    char buffer[4];                 //buffer to atoi convertion
    solucion s;             // var to pop the solutions from solution queue
    char input_char;    //received char form serial input
    char stage = 0;    //State of the parsing loop
    char parseFlag =1;  //flag to exit the input loop
    char displayFlag =1;   //flag to exit the display solution loop 
    int i;                  //used to indexing alog the differents arrays
    int number_threads;     //number of threads recived
    int number_threads_temp;  //used to verify if we have recived the number of threads
    char problema_counter;     //problem counter
    char item_counter;          //
    char buffer_counter;        //used to indexing the buffer used to atoi convertion
    pc.baud (115200);   //Baudrate
    
    
    while (true) {
        problemas_array =(problema *) malloc(10*sizeof(problema)) ;
        problema_counter=0;
        number_threads=0;
        item_counter=0;
        buffer_counter=0;
        buffer[0]='\0';
        buffer[3]='\0';
        i=0;
        parseFlag=1;
        displayFlag =1;
        stage = 0;
         
        while(parseFlag){               //input loop       
            input_char = getchar();     //receive char from Serial
            //Parsing the message
            if (input_char=='&'){   //start of message
                buffer[0]='\0';
                buffer_counter=0;
                problema_counter=0;
                item_counter=0;
                number_threads=0;
                stage = 1;
                //printf("Stage %i\n", stage);
            }else if (input_char=='#'){    //end of threads number
                buffer[0]='\0';
                buffer_counter=0;
                stage = 2;
                //printf("Stage %i\n", stage);
            }else if (input_char >= '0' && input_char <= '9'){ //number received
                buffer[buffer_counter++]=input_char;
                buffer[buffer_counter]='\0';
            }else if (input_char=='*'){             //end of line
                if (stage==1){
                     number_threads_temp = my_atoi(&buffer[0]);
                     number_threads = (number_threads_temp>0 && number_threads_temp<=10)? number_threads_temp: 5;
                    //printf("Number of threads = %i\n", number_threads);
                    //printf("Problema = %i\n", problema_counter);
                    buffer[0]='\0';
                    buffer_counter=0;
                }else if (stage==4){
                    problemas_array[problema_counter].values[item_counter++]=my_atoi(&buffer[0]);
                    problema_counter++;
                    item_counter=0;
                    //printf("4Problema = %i\n", problema_counter);
                }else if (stage==5){
                    problemas_array[problema_counter].values[item_counter++]=my_atoi(&buffer[0]);
                    problemas_array[problema_counter].values[item_counter]=-5;
                    problemas_array[problema_counter].weights[item_counter]=-5;
                    problemas_array[problema_counter].n=item_counter;
                    problema_counter++;
                    item_counter=0;
                    //printf("Problema = %i\n", problema_counter);
                }  
                
            }else if (input_char==','){         //delimiter do the message
                if (stage==2){
                    problemas_array[problema_counter].pid = my_atoi(&buffer[0]);
                    stage=3;
                    //printf("Stage %i\n", stage);
                }else if (stage==3){
                    problemas_array[problema_counter].cap = my_atoi(&buffer[0]);
                    stage=4;
                    //printf("Stage %i\n", stage);
                } else if (stage==4){
                    problemas_array[problema_counter].weights[item_counter]=my_atoi(&buffer[0]);
                    stage=5;
                    //printf("Stage %i\n", stage);
                }else if (stage==5){
                    problemas_array[problema_counter].values[item_counter++]=my_atoi(&buffer[0]);
                    stage=4;
                    //printf("Stage %i\n", stage);
                }
                buffer[0]='\0';
                buffer_counter=0;
            }else if (input_char=='\n'){    //newline received
                buffer[0]='\0';
                buffer_counter=0;
            }else if (input_char=='X'){    //end of message
                buffer[0]='\0';
                buffer_counter=0;
                stage=0;
                //printf("\nNumber of threads = %i\n", number_threads);
                fflush(stdout);
                fflush(stdin);
                parseFlag =0;               //exit form input loop
            }
        }
        //printf("\nNumber of threads = %i", number_threads);
        //printf("\nNumber of problems = %i", problema_counter);
        printf("\n Parse Finished \n");
        
        osMutexWait(mutex_p_id, osWaitForever);         //request lock
        for (i=0; i<problema_counter; i++){     
            problem_q.push(problemas_array[i]);
        }
        osMutexRelease(mutex_p_id);                    //unlock
        
        free(problemas_array);
        
        i=0;
        while (i<number_threads){
            threads_array[i]= new Thread(worker_thread,(void *)(i));
                #ifdef DELAY_BTWN
            Thread::wait(DELAY_BTWN_TIME);
            #endif
            i++;
        }
        
        #ifdef DELAY_DISPLAY
            Thread::wait(DELAY_DISPLAY_TIME);
        #endif
        
                
        while(displayFlag){
                displayFlag=0;
                printf("\n&%i*",number_threads);
                
                while(!solution_q.empty()){
                    osMutexWait(mutex_s_id, osWaitForever);
                        if (!solution_q.empty()){
                            s = solution_q.front();
                            solution_q.pop();
                            printF(s);
                        }    
                        osMutexRelease(mutex_s_id);
                }
                  
                
        }
        
      
        //i=0;
        //while (i<number_threads) threads_array[i];
        free(threads_array);
        
        //osMutexWait(mutex_leds_id, osWaitForever); //request lock
          //  led_func(6);
        //osMutexRelease(mutex_leds_id);              //unlock
    }
}