root/vtcross/trunk/src/cognitive_engines/CognitiveEngine.cpp @ 230

Revision 230, 19.9 KB (checked in by trnewman, 15 years ago)

Added a loop in the demo to actually adapt.

Added simple adaptation functionality and proper db querying in the CE.

Line 
1/* Virginia Tech Cognitive Radio Open Source Systems
2 * Virginia Tech, 2009
3 *
4 * LICENSE INFORMATION GOES HERE
5 */
6
7/* DESCRIPTION OF FILE.
8 */
9
10
11#include <cstdlib>
12#include <cstring>
13#include <stdint.h>
14#include <math.h>
15
16#include "vtcross/common.h"
17#include "vtcross/components.h"
18#include "vtcross/containers.h"
19#include "vtcross/debug.h"
20#include "vtcross/error.h"
21#include "vtcross/socketcomm.h"
22#include "vtcross/cbr.h"
23
24#include "cbr.c"
25
26#include <sqlite3.h>
27#include <sqlite3ext.h>
28
29
30
31static cbr myCBR;
32
33CognitiveEngine::CognitiveEngine()
34{
35    LOG("Creating Cognitive Engine.\n");
36    SML_present = false;
37    commandSocketFD = -1;
38}
39
40
41CognitiveEngine::~CognitiveEngine()
42{
43        cbr_free(myCBR);
44    delete [] pList;
45    delete [] oList;
46    delete [] uList;
47    delete [] radioInfo;
48}
49
50
51CognitiveEngine::CognitiveEngine(const char* serverName, const char* serverPort, \
52        const bool SML)
53{
54    LOG("Creating Cognitive Engine.\n");
55
56    pList = new Parameter[10];
57    oList = new Observable[10];
58    uList = new Utility[10];
59    radioInfo = new Radio_Info;
60
61    ConnectToRemoteComponent(serverName, serverPort, SML);
62}
63
64
65void
66CognitiveEngine::SendComponentType()
67{
68    SendMessage(commandSocketFD, "response_engine_cognitive");
69    LOG("Cognitive Engine responded to GetRemoteComponentType query.\n");
70}
71
72
73void
74CognitiveEngine::ConnectToRemoteComponent(const char* serverName, \
75        const char* serverPort, const bool SML)
76{
77    commandSocketFD = ClientSocket(serverName, serverPort);
78
79    SML_present = SML;
80
81    if(SML) {
82        RegisterComponent();
83        RegisterServices();
84        LOG("Cognitive Engine connected to SML at %s.\n", serverName);
85        ReceiveRadioConfiguration();
86        ReceiveExperience();
87    }
88    else {
89        RegisterComponent();
90        LOG("Cognitive Engine connected to shell at %s.\n", serverName);
91        ReceiveRadioConfiguration();
92        ReceiveExperience();
93    }
94}
95
96void
97CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters)
98{
99   LOG("Cognitive Engine:: Receiving feedback.\n");
100       
101        uint32_t numberColumns =
102                radioInfo->numParameters +
103                radioInfo->numUtilities;
104
105        uint32_t obsColumns = radioInfo->numObservables + 1;
106
107        float valList[numberColumns];
108        float obsVals[numberColumns];
109    char *nameList[numberColumns];
110    char *obsList[obsColumns];
111
112    size_t columnObsIndex = 0;
113    for (size_t i = 0; i < radioInfo->numObservables; i++){
114                obsList[columnObsIndex] = (char*)observables[i].name.c_str();
115        columnObsIndex++;
116    } 
117    obsList[columnObsIndex] = "utility";
118
119    size_t columnIndex = 0;
120    for (size_t i = 0; i < radioInfo->numParameters; i++){
121                nameList[columnIndex] = (char*)parameters[i].name.c_str();
122        columnIndex++;
123    }   
124    for (size_t i = 0; i < radioInfo->numUtilities; i++){
125                nameList[columnIndex] = (char*)uList[i].name.c_str();
126        columnIndex++;
127    }   
128
129        size_t obsValueIndex = 0;
130    for(size_t i = 0; i < radioInfo->numObservables; i++) {
131                obsVals[obsValueIndex] = observables[i].value;
132                obsValueIndex++;
133        }
134        // Calculate Utility
135        float newUtilityValue = 0;
136
137    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
138                newUtilityValue = newUtilityValue + (uList[i].target - observables[i].value);
139        }
140        obsVals[obsValueIndex] = newUtilityValue;
141
142        size_t returnValueIndex = 0;
143    for(size_t i = 0; i < radioInfo->numParameters; i++) {
144                valList[returnValueIndex] = parameters[i].value;
145                returnValueIndex++;
146        }
147    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
148                valList[returnValueIndex] = uList[i].target;
149                returnValueIndex++;
150        }
151
152
153        cbr_update(myCBR, nameList, obsList, valList, obsVals,
154                        numberColumns, obsColumns);
155}
156
157
158void
159CognitiveEngine::WaitForSignal()
160{
161    char buffer[256];
162
163    while(true) {
164        memset(buffer, 0, 256);
165       
166        ReadMessage(commandSocketFD, buffer);
167
168        // TODO this is ugly... is there a better way? Doesn't strcmp compare the
169        // whole string?  We only need to compare until we find a single different
170        // byte...
171        //
172        // If we send integer op codes rather than strings, this process will be
173        // MUCH faster since instead of donig string compares we can simply
174        // switch on the integer value...
175        if(strcmp(buffer, "update_performance") == 0) {
176           
177            /* Receive Set of current Parameters */
178            memset(buffer, 0, 256);
179            ReadMessage(commandSocketFD,buffer);
180            uint32_t numParameters = atoi(buffer);
181   
182            Parameter *p = new Parameter[numParameters];
183 
184            for(size_t i = 0; i < numParameters; i++) {
185                memset(buffer, 0, 256);
186                ReadMessage(commandSocketFD, buffer);
187                p[i].name = std::string(buffer);
188   
189                memset(buffer, 0, 256);
190                ReadMessage(commandSocketFD, buffer);
191                p[i].value = atof(buffer);
192            }
193
194            /* Receive Set of Observables */
195            memset(buffer, 0, 256);
196            ReadMessage(commandSocketFD,buffer);
197            uint32_t numObservables = atoi(buffer);
198   
199            Observable *o = new Observable[numObservables];
200 
201            for(size_t i = 0; i < numObservables; i++) {
202                memset(buffer, 0, 256);
203                ReadMessage(commandSocketFD, buffer);
204                o[i].name = std::string(buffer);
205   
206                memset(buffer, 0, 256);
207                ReadMessage(commandSocketFD, buffer);
208                o[i].value = atof(buffer);
209            } 
210
211                        ReceiveFeedback(o,p);
212
213            delete [] o;
214            delete [] p;
215                }
216                else if(strcmp(buffer, "request_optimization") == 0) {
217           
218            /* Receive Set of Observables */
219                        LOG("\nCognitive Engine:: Receiving Observable Parameters\n");
220
221            memset(buffer, 0, 256);
222            ReadMessage(commandSocketFD,buffer);
223            uint32_t numObservables = atoi(buffer);
224   
225            Observable *o = new Observable[numObservables];
226 
227            for(size_t i = 0; i < numObservables; i++) {
228                memset(buffer, 0, 256);
229                ReadMessage(commandSocketFD, buffer);
230                o[i].name = std::string(buffer);
231   
232                memset(buffer, 0, 256);
233                ReadMessage(commandSocketFD, buffer);
234                o[i].value = atof(buffer);
235            } 
236
237            /* Receive Set of current Parameters */
238                        LOG("Cognitive Engine:: Receiving Current Transmission Parameters\n");
239
240            memset(buffer, 0, 256);
241            ReadMessage(commandSocketFD,buffer);
242            uint32_t numCurrentParameters = atoi(buffer);
243   
244            Parameter *cp = new Parameter[numCurrentParameters];
245 
246            for(size_t i = 0; i < numCurrentParameters; i++) {
247                memset(buffer, 0, 256);
248                ReadMessage(commandSocketFD, buffer);
249                cp[i].name = std::string(buffer);
250   
251                memset(buffer, 0, 256);
252                ReadMessage(commandSocketFD, buffer);
253                cp[i].value = atof(buffer);
254            } 
255                        LOG("Cognitive Engine:: Processing parameters....\n");
256
257            Parameter *solutionSet;
258                       
259                        solutionSet = GetSolution(o,cp);
260
261            // TODO need to actually do something with the observables here
262           
263                        LOG("Cognitive Engine:: Sending Optimal Parameters to Application.\n");
264                        char numParametersChar[10];
265                        char solutionValue[50];
266                        sprintf(numParametersChar,"%i",radioInfo->numParameters);
267                        SendMessage(commandSocketFD,numParametersChar);
268            for(size_t i = 0; i < radioInfo->numParameters; i++) {
269                SendMessage(commandSocketFD,solutionSet[i].name.c_str());
270                memset(solutionValue, 0, 50);
271                            sprintf(solutionValue,"%f",solutionSet[i].value);
272                SendMessage(commandSocketFD,solutionValue);
273                        }
274
275            delete [] o;
276            delete [] cp;
277        }
278        else if(strcmp(buffer, "query_component_type") == 0) {
279            SendComponentType();
280        }
281        else if(strcmp(buffer, "connect_sml") == 0) {
282            /* This command implies that we are disconnecting from the shell and
283             * connecting to a SML component. */
284            char serverName[256];
285            char serverPort[256];
286            // TODO is this going to end up being too slow?
287            memset(serverName, 0, 256);
288            memset(serverPort, 0, 256);
289
290            ReadMessage(commandSocketFD, serverName);
291            ReadMessage(commandSocketFD, serverPort);
292
293            /* Only continue if we are currently connected to a shell. */
294            if(!SML_present) {
295                DeregisterComponent();
296
297                shutdown(commandSocketFD, 2);
298                close(commandSocketFD);
299
300                ConnectToRemoteComponent(serverName, serverPort, true);
301            }
302        }
303        else if(strcmp(buffer, "disconnect_sml") == 0) {
304            /* This command implies that we are disconnecting from the SML and
305             * connecting to a shell component. */
306            char serverName[256];
307            char serverPort[256];
308            // TODO is this going to end up being too slow?
309            memset(serverName, 0, 256);
310            memset(serverPort, 0, 256);
311
312            ReadMessage(commandSocketFD, serverName);
313            ReadMessage(commandSocketFD, serverPort);
314
315            /* We only want to do this if we are actually connected to an SML
316             * currently. */
317            if(SML_present) {
318                DeregisterServices();
319
320                shutdown(commandSocketFD, 2);
321                close(commandSocketFD);
322
323                ConnectToRemoteComponent(serverName, serverPort, false);
324            }
325        }
326        else if(strcmp(buffer, "reset_engine_cognitive") == 0) {
327            Reset();
328        }
329        else if(strcmp(buffer, "shutdown_engine_cognitive") == 0) {
330            Shutdown();
331        }
332    }
333}
334
335
336void
337CognitiveEngine::Shutdown()
338{
339    if(SML_present) {
340        DeregisterServices();
341        DeregisterComponent();
342    }
343    else {
344        DeregisterComponent();
345    }
346    // TODO should something else be happening here?
347}
348
349
350void
351CognitiveEngine::Reset()
352{
353    LOG("Resetting Cognitive Engine.\n");
354
355    if(SML_present) {
356        DeregisterServices();
357        DeregisterComponent();
358    }
359    else {
360        DeregisterComponent();
361    }
362}
363
364
365void
366CognitiveEngine::RegisterComponent()
367{
368    SendMessage(commandSocketFD, "register_engine_cognitive");
369    LOG("Cognitive Engine:: Registration message sent to shell.\n");
370}
371
372void
373CognitiveEngine::DeregisterComponent()
374{
375    SendMessage(commandSocketFD, "deregister_engine_cognitive");
376    LOG("Cognitive Engine:: Deregistration message sent.\n");
377
378    shutdown(commandSocketFD, 2);
379    close(commandSocketFD);
380    commandSocketFD = -1;
381    LOG("Cognitive Engine:: Shell socket closed.\n");
382}
383
384
385void
386CognitiveEngine::RegisterServices()
387{
388    LOG("Cognitive Engine:: Registering services.\n");
389
390    SendMessage(commandSocketFD, "register_service");
391    SendMessage(commandSocketFD, "jam_wifi");
392
393    SendMessage(commandSocketFD, "register_service");
394    SendMessage(commandSocketFD, "signal_detection");
395
396    SendMessage(commandSocketFD, "register_service");
397    SendMessage(commandSocketFD, "max_throughput");
398
399    SendMessage(commandSocketFD, "register_service");
400    SendMessage(commandSocketFD, "jam_bluetooth");
401}
402
403
404void
405CognitiveEngine::DeregisterServices()
406{
407    LOG("Cognitive Engine:: Deregistering services.\n");
408
409    SendMessage(commandSocketFD, "deregister_service");
410    SendMessage(commandSocketFD, "jam_wifi");
411
412    SendMessage(commandSocketFD, "deregister_service");
413    SendMessage(commandSocketFD, "signal_detection");
414
415    SendMessage(commandSocketFD, "deregister_service");
416    SendMessage(commandSocketFD, "max_throughput");
417
418    SendMessage(commandSocketFD, "deregister_service");
419    SendMessage(commandSocketFD, "jam_bluetooth");
420
421}
422
423void
424CognitiveEngine::ReceiveRadioConfiguration()
425{
426    LOG("Cognitive Engine:: Receiving Radio Configuration.\n");
427   
428    char buffer[256];
429 
430    /* Receive Set of Utilities */
431    memset(buffer, 0, 256);
432    ReadMessage(commandSocketFD,buffer);
433    radioInfo->numUtilities = atoi(buffer);
434   
435    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
436        memset(buffer, 0, 256);
437        ReadMessage(commandSocketFD,buffer);
438        uList[i].name = std::string(buffer);
439   
440        memset(buffer, 0, 256);
441        ReadMessage(commandSocketFD,buffer);
442        uList[i].units = std::string(buffer);
443
444        memset(buffer, 0, 256);
445        ReadMessage(commandSocketFD,buffer);
446        uList[i].goal = std::string(buffer);
447   
448        memset(buffer, 0, 256);
449        ReadMessage(commandSocketFD,buffer);
450        uList[i].target = atof(buffer);
451    }
452
453    /* Receive Set of Parameters */
454    memset(buffer, 0, 256);
455    ReadMessage(commandSocketFD, buffer);
456    radioInfo->numParameters = atoi(buffer);
457   
458    for(size_t i = 0; i < radioInfo->numParameters; i++) {
459        memset(buffer, 0, 256);
460        ReadMessage(commandSocketFD, buffer);
461        pList[i].name = std::string(buffer);
462   
463        memset(buffer, 0, 256);
464        ReadMessage(commandSocketFD, buffer);
465        pList[i].units = std::string(buffer);
466
467        memset(buffer, 0, 256);
468        ReadMessage(commandSocketFD, buffer);
469        pList[i].min = atof(buffer);
470   
471        memset(buffer, 0, 256);
472        ReadMessage(commandSocketFD, buffer);
473        pList[i].max = atof(buffer);
474   
475        memset(buffer, 0, 256);
476        ReadMessage(commandSocketFD, buffer);
477        pList[i].step = atof(buffer);
478   
479        memset(buffer, 0, 256);
480        ReadMessage(commandSocketFD,buffer);
481        pList[i].numAffects = atoi(buffer);
482   
483        for(size_t j = 0; j < pList[i].numAffects; j++) {
484            memset(buffer, 0, 256);
485            ReadMessage(commandSocketFD,buffer);
486            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
487                if(uList[k].name == std::string(buffer)){   
488                    pList[i].affection_list[j].u = &uList[k];   
489                    break;
490                }
491            }
492
493            memset(buffer, 0, 256);
494            ReadMessage(commandSocketFD,buffer);
495            pList[i].affection_list[j].relation = std::string(buffer);   
496        }
497    }   
498
499    /* Receive Set of Observables */
500    memset(buffer, 0, 256);
501    ReadMessage(commandSocketFD,buffer);
502    radioInfo->numObservables = atoi(buffer);
503   
504    for(size_t i = 0; i < radioInfo->numObservables; i++) {
505        memset(buffer, 0, 256);
506        ReadMessage(commandSocketFD,buffer);
507        oList[i].name = std::string(buffer);
508   
509        memset(buffer, 0, 256);
510        ReadMessage(commandSocketFD,buffer);
511        oList[i].numAffects = atoi(buffer);
512   
513        for(size_t j = 0; j < oList[i].numAffects; j++) {
514            memset(buffer, 0, 256);
515            ReadMessage(commandSocketFD,buffer);
516            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
517                if(uList[k].name == std::string(buffer)){   
518                    oList[i].affection_list[j].u = &uList[k];   
519                    break;
520                }
521            }
522 
523            memset(buffer, 0, 256);
524            ReadMessage(commandSocketFD,buffer);
525            oList[i].affection_list[j].relation = std::string(buffer);   
526        }
527    }
528
529    SendMessage(commandSocketFD, "receive_config_ack");
530
531        BuildCognitiveEngine();
532}
533
534void
535CognitiveEngine::ReceiveExperience()
536{
537    LOG("Cognitive Engine:: Receiving Experience Report.\n");
538    char buffer[256];
539    uint32_t numberExp;
540   
541    /* Receive number of experience entries */
542    memset(buffer, 0, 256);
543    ReadMessage(commandSocketFD,buffer);
544    numberExp = atoi(buffer);
545
546    LOG("Cognitive Engine:: Waiting for %i number of entries.\n",numberExp);
547 
548    SendMessage(commandSocketFD, "receive_exp_ack");
549}
550
551Parameter*
552CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters)
553{
554    LOG("Cognitive Engine:: Generating solution.\n");
555
556    char *searchNames[radioInfo->numUtilities];
557
558    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
559        searchNames[i] = (char*)observables[i].name.c_str();
560        }
561
562    float searchVals[radioInfo->numUtilities];
563
564        for(size_t i = 0; i < radioInfo->numUtilities; i++) {
565                searchVals[i] = uList[i].target;
566    }
567
568    uint32_t numberColumns =
569                radioInfo->numUtilities +
570                radioInfo->numParameters +
571                radioInfo->numObservables + 1;
572       
573        float returnValues[numberColumns];
574       
575        int searchOps[radioInfo->numUtilities];
576    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
577
578        /* If the goal is to maximum, set the search operation to
579                 * return values greater than the target.
580                 *
581                 * If the goal is to minimize, set the search operation to
582                 * return values less than the target.
583                 */
584
585                if(strcmp(uList[i].goal.c_str(),"max") == 0) {
586                    searchOps[i] = GT;
587                } else if(strcmp(uList[i].goal.c_str(),"min") == 0) {
588                        searchOps[i] = LT;
589                }
590        }
591
592        /* CBR specific call */
593        uint32_t rc = cbr_search(myCBR, searchNames, searchOps, searchVals,
594                        radioInfo->numUtilities, returnValues);
595
596        if(rc == 0){
597        /* Adapt the returned parameters to meet the objective */
598           
599        WARNING("Cognitive Engine:: Found\n");
600
601                // Should do a random adaptation..
602                if(returnValues[numberColumns-1] < 0) {
603                        returnValues[2] = returnValues[2] - 15;
604                        returnValues[3] = returnValues[3] - 2;
605        } else {
606                        returnValues[2] = returnValues[2] + 15;
607                        returnValues[3] = returnValues[3] + 2;
608                }
609    } else if(rc == 31337){
610        WARNING("Cognitive Engine:: Not Found.\n");
611                /* No rows in the CBR, pick default parameters */
612                // Currently this is hard coded and implementation specific!
613            returnValues[2] = currentParameters[0].value + 5;
614            returnValues[3] = currentParameters[1].value + 10;
615       
616        } else {
617        WARNING("Cognitive Engine:: Search return an invalid value.\n");
618        }
619
620        size_t returnValueIndex = 0;
621    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
622                uList[i].value = returnValues[returnValueIndex];
623                returnValueIndex++;
624        }
625    for(size_t i = 0; i < radioInfo->numParameters; i++) {
626                pList[i].value = returnValues[returnValueIndex];
627                returnValueIndex++;
628        }
629    for(size_t i = 0; i < radioInfo->numObservables; i++) {
630                oList[i].value = returnValues[returnValueIndex];
631                returnValueIndex++;
632        }
633    returnValues[returnValueIndex] = 0;
634
635    char *allNames[numberColumns];
636        size_t allNameIndex = 0;
637    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
638        allNames[allNameIndex] = (char*)uList[i].name.c_str();
639                returnValues[allNameIndex] = uList[i].target;
640                allNameIndex++;
641        }
642    for(size_t i = 0; i < radioInfo->numParameters; i++) {
643        allNames[allNameIndex] = (char*)pList[i].name.c_str();
644                allNameIndex++;
645        }
646    for(size_t i = 0; i < radioInfo->numObservables; i++) {
647        allNames[allNameIndex] = (char*)oList[i].name.c_str();
648                returnValues[allNameIndex] = 0;
649                allNameIndex++;
650        }
651    allNames[allNameIndex] = "utility";
652
653        // Add row to CBR.
654        cbr_add_row(myCBR, allNames, returnValues, returnValueIndex+1);
655
656        return pList;
657
658}
659
660
661Parameter*
662CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters, std::string service)
663{
664    LOG("Cognitive Engine:: Generating solution for %s service.\n",service.c_str());
665
666    return pList;
667}
668
669
670void
671CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters, \
672    std::string service)
673{
674    LOG("Cognitive Engine:: Receiving feedback.\n");
675}
676
677
678void
679CognitiveEngine::BuildCognitiveEngine()
680{
681        char filename[] = {"ex1"};
682        char tablename[] = {"data"};
683
684    uint32_t numberColumns =
685                radioInfo->numUtilities +
686                radioInfo->numParameters +
687                radioInfo->numObservables + 1;
688
689    char *cols[numberColumns];
690
691    size_t columnIndex = 0;
692    for (size_t i = 0; i < radioInfo->numUtilities; i++){
693                cols[columnIndex] = (char*)uList[i].name.c_str();
694        columnIndex++;
695    }   
696    for (size_t i = 0; i < radioInfo->numParameters; i++){
697                cols[columnIndex] = (char*)pList[i].name.c_str();
698        columnIndex++;
699    }   
700    for (size_t i = 0; i < radioInfo->numObservables; i++){
701                cols[columnIndex] = (char*)oList[i].name.c_str();
702        columnIndex++;
703    }   
704    cols[columnIndex] = "utility";
705
706    myCBR = cbr_create(filename, tablename, cols, numberColumns);
707}
708
Note: See TracBrowser for help on using the browser.