/* Virginia Tech Cognitive Radio Open Source Systems * Virginia Tech, 2009 * * LICENSE INFORMATION GOES HERE */ /* DESCRIPTION OF FILE. */ #include #include #include #include #include "vtcross/cognitive_engine.h" #include "vtcross/common.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" #define TXPOWER 1 #define BER_ENV 1 #define BER_OBJ 1 #define DECREMENTSCALE 5 #define INCREMENTSCALE 5 #define EVF 20 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(); } } // This function needs serious help and is very confusing void CognitiveEngine::ReceiveFeedback(Observable *observables, Parameter *parameters) { LOG("Cognitive Engine:: Receiving feedback.\n"); uint32_t numberColumns = radioInfo->numParameters; uint32_t utilColumns = radioInfo->numUtilities + 1; float valList[numberColumns]; float newUtilityVals[numberColumns]; char *nameList[numberColumns]; char *utilList[utilColumns]; size_t columnUtilIndex = 0; for (size_t i = 0; i < radioInfo->numUtilities; i++){ utilList[columnUtilIndex] = (char*)uList[i].name.c_str(); columnUtilIndex++; } utilList[columnUtilIndex] = (char*) "utility"; size_t columnIndex = 0; for (size_t i = 0; i < radioInfo->numParameters; i++){ nameList[columnIndex] = (char*)parameters[i].name.c_str(); columnIndex++; } size_t newUtilityValueIndex = 0; for(size_t i = 0; i < radioInfo->numUtilities; i++) { // This is a special case because the observable is also the utility newUtilityVals[newUtilityValueIndex] = observables[i].value; newUtilityValueIndex++; } /* Calculate Utility */ float newUtilityValue = 0; for(size_t i = 0; i < radioInfo->numUtilities; i++) { newUtilityValue = newUtilityValue + (uList[i].target - observables[i].value); } newUtilityVals[newUtilityValueIndex] = newUtilityValue; size_t returnValueIndex = 0; for(size_t i = 0; i < radioInfo->numParameters; i++) { valList[returnValueIndex] = parameters[i].value; returnValueIndex++; } // cbr_update(database,where,set,whereval,setval,..) cbr_update(myCBR, nameList, utilList, valList, newUtilityVals, numberColumns, utilColumns); } 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->numObservables]; for(size_t i = 0; i < radioInfo->numObservables; i++) { searchNames[i] = (char*)observables[i].name.c_str(); } float searchVals[radioInfo->numObservables]; for(size_t i = 0; i < radioInfo->numUtilities; i++) { searchVals[i] = observables[i].value; } 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_print(myCBR); /* CBR specific call */ uint32_t rc = cbr_search(myCBR, searchNames, searchOps, searchVals, radioInfo->numUtilities, returnValues, EVF); 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] > (uList[0].target * 0.2)) { returnValues[1] = returnValues[1] - DECREMENTSCALE*fabs(returnValues[numberColumns-1]); LOG("RREEEALLLY CLOSE1\n %f", fabs(returnValues[numberColumns-1])); } else if(returnValues[numberColumns-1] < -(uList[0].target * 0.2)) { LOG("RREEEALLLY CLOSE2\n %f", fabs(returnValues[numberColumns-1])); returnValues[1] = returnValues[1] + INCREMENTSCALE*fabs(returnValues[numberColumns-1]); } else { LOG("RREEEALLLY CLOSE\n"); } } 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[1] = currentParameters[0].value; } 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] = observables[i].value; allNameIndex++; } allNames[allNameIndex] = (char *) "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] = (char *)"utility"; myCBR = cbr_create(filename, tablename, cols, numberColumns); }