root/vtcross/branches/wrodgers/src/cognitive_engines/CognitiveEngine.cpp @ 275

Revision 275, 20.8 KB (checked in by wrodgers, 15 years ago)

Updated data management, added function descriptions, fixed a few errors

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