/* Copyright 2009 Virginia Polytechnic Institute and State University Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /*! This CE was written to extend the functionality of a basic CBR-based CE for * use with the OSSIE demonstration. This file contains the implementation for * both the OSSIE CBR as well as the OSSIE Cognitive Engine. */ #include "OSSIE_CE.h" using namespace std; ossieCBR::ossieCBR(string _filename, string _tablename, string _cols[], uint32_t _len) { /* Store database properties. */ filename = _filename; tablename = _tablename; numColumns = _len; /* Create the database (or open it if it already exists). */ OpenDatabase(); /* Generate the command that will create the initial table within the * VTCROSS database. */ command = "CREATE TABLE " + tablename + "("; for(size_t i = 0; i < numColumns; i++) { command += _cols[i] + " FLOAT"; /* If this column is not the last entry, add a comma to the command in * preperation for the next entry. */ if(i != numColumns - 1) command += ", "; } command += ", timestamp DATE, PRIMARY KEY(tx_power));"; /* Execute the generated command. At this point, the database is ready for * use. */ ExecuteCommand(); } int32_t ossieCBR::Search(string _names[], int32_t *_ops, float *_vals, uint32_t _n, \ float *_retvals, int32_t evf) { float lower_limit; float upper_limit; char str_buffer[64]; command = "select " + tablename + ".* from " + tablename + " where "; for(size_t i = 0; i < _n; i++) { /* Make sure that the passed ops value is valid. */ if((_ops[i] < 0) || (_ops[i] > 5)) { ERROR(1, "Error: cbr_search(), invalid ops id : %d\n", _ops[i]); } command += _names[i] + " between "; lower_limit = _vals[i] * (1 - ((float) evf / 100)); upper_limit = _vals[i] * (1 + ((float) evf / 100)); LOG("%f %f %f\n", lower_limit, upper_limit, _vals[i]); sprintf(str_buffer, "%f", lower_limit); command += string(str_buffer) + " and "; sprintf(str_buffer, "%f", upper_limit); command += string(str_buffer); if(i < _n - 1) command += " AND "; else command += " order by abs(utility) asc, timestamp desc;"; } LOG("Search command: %s\n", command.c_str()); return ExecuteSearchCommand(_retvals); } int32_t ossieCBR::Update(string _where[], string _set[], float *_wherevals, float *_setvals, uint32_t _wherelen, uint32_t _setlen) { char str_buffer[64]; command = "UPDATE " + tablename + " SET "; for(size_t i = 0; i < _setlen; i++) { command += _set[i] + " = "; sprintf(str_buffer, "%f", _setvals[i]); command += string(str_buffer) + " "; if(i != _setlen - 1) command += ", "; } command += ", timestamp = DATETIME('NOW') WHERE "; for(size_t j = 0; j < _wherelen; j++) { command += _where[j] + " = "; sprintf(str_buffer, "%f", _wherevals[j]); command += string(str_buffer) + " "; if(j != _wherelen - 1) command += "AND "; } command += ";"; return ExecuteCommand(); } /******************** END DEFINITION OF OSSIE CBR CLASS ****************/ OSSIE_CE::OSSIE_CE(const char* serverName, const char* serverPort, \ const int32_t numFields, const bool SML) \ : CognitiveEngine(serverName, serverPort, numFields, SML) { BuildCognitiveEngine(); } OSSIE_CE::~OSSIE_CE() { delete myCBR; delete [] pList; delete [] oList; delete [] uList; delete [] radioInfo; } // This function needs serious help and is very confusing void OSSIE_CE::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]; string nameList[numberColumns]; string utilList[utilColumns]; size_t columnUtilIndex = 0; for (size_t i = 0; i < radioInfo->numUtilities; i++){ utilList[columnUtilIndex] = uList[i].name; columnUtilIndex++; } utilList[columnUtilIndex] = "utility"; size_t columnIndex = 0; for (size_t i = 0; i < radioInfo->numParameters; i++){ nameList[columnIndex] = parameters[i].name; 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++; } myCBR->Update(nameList, utilList, valList, newUtilityVals, numberColumns, utilColumns); } void OSSIE_CE::ReceiveFeedback(Observable *observables, Parameter *parameters, \ std::string service) { LOG("Cognitive Engine:: Receiving feedback.\n"); } void OSSIE_CE::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"); } void OSSIE_CE::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"); } Parameter* OSSIE_CE::GetSolution(Observable *observables, Parameter *currentParameters) { LOG("Cognitive Engine:: Generating solution.\n"); string searchNames[radioInfo->numObservables]; for(size_t i = 0; i < radioInfo->numObservables; i++) { searchNames[i] = observables[i].name; } 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] = 2; } else if(strcmp(uList[i].goal.c_str(), "min") == 0) { searchOps[i] = 4; } } myCBR->Print(); /* CBR specific call */ uint32_t rc = myCBR->Search(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; string allNames[numberColumns]; size_t allNameIndex = 0; for(size_t i = 0; i < radioInfo->numUtilities; i++) { allNames[allNameIndex] = uList[i].name; returnValues[allNameIndex] = uList[i].target; allNameIndex++; } for(size_t i = 0; i < radioInfo->numParameters; i++) { allNames[allNameIndex] = pList[i].name; allNameIndex++; } for(size_t i = 0; i < radioInfo->numObservables; i++) { allNames[allNameIndex] = oList[i].name; returnValues[allNameIndex] = observables[i].value; allNameIndex++; } allNames[allNameIndex] = "utility"; // Add row to CBR. myCBR->AddRow(allNames, returnValues, returnValueIndex+1); return pList; } Parameter* OSSIE_CE::GetSolution(Observable *observables, \ Parameter *currentParameters, std::string service) { LOG("Cognitive Engine:: Generating solution for %s service.\n", service.c_str()); return pList; } void OSSIE_CE::BuildCognitiveEngine() { string filename = "ex1"; string tablename = "data"; uint32_t numberColumns = radioInfo->numUtilities + radioInfo->numParameters + \ radioInfo->numObservables + 1; string cols[numberColumns]; size_t columnIndex = 0; for (size_t i = 0; i < radioInfo->numUtilities; i++){ cols[columnIndex] = uList[i].name; columnIndex++; } for (size_t i = 0; i < radioInfo->numParameters; i++){ cols[columnIndex] = pList[i].name; columnIndex++; } for (size_t i = 0; i < radioInfo->numObservables; i++){ cols[columnIndex] = oList[i].name; columnIndex++; } cols[columnIndex] = "utility"; myCBR = new ossieCBR(filename, tablename, cols, numberColumns); } void OSSIE_CE::PerformUpdatePerformance() { /* Receive Set of current Parameters */ char buffer[256]; 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; } void OSSIE_CE::PerformRequestOptimizationService() { /* Receive Set of Observables */ LOG("\nCognitive Engine:: Receiving service name\n"); char buffer[256]; 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; } void OSSIE_CE::PerformRequestOptimization() { /* Receive Set of Observables */ LOG("\nCognitive Engine:: Receiving Observable Parameters\n"); char buffer[256]; 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; } void OSSIE_CE::PerformQueryComponentType() { SendComponentType(); } void OSSIE_CE::PerformConnectSML() { /* 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); } } void OSSIE_CE::PerformDisconnectSML() { /* 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); } } void OSSIE_CE::PerformResetEngineCognitive() { Reset(); } void OSSIE_CE::PerformShutdownEngineCognitive() { Shutdown(); }