Index: /vtcross/trunk/src/cognitive_engines/DSA_CE/DSA_CognitiveEngine.cpp
===================================================================
--- /vtcross/trunk/src/cognitive_engines/DSA_CE/DSA_CognitiveEngine.cpp	(revision 375)
+++ /vtcross/trunk/src/cognitive_engines/DSA_CE/DSA_CognitiveEngine.cpp	(revision 375)
@@ -0,0 +1,789 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * LICENSE INFORMATION GOES HERE
+ */
+
+/* DESCRIPTION OF FILE.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+#include <math.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+#include "vtcross/cbr.h"
+
+// TODO this is really bad; need to move to a proper cbr.h
+#include "cbr.c"
+
+#include "sqlite3.h"
+#include "sqlite3ext.h"
+
+
+static cbr myCBR;
+
+
+CognitiveEngine::CognitiveEngine()
+{
+    LOG("Creating Cognitive Engine.\n");
+    SML_present = false;
+    commandSocketFD = -1;
+}
+
+
+CognitiveEngine::~CognitiveEngine()
+{
+    cbr_free(myCBR);
+    delete [] pList;
+    delete [] oList;
+    delete [] uList;
+    delete [] radioInfo;
+}
+
+
+CognitiveEngine::CognitiveEngine(const char *serverName, const char *serverPort, \
+        const bool SML)
+{
+    LOG("Creating Cognitive Engine.\n");
+
+    pList = new Parameter[10];
+    oList = new Observable[10];
+    uList = new Utility[10];
+    radioInfo = new Radio_Info;
+
+    ConnectToRemoteComponent(serverName, serverPort, SML);
+}
+
+
+void
+CognitiveEngine::SendComponentType()
+{
+    SendMessage(commandSocketFD, "response_engine_cognitive");
+    LOG("Cognitive Engine responded to GetRemoteComponentType query.\n");
+}
+
+
+void
+CognitiveEngine::ConnectToRemoteComponent(const char *serverName, \
+        const char *serverPort, const bool SML)
+{
+    commandSocketFD = ClientSocket(serverName, serverPort);
+
+    SML_present = SML;
+
+    if(SML) {
+        
+        RegisterComponent();
+        LOG("Cognitive Engine connected to SML at %s.\n", serverName);
+        ReceiveRadioConfiguration();
+        ReceiveExperience();
+        
+        RegisterServices();
+    }
+    else {
+        RegisterComponent();
+        LOG("Cognitive Engine connected to shell at %s.\n", serverName);
+        ReceiveRadioConfiguration();
+        ReceiveExperience();
+    }
+}
+
+void 
+CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters)
+{ 
+   LOG("Cognitive Engine:: Receiving feedback.\n");
+    
+    uint32_t numberColumns = 
+        radioInfo->numParameters +
+        radioInfo->numUtilities;
+
+    uint32_t obsColumns = radioInfo->numObservables + 1;
+
+    float valList[numberColumns];
+    float obsVals[numberColumns];
+    char *nameList[numberColumns];
+    char *obsList[obsColumns];
+
+    size_t columnObsIndex = 0;
+    for (size_t i = 0; i < radioInfo->numObservables; i++){
+        obsList[columnObsIndex] = (char*)observables[i].name.c_str();
+        columnObsIndex++;
+    }  
+    obsList[columnObsIndex] = "utility";
+
+    size_t columnIndex = 0;
+    for (size_t i = 0; i < radioInfo->numParameters; i++){
+        nameList[columnIndex] = (char*)parameters[i].name.c_str();
+        columnIndex++;
+    }   
+    for (size_t i = 0; i < radioInfo->numUtilities; i++){
+        nameList[columnIndex] = (char*)uList[i].name.c_str();
+        columnIndex++;
+    }   
+
+    size_t obsValueIndex = 0;
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        obsVals[obsValueIndex] = observables[i].value;
+        obsValueIndex++;
+    }
+
+    /* Calculate Utility */
+    float newUtilityValue = 0;
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        newUtilityValue = newUtilityValue + (uList[i].target - observables[i].value);
+    }
+    obsVals[obsValueIndex] = newUtilityValue;
+
+    size_t returnValueIndex = 0;
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        valList[returnValueIndex] = parameters[i].value;
+        returnValueIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        valList[returnValueIndex] = uList[i].target;
+        returnValueIndex++;
+    }
+
+    cbr_update(myCBR, nameList, obsList, valList, obsVals, 
+            numberColumns, obsColumns);
+}
+
+
+void 
+CognitiveEngine::WaitForSignal()
+{
+    char buffer[256];
+
+    while(true) {
+        memset(buffer, 0, 256);
+       
+        ReadMessage(commandSocketFD, buffer);
+
+        // TODO this is ugly... is there a better way? Doesn't strcmp compare the
+        // whole string?  We only need to compare until we find a single different
+        // byte...
+        //
+        // If we send integer op codes rather than strings, this process will be
+        // MUCH faster since instead of donig string compares we can simply
+        // switch on the integer value...
+        if(strcmp(buffer, "update_performance") == 0) {
+            
+            /* Receive Set of current Parameters */
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numParameters = atoi(buffer);
+   
+            Parameter *p = new Parameter[numParameters];
+ 
+            for(size_t i = 0; i < numParameters; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                p[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                p[i].value = atof(buffer);
+            } 
+
+            /* Receive Set of Observables */
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numObservables = atoi(buffer);
+   
+            Observable *o = new Observable[numObservables];
+ 
+            for(size_t i = 0; i < numObservables; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].value = atof(buffer);
+            }  
+
+            ReceiveFeedback(o,p);
+
+            delete [] o;
+            delete [] p;
+        } 
+        else if(strcmp(buffer, "request_optimization_service") == 0) {
+	    // THIS IS CURRENTLY IN DEMO MODE            
+
+
+            /* Receive Set of Observables */
+            LOG("\nCognitive Engine:: Receiving service name\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD,buffer);
+            LOG("\nCognitive Engine:: Got service name, %s\n", buffer);
+
+            /* Receive Set of Observables */
+            LOG("\nCognitive Engine:: Receiving Observable Parameters\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD,buffer);
+            uint32_t numObservables = atoi(buffer);
+   
+            Observable *o = new Observable[numObservables];
+ 
+            for(size_t i = 0; i < numObservables; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].value = atof(buffer);
+            }  
+
+            /* Receive Set of current Parameters */
+            LOG("Cognitive Engine:: Receiving Current Transmission Parameters\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numCurrentParameters = atoi(buffer);
+   
+            Parameter *cp = new Parameter[numCurrentParameters];
+ 
+            for(size_t i = 0; i < numCurrentParameters; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                cp[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                cp[i].value = atof(buffer);
+            }  
+            LOG("Cognitive Engine:: Processing parameters....\n");
+
+            Parameter *solutionSet;
+            
+            //solutionSet = GetSolution(o,cp);
+
+            // TODO need to actually do something with the observables here
+           
+            LOG("Cognitive Engine:: Sending Optimal Parameters to Application.\n");
+            char numParametersChar[10];
+            char solutionValue[50];
+            sprintf(numParametersChar, "%i", radioInfo->numParameters);
+            SendMessage(commandSocketFD, numParametersChar);
+            for(size_t i = 0; i < radioInfo->numParameters; i++) {
+                //SendMessage(commandSocketFD, solutionSet[i].name.c_str());
+		SendMessage(commandSocketFD, "test");
+                //memset(solutionValue, 0, 50);
+                //sprintf(solutionValue, "%f", solutionSet[i].value);
+                //SendMessage(commandSocketFD, solutionValue);
+		SendMessage(commandSocketFD, "00");
+            }
+
+            delete [] o;
+            delete [] cp;
+        }
+        else if(strcmp(buffer, "request_optimization") == 0) {
+            
+            /* Receive Set of Observables */
+            LOG("\nCognitive Engine:: Receiving Observable Parameters\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD,buffer);
+            uint32_t numObservables = atoi(buffer);
+   
+            Observable *o = new Observable[numObservables];
+ 
+            for(size_t i = 0; i < numObservables; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                o[i].value = atof(buffer);
+            }  
+
+            /* Receive Set of current Parameters */
+            LOG("Cognitive Engine:: Receiving Current Transmission Parameters\n");
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            uint32_t numCurrentParameters = atoi(buffer);
+   
+            Parameter *cp = new Parameter[numCurrentParameters];
+ 
+            for(size_t i = 0; i < numCurrentParameters; i++) {
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                cp[i].name = std::string(buffer);
+    
+                memset(buffer, 0, 256);
+                ReadMessage(commandSocketFD, buffer);
+                cp[i].value = atof(buffer);
+            }  
+            LOG("Cognitive Engine:: Processing parameters....\n");
+
+            Parameter *solutionSet;
+            
+            solutionSet = GetSolution(o,cp);
+
+            // TODO need to actually do something with the observables here
+           
+            LOG("Cognitive Engine:: Sending Optimal Parameters to Application.\n");
+            char numParametersChar[10];
+            char solutionValue[50];
+            sprintf(numParametersChar, "%i", radioInfo->numParameters);
+            SendMessage(commandSocketFD, numParametersChar);
+            for(size_t i = 0; i < radioInfo->numParameters; i++) {
+                SendMessage(commandSocketFD, solutionSet[i].name.c_str());
+                memset(solutionValue, 0, 50);
+                sprintf(solutionValue, "%f", solutionSet[i].value);
+                SendMessage(commandSocketFD, solutionValue);
+            }
+
+            delete [] o;
+            delete [] cp;
+        }
+        else if(strcmp(buffer, "query_component_type") == 0) {
+            SendComponentType();
+        }
+        else if(strcmp(buffer, "connect_sml") == 0) {
+            /* This command implies that we are disconnecting from the shell and
+             * connecting to a SML component. */
+            char serverName[256];
+            char serverPort[256];
+            // TODO is this going to end up being too slow?
+            memset(serverName, 0, 256);
+            memset(serverPort, 0, 256);
+
+            ReadMessage(commandSocketFD, serverName);
+            ReadMessage(commandSocketFD, serverPort);
+
+            /* Only continue if we are currently connected to a shell. */
+            if(!SML_present) {
+                DeregisterComponent();
+
+                shutdown(commandSocketFD, 2);
+                close(commandSocketFD);
+
+                ConnectToRemoteComponent(serverName, serverPort, true);
+            }
+        }
+        else if(strcmp(buffer, "disconnect_sml") == 0) {
+            /* This command implies that we are disconnecting from the SML and
+             * connecting to a shell component. */
+            char serverName[256];
+            char serverPort[256];
+            // TODO is this going to end up being too slow?
+            memset(serverName, 0, 256);
+            memset(serverPort, 0, 256);
+
+            ReadMessage(commandSocketFD, serverName);
+            ReadMessage(commandSocketFD, serverPort);
+
+            /* We only want to do this if we are actually connected to an SML
+             * currently. */
+            if(SML_present) {
+                DeregisterServices();
+
+                shutdown(commandSocketFD, 2);
+                close(commandSocketFD);
+
+                ConnectToRemoteComponent(serverName, serverPort, false);
+            }
+        }
+        else if(strcmp(buffer, "reset_engine_cognitive") == 0) {
+            Reset();
+        }
+        else if(strcmp(buffer, "shutdown_engine_cognitive") == 0) {
+            Shutdown();
+        }
+    }
+}
+
+
+void 
+CognitiveEngine::Shutdown()
+{
+    if(SML_present) {
+        //DeregisterServices();
+        DeregisterComponent();
+    } 
+    else {
+        DeregisterComponent();
+    }
+    // TODO should something else be happening here?
+}
+
+
+void
+CognitiveEngine::Reset()
+{
+    LOG("Resetting Cognitive Engine.\n");
+
+    if(SML_present) {
+        DeregisterServices();
+        DeregisterComponent();
+    } 
+    else {
+        DeregisterComponent();
+    }
+}
+
+
+void
+CognitiveEngine::RegisterComponent()
+{
+    char buffer[256];
+    SendMessage(commandSocketFD, "register_engine_cognitive");
+    LOG("Cognitive Engine:: Registration message sent to shell.\n");
+
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+}
+
+void 
+CognitiveEngine::DeregisterComponent()
+{
+    SendMessage(commandSocketFD, "deregister_engine_cognitive");
+    LOG("Cognitive Engine:: Deregistration message sent.\n");
+
+    shutdown(commandSocketFD, 2);
+    close(commandSocketFD);
+    commandSocketFD = -1;
+    LOG("Cognitive Engine:: Shell socket closed.\n");
+}
+
+
+void 
+CognitiveEngine::RegisterServices()
+{
+    LOG("Cognitive Engine:: Registering services.\n");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "test_srv");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "test_srv1");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "test_srv2");
+
+    SendMessage(commandSocketFD, "register_service");
+    SendMessage(commandSocketFD, "test_srv3");
+
+}
+
+//Combined with deregister component since those two things must happen togeather
+void 
+CognitiveEngine::DeregisterServices()
+{
+    LOG("Cognitive Engine:: Deregistering services.\n");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "test_srv");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "test_srv1");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "test_srv2");
+
+    SendMessage(commandSocketFD, "deregister_service");
+    SendMessage(commandSocketFD, "test_srv3");
+
+}
+
+void 
+CognitiveEngine::ReceiveRadioConfiguration()
+{
+    LOG("Cognitive Engine:: Receiving Radio Configuration.\n");
+    
+    char buffer[256];
+ 
+    /* Receive Set of Utilities */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    radioInfo->numUtilities = atoi(buffer);
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].name = std::string(buffer);
+   
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].units = std::string(buffer);
+
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].goal = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        uList[i].target = atof(buffer);
+    }
+
+    /* Receive Set of Parameters */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    radioInfo->numParameters = atoi(buffer);
+    
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].name = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].units = std::string(buffer);
+
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].min = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].max = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        pList[i].step = atof(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD,buffer);
+        pList[i].numAffects = atoi(buffer);
+    
+        for(size_t j = 0; j < pList[i].numAffects; j++) {
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD,buffer);
+            // TODO for + if{break} = while?
+            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
+                if(uList[k].name == std::string(buffer)) {    
+                    pList[i].affection_list[j].u = &uList[k];   
+                    break;
+                }
+            }
+
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            pList[i].affection_list[j].relation = std::string(buffer);   
+        }
+    }   
+
+    /* Receive Set of Observables */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    radioInfo->numObservables = atoi(buffer);
+    
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        oList[i].name = std::string(buffer);
+    
+        memset(buffer, 0, 256);
+        ReadMessage(commandSocketFD, buffer);
+        oList[i].numAffects = atoi(buffer);
+    
+        for(size_t j = 0; j < oList[i].numAffects; j++) {
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            // TODO for + if{break} = while?
+            for(size_t k = 0; k < radioInfo->numUtilities; k++) {
+                if(uList[k].name == std::string(buffer)){    
+                    oList[i].affection_list[j].u = &uList[k];   
+                    break;
+                }
+            }
+ 
+            memset(buffer, 0, 256);
+            ReadMessage(commandSocketFD, buffer);
+            oList[i].affection_list[j].relation = std::string(buffer);   
+        }
+    }
+
+    SendMessage(commandSocketFD, "receive_config_ack");
+
+    BuildCognitiveEngine();
+}
+
+void 
+CognitiveEngine::ReceiveExperience()
+{
+    LOG("Cognitive Engine:: Receiving Experience Report.\n");
+    char buffer[256];
+    uint32_t numberExp;
+    
+    /* Receive number of experience entries */
+    memset(buffer, 0, 256);
+    ReadMessage(commandSocketFD, buffer);
+    numberExp = atoi(buffer);
+
+    LOG("Cognitive Engine:: Waiting for %i number of entries.\n", numberExp);
+ 
+    SendMessage(commandSocketFD, "receive_exp_ack");
+}
+
+Parameter* 
+CognitiveEngine::GetSolution(Observable *observables, Parameter *currentParameters)
+{
+    LOG("Cognitive Engine:: Generating solution.\n");
+
+    char *searchNames[radioInfo->numUtilities];
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        searchNames[i] = (char*)observables[i].name.c_str();
+    }
+
+    float searchVals[radioInfo->numUtilities];
+
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        searchVals[i] = uList[i].target;
+    }
+
+    uint32_t numberColumns = 
+        radioInfo->numUtilities +
+        radioInfo->numParameters +
+        radioInfo->numObservables + 1;
+    
+    float returnValues[numberColumns];
+    
+    int searchOps[radioInfo->numUtilities];
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+
+        /* If the goal is to maximum, set the search operation to
+         * return values greater than the target.
+         *
+         * If the goal is to minimize, set the search operation to
+         * return values less than the target.
+         */
+        if(strcmp(uList[i].goal.c_str(), "max") == 0) {
+            searchOps[i] = GT;
+        } else if(strcmp(uList[i].goal.c_str(), "min") == 0) {
+            searchOps[i] = LT;
+        }
+    }
+
+    /* CBR specific call */
+    uint32_t rc = cbr_search(myCBR, searchNames, searchOps, searchVals,
+            radioInfo->numUtilities, returnValues);
+
+    if(rc == 0){
+        /* Adapt the returned parameters to meet the objective */
+        LOG("Cognitive Engine:: Found\n");
+
+        /* Should do a random adaptation.. */
+        if(returnValues[numberColumns-1] < 0) {
+            returnValues[2] = returnValues[2] - 15;
+            returnValues[3] = returnValues[3] - 2;
+        } else {
+            returnValues[2] = returnValues[2] + 15;
+            returnValues[3] = returnValues[3] + 2;
+        }
+    } else if(rc == 31337) {
+        LOG("Cognitive Engine:: Not Found.\n");
+        /* No rows in the CBR, pick default parameters */
+        /* Currently this is hard coded and implementation specific! */
+        returnValues[2] = currentParameters[0].value + 5;
+        returnValues[3] = currentParameters[1].value + 10;
+        
+    } else {
+        LOG("Cognitive Engine:: Search return an invalid value.\n");
+    }
+
+    size_t returnValueIndex = 0;
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        uList[i].value = returnValues[returnValueIndex];
+        returnValueIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        pList[i].value = returnValues[returnValueIndex];
+        returnValueIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        oList[i].value = returnValues[returnValueIndex];
+        returnValueIndex++;
+    }
+    returnValues[returnValueIndex] = 0;
+
+    char *allNames[numberColumns];
+    size_t allNameIndex = 0;
+    for(size_t i = 0; i < radioInfo->numUtilities; i++) {
+        allNames[allNameIndex] = (char*)uList[i].name.c_str();
+        returnValues[allNameIndex] = uList[i].target;
+        allNameIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numParameters; i++) {
+        allNames[allNameIndex] = (char*)pList[i].name.c_str();
+        allNameIndex++;
+    }
+    for(size_t i = 0; i < radioInfo->numObservables; i++) {
+        allNames[allNameIndex] = (char*)oList[i].name.c_str();
+        returnValues[allNameIndex] = 0;
+        allNameIndex++;
+    }
+    allNames[allNameIndex] = "utility";
+
+    // Add row to CBR. 
+    cbr_add_row(myCBR, allNames, returnValues, returnValueIndex+1);
+
+    return pList;
+}
+
+
+Parameter* 
+CognitiveEngine::GetSolution(Observable *observables, \
+        Parameter *currentParameters, std::string service)
+{
+    LOG("Cognitive Engine:: Generating solution for %s service.\n", service.c_str());
+
+    return pList;
+}
+
+
+void 
+CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters, \
+    std::string service)
+{
+    LOG("Cognitive Engine:: Receiving feedback.\n");
+}
+
+
+void
+CognitiveEngine::BuildCognitiveEngine()
+{
+    char filename[] = {"ex1"};
+    char tablename[] = {"data"};
+
+    uint32_t numberColumns = 
+        radioInfo->numUtilities +
+        radioInfo->numParameters +
+        radioInfo->numObservables + 1;
+
+    char *cols[numberColumns];
+
+    size_t columnIndex = 0;
+    for (size_t i = 0; i < radioInfo->numUtilities; i++){
+        cols[columnIndex] = (char*)uList[i].name.c_str();
+        columnIndex++;
+    }   
+    for (size_t i = 0; i < radioInfo->numParameters; i++){
+        cols[columnIndex] = (char*)pList[i].name.c_str();
+        columnIndex++;
+    }   
+    for (size_t i = 0; i < radioInfo->numObservables; i++){
+        cols[columnIndex] = (char*)oList[i].name.c_str();
+        columnIndex++;
+    }   
+    cols[columnIndex] = "utility";
+
+    myCBR = cbr_create(filename, tablename, cols, numberColumns);
+}
+
Index: /vtcross/trunk/src/cognitive_engines/DSA_CE/cbr.c
===================================================================
--- /vtcross/trunk/src/cognitive_engines/DSA_CE/cbr.c	(revision 375)
+++ /vtcross/trunk/src/cognitive_engines/DSA_CE/cbr.c	(revision 375)
@@ -0,0 +1,312 @@
+//
+// Case-based reasoner
+//
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "vtcross/cbr.h"
+#include "vtcross/common.h"
+
+
+struct cbr_s {
+    char filename[64];
+    char tablename[64];
+    char command[2048];
+    sqlite3 *db; 
+    unsigned int num_columns;
+};
+
+
+// open a database or create a database if it does not exist
+int OpenDatabase(cbr _cbr){
+    int rc;
+    //sqlite3 **db;
+
+    //printf("database name: %s\n", _cbr->filename);
+    //rc = sqlite3_open(_cbr->filename, db);
+    rc = sqlite3_open(_cbr->filename, &(_cbr->db));
+    if (rc) {
+        //fprintf(stderr, "can't open database: %s\n", sqlite3_errmsg(*db));
+        fprintf(stderr, "can't open database: %s\n", sqlite3_errmsg(_cbr->db));
+        sqlite3_close(_cbr->db);
+        exit(1);
+    } else{
+        //printf("database opened.\n");
+    }
+    //_cbr->db = *db;
+    return rc;
+}
+
+
+// simple callback function, display result
+int callback(void *notUsed, int argc, char **argv, char **azColName){
+    int i;
+    for(i=0; i<argc; i++){
+        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
+    }
+    printf("\n");
+    return 0;
+}
+
+
+// execute command
+int ExecuteCommand(cbr _cbr){
+    int rc;
+    char *zErrMsg = 0;
+
+    //printf("command: %s\n", _cbr->command);
+    rc = sqlite3_exec(_cbr->db, _cbr->command, callback, 0, &zErrMsg);
+    if( rc!=SQLITE_OK){
+        fprintf(stderr, "SQL error: %s: %s\n", zErrMsg,_cbr->command);
+        sqlite3_free(zErrMsg);
+    } else{
+        //printf("command executed.\n");
+    }
+    return rc;
+}
+
+
+// execute search command
+int ExecuteSearchCommand(cbr _cbr, float *_retvals){
+    int rc;
+    unsigned int i;
+
+    sqlite3_stmt * pStatement;
+    rc = sqlite3_prepare_v2(_cbr->db, _cbr->command, -1, &pStatement, NULL);
+    if (rc == SQLITE_OK){ 
+        if (sqlite3_step(pStatement) == SQLITE_ROW){
+            for (i=0; i<_cbr->num_columns; ++i)
+                _retvals[i] = sqlite3_column_double(pStatement, i);
+        } else {
+		    printf("CBR:: No matched results returning default.\n");
+			rc=31337;
+		}
+    } else {
+		printf("CBR:: Error executing SQL statement. rc = %i\n%s\n",rc,_cbr->command);
+    }
+
+    sqlite3_finalize(pStatement);
+   
+    return rc;
+}
+
+
+// create database
+cbr cbr_create(char * _filename, char * _tablename, char * _cols[], unsigned int _len)
+{
+    // cbr is a pointer to struct cbr_s
+    cbr _cbr = (cbr) malloc(sizeof(struct cbr_s));
+
+    // create database
+
+    // copy filename
+    unsigned int i=0;
+    strcpy(_cbr->filename, _filename);
+
+    // execute create database command
+    // database handle
+    //_cbr->db = NULL;
+    OpenDatabase(_cbr);
+
+    // create table
+
+    // copy tablename
+    strcpy(_cbr->tablename, _tablename);
+
+    // number of columns in the table
+    _cbr->num_columns = _len;
+
+    // generate command
+    strcpy(_cbr->command, "CREATE TABLE ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, "(");
+    for (i=0; i<_cbr->num_columns; i++) {
+        strcat(_cbr->command, _cols[i]);
+        strcat(_cbr->command, " FLOAT");
+        if (i != _cbr->num_columns-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, ");");
+
+    // execute create table command
+    ExecuteCommand(_cbr);
+
+    return _cbr;
+}
+
+
+// free space
+void cbr_free(cbr _cbr)
+{  
+    // generate command, remove a table with its content
+    strcpy(_cbr->command, "drop table ");
+    strcat(_cbr->command, _cbr->tablename);
+
+    // execute delete command
+    ExecuteCommand(_cbr);
+
+    // clean the database
+    strcpy(_cbr->command, "vacuum");
+    ExecuteCommand(_cbr);
+
+    free(_cbr);
+}
+
+
+// print 
+void cbr_print(cbr _cbr)
+{
+    // generate commandi
+    strcpy(_cbr->command, "select ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, ".* from ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, ";");
+
+    // execute print (select all)  command
+    ExecuteCommand(_cbr);
+    printf("database %s, table %s:\n", _cbr->filename, _cbr->tablename);
+}
+
+
+/*//static
+int cbr_callback(void *notUsed, int argc, char **argv, char **azColName)
+{
+    return 0;
+}*/
+
+
+const char * ops_str[] = {
+    "==", "!=", ">", ">=", "<", "<="};
+
+
+// cbr search
+int cbr_search(
+    cbr _cbr,
+    char *_names[],
+    int * _ops,
+    float *_vals,
+    unsigned int _n,
+    float *_retvals)
+{   
+    int rc;
+    // generate command
+    strcpy(_cbr->command, "select ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, ".* from ");
+    strcat(_cbr->command, _cbr->tablename);
+    strcat(_cbr->command, " where ");
+
+    unsigned int i;
+    char str_buffer[64];
+    printf("number of ops %d:\n", _n);
+    for (i=0; i<_n; i++) {
+        // ensure valid ops value
+        if (_ops[i] < 0 || _ops[i] > 5) {
+            printf("error: cbr_search(), invalid ops id : %d\n", _ops[i]);
+            exit(1);
+        }
+
+        strcat(_cbr->command, _names[i]);
+        strcat(_cbr->command, ops_str[_ops[i]]);
+    printf("search command: %s\n", _cbr->command);
+        sprintf(str_buffer, "%E", _vals[i]);
+        strcat(_cbr->command, str_buffer);
+
+
+        if (i<_n-1)
+            strcat(_cbr->command, " AND ");
+        else
+            strcat(_cbr->command, " order by utility desc;");
+    }
+
+    //printf("search command: %s\n", _cbr->command);
+
+    //ExecuteCommand(_cbr);
+    rc = ExecuteSearchCommand(_cbr, _retvals);
+    
+    /*printf("search result: ");
+    for (i=0; i<_cbr->num_columns; i++)
+        printf("%f, ",_retvals[i]);
+    printf("\n");*/
+
+    return rc;
+}
+
+
+// update a row 
+int cbr_update(cbr _cbr, char *_where[], char*_set[], float *_wherevals, float *_setvals, 
+		unsigned int _wherelen, unsigned int _setlen)
+{
+    unsigned int i;
+    
+    // generate command
+    //printf("%s\n", _cbr->command);
+    strcpy(_cbr->command, "UPDATE ");
+    strcat(_cbr->command, _cbr->tablename);
+    
+    strcat(_cbr->command, " SET ");
+    for (i=0; i<_setlen; i++) {
+        strcat(_cbr->command, _set[i]);
+        strcat(_cbr->command, " = ");
+        sprintf(_cbr->command, "%s%f", _cbr->command, _setvals[i]);
+        strcat(_cbr->command, "  ");
+        if (i != _setlen-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, " WHERE ");
+
+    for (i=0; i<_wherelen; i++) {
+        strcat(_cbr->command, _where[i]);
+        strcat(_cbr->command, " = ");
+        sprintf(_cbr->command, "%s%f", _cbr->command, _wherevals[i]);
+        strcat(_cbr->command, "  ");
+        if (i != _wherelen-1) // not last entry
+            strcat(_cbr->command, "AND ");
+    }
+    strcat(_cbr->command, ";");
+    
+    //printf("search command: %s\n", _cbr->command);
+    // execute add command
+    ExecuteCommand(_cbr);
+
+    return 0;
+}
+
+// cbr add a row
+int cbr_add_row(cbr _cbr, char *_cols[], float *_vals, unsigned int _len)
+{
+    unsigned int i;
+    
+    // generate command
+    //printf("%s\n", _cbr->command);
+    strcpy(_cbr->command, "insert into ");
+    strcat(_cbr->command, _cbr->tablename);
+    
+    strcat(_cbr->command, " (");
+    for (i=0; i<_len; i++) {
+        strcat(_cbr->command, _cols[i]);
+        if (i != _cbr->num_columns-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, ") ");
+
+    strcat(_cbr->command, " values(");
+    for (i=0; i<_len; i++) {
+        // ???? how to fill the values if _cbr->num_columns != _len
+        // assume = in the following
+        sprintf(_cbr->command, "%s%f", _cbr->command, _vals[i]);
+        if (i != _cbr->num_columns-1) // not last entry
+            strcat(_cbr->command, ", ");
+    }
+    strcat(_cbr->command, ");");
+    
+    //printf("search command: %s\n", _cbr->command);
+    // execute add command
+    ExecuteCommand(_cbr);
+
+    return 0;
+}
+
Index: /vtcross/trunk/src/cognitive_engines/DSA_CE/Makefile.am
===================================================================
--- /vtcross/trunk/src/cognitive_engines/DSA_CE/Makefile.am	(revision 375)
+++ /vtcross/trunk/src/cognitive_engines/DSA_CE/Makefile.am	(revision 375)
@@ -0,0 +1,12 @@
+include $(top_srcdir)/Makefile.common
+
+INCLUDES = -I$(top_srcdir)/src/include
+
+AM_CXXFLAGS = -Wall -g
+
+bin_PROGRAMS = DSA_Demo
+include_HEADERS = cbr.c
+
+cbr_demo_SOURCES = DSA_CognitiveEngine.cpp DSA_Demo.cpp
+cbr_demo_LDADD = -lsqlite3 $(CROSS_SOCKETCOMM_LA) 
+
Index: /vtcross/trunk/src/cognitive_engines/DSA_CE/DSA_Demo.cpp
===================================================================
--- /vtcross/trunk/src/cognitive_engines/DSA_CE/DSA_Demo.cpp	(revision 375)
+++ /vtcross/trunk/src/cognitive_engines/DSA_CE/DSA_Demo.cpp	(revision 375)
@@ -0,0 +1,42 @@
+/* Virginia Tech Cognitive Radio Open Source Systems
+ * Virginia Tech, 2009
+ *
+ * TODO LICENSE INFORMATION GOES HERE
+ */
+
+/* TODO DESCRIPTION OF FILE.
+ *
+ * This file is a temporary demo of a policy engine using some of our socket
+ * communication functions. This is *not* an actual implementation of our
+ * defined PolicyEngine class.
+ */
+
+
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+#include "vtcross/common.h"
+#include "vtcross/components.h"
+#include "vtcross/containers.h"
+#include "vtcross/debug.h"
+#include "vtcross/error.h"
+#include "vtcross/socketcomm.h"
+
+
+int32_t 
+main(int32_t argc, char *argv[])
+{
+    if(argc < 3)
+       ERROR(1, "Usage: %s hostname port\n", argv[0]);
+    
+    CognitiveEngine cognitiveEngine(argv[1], argv[2], false);
+
+    LOG("Waiting for signal...\n");
+    while(1) {
+        cognitiveEngine.WaitForSignal();
+    }
+
+    return 0;
+}
+
Index: /vtcross/trunk/src/shell/configs/demo.xml
===================================================================
--- /vtcross/trunk/src/shell/configs/demo.xml	(revision 375)
+++ /vtcross/trunk/src/shell/configs/demo.xml	(revision 375)
@@ -0,0 +1,33 @@
+<!--
+This is an example XML file to interface with our cognitive engine.
+The library shall create a new table "myengine" with the following cols:
+  throughput spectral_efficiency log10_ber mod_scheme tx_power SNR
+-->
+<engine name="myengine" filename="myengine.sql">
+
+    <!-- utilities : QoS metrics -->
+    <utilities>
+        <utility name="tp" units="kbps" goal="max" target="125000" /> 
+        <utility name="packet_error" units="none" goal="min" target="1" />
+    </utilities>
+
+    <!-- radio parameters -->
+    <parameters>
+        <parameter name="bandwidth" units="hz" min="1" max="255" step="1">
+            <affect utility="tp" relationship="improve" />
+        </parameter>
+        <parameter name="tx_power" units="dBm" min="1" max="255" step="1">
+            <affect utility="packet_error" relationship="improve"/>
+        </parameter>
+    </parameters>
+
+    <!-- link/channel observations -->
+    <observables>
+        <observable name="throughput">
+            <affect utility="tp" relationship="improve" />
+        </observable>
+        <observable name="PER">
+            <affect utility="packet_error" relationship="improve" />
+        </observable>
+    </observables>
+</engine>
Index: /vtcross/trunk/src/shell/configs/example.xml
===================================================================
--- /vtcross/trunk/src/shell/configs/example.xml	(revision 375)
+++ /vtcross/trunk/src/shell/configs/example.xml	(revision 375)
@@ -0,0 +1,34 @@
+<!--
+This is an example XML file to interface with our cognitive engine.
+The library shall create a new table "myengine" with the following cols:
+  throughput spectral_efficiency log10_ber mod_scheme tx_power SNR
+-->
+<engine name="myengine" filename="myengine.sql">
+
+    <!-- utilities : QoS metrics -->
+    <utilities>
+        <utility name="throughput" units="kbps" goal="max" target="125" />
+        <utility name="spectral_efficiency" units="b/s/Hz" goal="max" />
+        <utility name="log10_ber" units="none" goal="min" target="-3" />
+    </utilities>
+
+    <!-- radio parameters -->
+    <parameters>
+        <parameter name="mod_scheme" min="1" max="4" step="1">
+            <!-- BPSK, QPSK, 8-PSK, 16-QAM -->
+            <affect utility="throughput" relationship="improve" />
+            <affect utility="spectral_efficiency" relationship="improve" />
+            <affect utility="log10_ber" relationship="degrade" />
+        </parameter>
+        <parameter name="tx_power" units="dBm" min="-30.0" max="0.0" step="0.1">
+            <affect utility="log10_ber" relationship="improve"/>
+        </parameter>
+    </parameters>
+
+    <!-- link/channel observations -->
+    <observables>
+        <observable name="SNR">
+            <affect utility="log10_ber" relationship="improve" />
+        </observable>
+    </observables>
+</engine>
