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

Revision 277, 20.7 KB (checked in by wrodgers, 15 years ago)

Updating SML functionality

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
366void
367CognitiveEngine::RegisterComponent()
368{
369    SendMessage(commandSocketFD, "register_engine_cognitive");
370    LOG("Cognitive Engine:: Registration message sent to shell.\n");
371}
372
373void
374CognitiveEngine::DeregisterComponent()
375{
376    SendMessage(commandSocketFD, "deregister_engine_cognitive");
377    LOG("Cognitive Engine:: Deregistration message sent.\n");
378
379    shutdown(commandSocketFD, 2);
380    close(commandSocketFD);
381    commandSocketFD = -1;
382    LOG("Cognitive Engine:: Shell socket closed.\n");
383}
384
385
386void
387CognitiveEngine::RegisterServices()
388{
389    LOG("Cognitive Engine:: Registering services.\n");
390
391    SendMessage(commandSocketFD, "register_service");
392    SendMessage(commandSocketFD, "jam_wifi");
393
394    SendMessage(commandSocketFD, "register_service");
395    SendMessage(commandSocketFD, "signal_detection");
396
397    SendMessage(commandSocketFD, "register_service");
398    SendMessage(commandSocketFD, "max_throughput");
399
400    SendMessage(commandSocketFD, "register_service");
401    SendMessage(commandSocketFD, "jam_bluetooth");
402}
403
404//Combined with deregister component since those two things must happen togeather
405void
406CognitiveEngine::DeregisterServices()
407{
408    LOG("Cognitive Engine:: Deregistering services.\n");
409
410    SendMessage(commandSocketFD, "deregister_service");
411    SendMessage(commandSocketFD, "jam_wifi");
412
413    SendMessage(commandSocketFD, "deregister_service");
414    SendMessage(commandSocketFD, "signal_detection");
415
416    SendMessage(commandSocketFD, "deregister_service");
417    SendMessage(commandSocketFD, "max_throughput");
418
419    SendMessage(commandSocketFD, "deregister_service");
420    SendMessage(commandSocketFD, "jam_bluetooth");
421
422}
423
424void
425CognitiveEngine::ReceiveRadioConfiguration()
426{
427    LOG("Cognitive Engine:: Receiving Radio Configuration.\n");
428   
429    char buffer[256];
430 
431    /* Receive Set of Utilities */
432    memset(buffer, 0, 256);
433    ReadMessage(commandSocketFD, buffer);
434    radioInfo->numUtilities = atoi(buffer);
435   
436    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
437        memset(buffer, 0, 256);
438        ReadMessage(commandSocketFD, buffer);
439        uList[i].name = std::string(buffer);
440   
441        memset(buffer, 0, 256);
442        ReadMessage(commandSocketFD, buffer);
443        uList[i].units = std::string(buffer);
444
445        memset(buffer, 0, 256);
446        ReadMessage(commandSocketFD, buffer);
447        uList[i].goal = std::string(buffer);
448   
449        memset(buffer, 0, 256);
450        ReadMessage(commandSocketFD, buffer);
451        uList[i].target = atof(buffer);
452    }
453
454    /* Receive Set of Parameters */
455    memset(buffer, 0, 256);
456    ReadMessage(commandSocketFD, buffer);
457    radioInfo->numParameters = atoi(buffer);
458   
459    for(size_t i = 0; i < radioInfo->numParameters; i++) {
460        memset(buffer, 0, 256);
461        ReadMessage(commandSocketFD, buffer);
462        pList[i].name = std::string(buffer);
463   
464        memset(buffer, 0, 256);
465        ReadMessage(commandSocketFD, buffer);
466        pList[i].units = std::string(buffer);
467
468        memset(buffer, 0, 256);
469        ReadMessage(commandSocketFD, buffer);
470        pList[i].min = atof(buffer);
471   
472        memset(buffer, 0, 256);
473        ReadMessage(commandSocketFD, buffer);
474        pList[i].max = atof(buffer);
475   
476        memset(buffer, 0, 256);
477        ReadMessage(commandSocketFD, buffer);
478        pList[i].step = atof(buffer);
479   
480        memset(buffer, 0, 256);
481        ReadMessage(commandSocketFD,buffer);
482        pList[i].numAffects = atoi(buffer);
483   
484        for(size_t j = 0; j < pList[i].numAffects; j++) {
485            memset(buffer, 0, 256);
486            ReadMessage(commandSocketFD,buffer);
487            // TODO for + if{break} = while?
488            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
489                if(uList[k].name == std::string(buffer)) {   
490                    pList[i].affection_list[j].u = &uList[k];   
491                    break;
492                }
493            }
494
495            memset(buffer, 0, 256);
496            ReadMessage(commandSocketFD, buffer);
497            pList[i].affection_list[j].relation = std::string(buffer);   
498        }
499    }   
500
501    /* Receive Set of Observables */
502    memset(buffer, 0, 256);
503    ReadMessage(commandSocketFD, buffer);
504    radioInfo->numObservables = atoi(buffer);
505   
506    for(size_t i = 0; i < radioInfo->numObservables; i++) {
507        memset(buffer, 0, 256);
508        ReadMessage(commandSocketFD, buffer);
509        oList[i].name = std::string(buffer);
510   
511        memset(buffer, 0, 256);
512        ReadMessage(commandSocketFD, buffer);
513        oList[i].numAffects = atoi(buffer);
514   
515        for(size_t j = 0; j < oList[i].numAffects; j++) {
516            memset(buffer, 0, 256);
517            ReadMessage(commandSocketFD, buffer);
518            // TODO for + if{break} = while?
519            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
520                if(uList[k].name == std::string(buffer)){   
521                    oList[i].affection_list[j].u = &uList[k];   
522                    break;
523                }
524            }
525 
526            memset(buffer, 0, 256);
527            ReadMessage(commandSocketFD, buffer);
528            oList[i].affection_list[j].relation = std::string(buffer);   
529        }
530    }
531
532    SendMessage(commandSocketFD, "receive_config_ack");
533
534    BuildCognitiveEngine();
535}
536
537void
538CognitiveEngine::ReceiveExperience()
539{
540    LOG("Cognitive Engine:: Receiving Experience Report.\n");
541    char buffer[256];
542    uint32_t numberExp;
543   
544    /* Receive number of experience entries */
545    memset(buffer, 0, 256);
546    ReadMessage(commandSocketFD, buffer);
547    numberExp = atoi(buffer);
548
549    LOG("Cognitive Engine:: Waiting for %i number of entries.\n", numberExp);
550 
551    SendMessage(commandSocketFD, "receive_exp_ack");
552}
553
554Parameter*
555CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters)
556{
557    LOG("Cognitive Engine:: Generating solution.\n");
558
559    char *searchNames[radioInfo->numUtilities];
560
561    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
562        searchNames[i] = (char*)observables[i].name.c_str();
563    }
564
565    float searchVals[radioInfo->numUtilities];
566
567    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
568        searchVals[i] = uList[i].target;
569    }
570
571    uint32_t numberColumns =
572        radioInfo->numUtilities +
573        radioInfo->numParameters +
574        radioInfo->numObservables + 1;
575   
576    float returnValues[numberColumns];
577   
578    int searchOps[radioInfo->numUtilities];
579    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
580
581        /* If the goal is to maximum, set the search operation to
582         * return values greater than the target.
583         *
584         * If the goal is to minimize, set the search operation to
585         * return values less than the target.
586         */
587        if(strcmp(uList[i].goal.c_str(), "max") == 0) {
588            searchOps[i] = GT;
589        } else if(strcmp(uList[i].goal.c_str(), "min") == 0) {
590            searchOps[i] = LT;
591        }
592    }
593
594    /* CBR specific call */
595    uint32_t rc = cbr_search(myCBR, searchNames, searchOps, searchVals,
596            radioInfo->numUtilities, returnValues);
597
598    if(rc == 0){
599        /* Adapt the returned parameters to meet the objective */
600        WARNING("Cognitive Engine:: Found\n");
601
602        /* Should do a random adaptation.. */
603        if(returnValues[numberColumns-1] < 0) {
604            returnValues[2] = returnValues[2] - 15;
605            returnValues[3] = returnValues[3] - 2;
606        } else {
607            returnValues[2] = returnValues[2] + 15;
608            returnValues[3] = returnValues[3] + 2;
609        }
610    } else if(rc == 31337) {
611        WARNING("Cognitive Engine:: Not Found.\n");
612        /* No rows in the CBR, pick default parameters */
613        /* Currently this is hard coded and implementation specific! */
614        returnValues[2] = currentParameters[0].value + 5;
615        returnValues[3] = currentParameters[1].value + 10;
616       
617    } else {
618        WARNING("Cognitive Engine:: Search return an invalid value.\n");
619    }
620
621    size_t returnValueIndex = 0;
622    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
623        uList[i].value = returnValues[returnValueIndex];
624        returnValueIndex++;
625    }
626    for(size_t i = 0; i < radioInfo->numParameters; i++) {
627        pList[i].value = returnValues[returnValueIndex];
628        returnValueIndex++;
629    }
630    for(size_t i = 0; i < radioInfo->numObservables; i++) {
631        oList[i].value = returnValues[returnValueIndex];
632        returnValueIndex++;
633    }
634    returnValues[returnValueIndex] = 0;
635
636    char *allNames[numberColumns];
637    size_t allNameIndex = 0;
638    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
639        allNames[allNameIndex] = (char*)uList[i].name.c_str();
640        returnValues[allNameIndex] = uList[i].target;
641        allNameIndex++;
642    }
643    for(size_t i = 0; i < radioInfo->numParameters; i++) {
644        allNames[allNameIndex] = (char*)pList[i].name.c_str();
645        allNameIndex++;
646    }
647    for(size_t i = 0; i < radioInfo->numObservables; i++) {
648        allNames[allNameIndex] = (char*)oList[i].name.c_str();
649        returnValues[allNameIndex] = 0;
650        allNameIndex++;
651    }
652    allNames[allNameIndex] = "utility";
653
654    // Add row to CBR.
655    cbr_add_row(myCBR, allNames, returnValues, returnValueIndex+1);
656
657    return pList;
658}
659
660
661Parameter*
662CognitiveEngine::GetSolution(Observable *observables, \
663        Parameter *currentParameters, std::string service)
664{
665    LOG("Cognitive Engine:: Generating solution for %s service.\n", service.c_str());
666
667    return pList;
668}
669
670
671void
672CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters, \
673    std::string service)
674{
675    LOG("Cognitive Engine:: Receiving feedback.\n");
676}
677
678
679void
680CognitiveEngine::BuildCognitiveEngine()
681{
682    char filename[] = {"ex1"};
683    char tablename[] = {"data"};
684
685    uint32_t numberColumns =
686        radioInfo->numUtilities +
687        radioInfo->numParameters +
688        radioInfo->numObservables + 1;
689
690    char *cols[numberColumns];
691
692    size_t columnIndex = 0;
693    for (size_t i = 0; i < radioInfo->numUtilities; i++){
694        cols[columnIndex] = (char*)uList[i].name.c_str();
695        columnIndex++;
696    }   
697    for (size_t i = 0; i < radioInfo->numParameters; i++){
698        cols[columnIndex] = (char*)pList[i].name.c_str();
699        columnIndex++;
700    }   
701    for (size_t i = 0; i < radioInfo->numObservables; i++){
702        cols[columnIndex] = (char*)oList[i].name.c_str();
703        columnIndex++;
704    }   
705    cols[columnIndex] = "utility";
706
707    myCBR = cbr_create(filename, tablename, cols, numberColumns);
708}
709
Note: See TracBrowser for help on using the browser.