#include "stdafx.h" #include "cbr.h" #include <ipl98/cpp/image.h> #include <cstdlib> // ostream needed for endl #include <ostream> #include <cmath> // iostream needed for cout #include <iostream> #include <fstream> using namespace std; struct Cbr::a_case oldCases[1000]; int casecount=0; int first=0; int reusethreshold=80; ofstream logg ("logg.txt", ios::app); //writing to file in append mode void Cbr::Retrieve(struct a_case thenewcase){ logg << "------------------------------------------------" << "\n"; //logg << "Starting Retrieve Stage" << "\n"; // must search case database for relevant cases Cbr::ReadCasesFromDB(); logg << "Done reading cases from DB." << "\n"; int one = 0; int two = 0; int three = 0; if(casecount==0){ logg << "There are no cases in the case database." << "\n"; Cbr::Retain(0,thenewcase,0,0,0); } else{ Cbr::CompareCasesRetrieve(thenewcase, &one, &two, &three); Cbr::Reuse(thenewcase, one, two, three); } Cbr::UpdateDataBase(); logg.close(); } void Cbr::ReadCasesFromDB(){ ifstream ci ("example.txt", ios::in); //reading from file string s[1000]; if (ci.is_open()) { int i = 0; int internal = 0; char ss[100]; //must get one line at a time while(!ci.getline(ss, 100).eof()){ cout << ss << endl; //must check if the line identifies a new case if(strtol(ss,0,10)==999){ casecount++; internal=13; } if(internal == 0){ oldCases[casecount].case_nr=strtol(ss,0,10); internal++; } else if(internal == 1){ oldCases[casecount].nr_of_objects=strtol(ss,0,10); internal++; } else if(internal == 2){ oldCases[casecount].largest_object=strtol(ss,0,10); internal++; } else if(internal == 3){ char * tt; oldCases[casecount].avg_object=strtod(ss,&tt); internal++; } else if(internal == 4){ char * tt; oldCases[casecount].avg_intensity=strtod(ss, &tt); internal++; } else if(internal == 5){ char * tt; oldCases[casecount].change_intensity=strtod(ss, &tt); internal++; } else if(internal == 6){ char * tt; oldCases[casecount].weight_nr_of_objects=strtod(ss,&tt); internal++; } else if(internal == 7){ char * tt; oldCases[casecount].weight_largest_object=strtod(ss, &tt); internal++; } else if(internal == 8){ char * tt; oldCases[casecount].weight_avg_object=strtod(ss, &tt); internal++; } else if(internal == 9){ char * tt; oldCases[casecount].weight_avg_intensity=strtod(ss, &tt); internal++; } else if(internal == 10){ char * tt; oldCases[casecount].weight_change_intensity=strtod(ss, &tt); internal++; } else if(internal == 11){ char * tt; oldCases[casecount].alarm_situation=strtod(ss, &tt); internal++; } else if(internal == 12){ oldCases[casecount].textual=ss; cout << "reading from the file: " << ss << endl; internal++; } else if(internal == 13){ internal = 0; } } ci.close(); } else logg << "Unable to open file" << "\n"; } void Cbr::CompareCasesRetrieve(struct a_case thenewcase, int* best, int* second, int* third){ logg << "Comparing cases in the retrieve stage." << "\n"; double bestvalue=10000000000000000000; double secondbestvalue=10000000000000000000; double thirdbestvalue=10000000000000000000; //must do a comparison with all the cases in the database and find the best match for(unsigned int i=1;i<casecount+1;i++){ //must sum up difference between all features!! double weightCo = 1/(oldCases[i].weight_largest_object+oldCases[i].weight_nr_of_objects+oldCases[i].weight_avg_object+oldCases[i].weight_avg_intensity+oldCases[i].weight_change_intensity); double firstF = (pow(thenewcase.nr_of_objects-oldCases[i].nr_of_objects,2))*oldCases[i].weight_nr_of_objects; double secondF = (pow(thenewcase.largest_object-oldCases[i].largest_object,2))*oldCases[i].weight_largest_object; double thirdF = (pow(thenewcase.avg_object-oldCases[i].avg_object,2))*oldCases[i].weight_avg_object; double fourthF = (pow(thenewcase.avg_intensity-oldCases[i].avg_intensity,2))*oldCases[i].weight_avg_intensity; double fifthF = (pow(thenewcase.change_intensity-oldCases[i].change_intensity,2))*oldCases[i].weight_change_intensity; //add more features when nesc double solution = weightCo*((firstF*0.5)+(secondF*0.5)+(thirdF*0.5)+(fourthF*10)+(fifthF*10)); if(solution<bestvalue){ thirdbestvalue=secondbestvalue; secondbestvalue=bestvalue; bestvalue=solution; (*third)=(*second); (*second)=(*best); (*best)=oldCases[i].case_nr; } else if(solution<secondbestvalue){ thirdbestvalue=secondbestvalue; secondbestvalue=solution; (*third)=(*second); (*second)=oldCases[i].case_nr; } else if(solution<thirdbestvalue){ thirdbestvalue=solution; (*third)=oldCases[i].case_nr; } } cout << "the selected best case is case nr: " << *best << " with textual description: " << oldCases[*best].textual << endl; cout << "the selected secondbest case is case nr: " << *second << " with textual description: " << oldCases[*second].textual << endl; cout << "the selected third best case is case nr: " << *third << " with textual description: " << oldCases[*third].textual << endl; logg << "The best case is case " << *best << ": " << oldCases[*best].textual << "." << "\n"; logg << "The second best case is case " << *second << ": " << oldCases[*second].textual << "." << "\n"; logg << "The third best case is case " << *third << ": " << oldCases[*third].textual << "." << "\n"; } void Cbr::RaiseAlarm(int alarm){ if(alarm==1){ logg << "ALARM IS RAISED!" << "\n"; }else{ logg << "ALARM IS NOT RAISED!" << "\n"; } } void Cbr::AddNewCase(struct a_case thenewcase){ oldCases[casecount+1].case_nr=casecount+1; oldCases[casecount+1].nr_of_objects=thenewcase.nr_of_objects; oldCases[casecount+1].largest_object=thenewcase.largest_object; oldCases[casecount+1].avg_object=thenewcase.avg_object; oldCases[casecount+1].avg_intensity=thenewcase.avg_intensity; oldCases[casecount+1].change_intensity=thenewcase.change_intensity; oldCases[casecount+1].weight_nr_of_objects=thenewcase.weight_nr_of_objects; oldCases[casecount+1].weight_largest_object=thenewcase.weight_largest_object; oldCases[casecount+1].weight_avg_object=thenewcase.weight_avg_object; oldCases[casecount+1].weight_avg_intensity=thenewcase.weight_avg_intensity; oldCases[casecount+1].weight_change_intensity=thenewcase.weight_change_intensity; oldCases[casecount+1].alarm_situation=thenewcase.alarm_situation; oldCases[casecount+1].textual=thenewcase.textual; casecount++; } void Cbr::UpdateDataBase(){ logg << "Updating the database." << "\n"; ofstream ofs ("example.txt", ios::out); //writing to file in rewrite mode for(unsigned int y=1;y<casecount+1;y++){ ofs << 999 << "\n"; ofs << y << "\n"; ofs << oldCases[y].nr_of_objects << "\n"; ofs << oldCases[y].largest_object << "\n"; ofs << oldCases[y].avg_object << "\n"; ofs << oldCases[y].avg_intensity << "\n"; ofs << oldCases[y].change_intensity << "\n"; ofs << oldCases[y].weight_nr_of_objects << "\n"; ofs << oldCases[y].weight_largest_object << "\n"; ofs << oldCases[y].weight_avg_object << "\n"; ofs << oldCases[y].weight_avg_intensity << "\n"; ofs << oldCases[y].weight_change_intensity << "\n"; ofs << oldCases[y].alarm_situation << "\n"; ofs << oldCases[y].textual << "\n"; } ofs << "end.\n"; ofs.close(); } double Cbr::CompareCasesReuse(struct a_case firstcase, struct a_case secondcase){ double casediff=0; //must do a comparison with all the cases in the database and find the best match //must sum up difference between all features!! double firstF = (pow(firstcase.nr_of_objects-secondcase.nr_of_objects,2)); double secondF = (pow(firstcase.largest_object-secondcase.largest_object,2)); double thirdF = (pow(firstcase.avg_object-secondcase.avg_object,2)); double fourthF = (pow(firstcase.avg_intensity-secondcase.avg_intensity,2)); double fifthF = (pow(firstcase.change_intensity-secondcase.change_intensity,2)); //add more features when nesc casediff = sqrt(firstF+secondF+thirdF+fourthF+fifthF); return casediff; } void Cbr::Reuse(struct a_case thenewcase, int oldcaseindex, int second, int third){ //logg << "starting reuse stage" << "\n"; //must test case resemble value if(CompareCasesReuse(thenewcase, oldCases[oldcaseindex])<reusethreshold){//the cases are sufficiently similar logg << "The cases are similar enough to pass reuse." << "\n"; if(oldCases[oldcaseindex].alarm_situation==1){ logg << "The retrieved case is approved as solution and represents an alarm." << "\n"; Cbr::RaiseAlarm(1); } else{ logg << "The retrieved case is approved as solution and does not represent an alarm." << "\n"; Cbr::RaiseAlarm(0); } Cbr::Retain(2, thenewcase, oldcaseindex, second, third); }else{ logg << "The cases are not similar enough to pass reuse." << "\n"; //develop new case!!!! int test=1; int buffer, one, two, three; int found=0; one = oldcaseindex; two = second; three = third; if(casecount>2){ while(found==0){ test = Cbr::Revise(thenewcase, one, two, three, test, &found); buffer=one; one=two; two=three; three=buffer; } if(test==2){ // the first case is approved Cbr::Retain(2, thenewcase, oldcaseindex, second, third);//found a case } else if(test==3){ // the second case is approved Cbr::Retain(3, thenewcase, oldcaseindex, second, third);//found a case } else if(test==4 && found==1){ // the third case is approved Cbr::Retain(4, thenewcase, oldcaseindex, second, third);//found a case } else if(test==4 && found==2 ){ //no cases approved create new case Cbr::Retain(1, thenewcase, oldcaseindex, second, third);//never found a case } } else{ //if there are less then 3 cases in the database, just check the best one!!!! test = Cbr::Revise(thenewcase, one, two, three, test, &found); if(found==1){ // the first case is approved Cbr::Retain(2, thenewcase, oldcaseindex, second, third);//found a case } else{ Cbr::Retain(1, thenewcase, oldcaseindex, second, third);//never found a case } } } } int Cbr::Revise(struct a_case thenewcase, int oldcaseindex, int second, int third, int args, int* found){ //must detect textual description and ask user if the selected case can be approved anyway cout << "the textual description of the retrieved case was: " << oldCases[oldcaseindex].textual << "." << endl; cout << "---------------------------------------------" << endl; cout << " on the basis of the texual description of the retrieved case, please enter yes or no " << endl; string approved; cin >> approved; cin.ignore(); cout << " does this image represent an alarm situation? please enter yes or no " << endl; string alarm; cin >> alarm; cin.ignore(); logg << "Case " << oldCases[oldcaseindex].case_nr << " approved by user: " << approved << "." << "\n"; cout << "user said: " << approved << " and is this an alarm situation? " << alarm << endl; if(approved=="yes"){ *found=1; if(alarm=="yes" && oldCases[oldcaseindex].alarm_situation == 1){ Cbr::RaiseAlarm(1); thenewcase.alarm_situation=1; //should raise alarm } else if(alarm=="no" && oldCases[oldcaseindex].alarm_situation == 0){ Cbr::RaiseAlarm(0); thenewcase.alarm_situation=0; } else{ cout << "user approved wrong solution" << endl; //this should never happen. User approved wrong solution } }else if(approved=="no"){ //need to try next case if(args==3){ *found=2; } if(alarm=="yes"){ //implies that one should add a new case to the database //should raise alarm thenewcase.alarm_situation=1; } else if(alarm=="no"){ //implies that one should add a new case to the database thenewcase.alarm_situation=0; } else{ cout << " something fishy is going on" << endl; } }else{ cout << "something wrong" << endl; } args = args + 1; return args; } void Cbr::UpdateWeight(int args, struct a_case thenewcase, int oldcaseindex){ logg << "Updating weights with oldcase: " << oldcaseindex << " and args " << args << "." << "\n"; logg << "Case text: " << oldCases[oldcaseindex].textual << "\n"; double newarray[5]; double oldarray[5]; double weightarray[5]; newarray[0]=thenewcase.nr_of_objects; newarray[1]=thenewcase.largest_object; newarray[2]=thenewcase.avg_object; newarray[3]=thenewcase.avg_intensity; newarray[4]=thenewcase.change_intensity; oldarray[0]=oldCases[oldcaseindex].nr_of_objects; oldarray[1]=oldCases[oldcaseindex].largest_object; oldarray[2]=oldCases[oldcaseindex].avg_object; oldarray[3]=oldCases[oldcaseindex].avg_intensity; oldarray[4]=oldCases[oldcaseindex].change_intensity; double weightacc=0; weightacc=weightacc+oldCases[oldcaseindex].weight_nr_of_objects+oldCases[oldcaseindex].weight_largest_object+oldCases[oldcaseindex].weight_avg_object+oldCases[oldcaseindex].weight_avg_intensity+oldCases[oldcaseindex].weight_change_intensity; weightarray[0]=oldCases[oldcaseindex].weight_nr_of_objects; weightarray[1]=oldCases[oldcaseindex].weight_largest_object; weightarray[2]=oldCases[oldcaseindex].weight_avg_object; weightarray[3]=oldCases[oldcaseindex].weight_avg_intensity; weightarray[4]=oldCases[oldcaseindex].weight_change_intensity; double threshold = 2.5; int numberoffeatures = 5; double highper = 1.37; double lowper = 1.112; for(unsigned int i=0;i<numberoffeatures;i++){ if(i==2){ threshold=1.3; } if(i==3){ threshold=1.1; } double firstnr=0; if(newarray[i]>oldarray[i]){ firstnr=(newarray[i]/oldarray[i]); }else{ firstnr=(oldarray[i]/newarray[i]); } if(firstnr<0){firstnr=(-firstnr);} if(firstnr<threshold){ for(unsigned int j=0;j<numberoffeatures;j++){ if(i==j){ if(args==2){ weightarray[j]=weightarray[j]*highper; }else{ weightarray[j]=weightarray[j]/highper; } }else{ if(args==2){ weightarray[j]=weightarray[j]/lowper; }else{ weightarray[j]=weightarray[j]*lowper; } } } j=0; }else{ for(unsigned int j=0;j<numberoffeatures;j++){ if(i==j){ if(args==2){ weightarray[j]=weightarray[j]/highper; }else{ weightarray[j]=weightarray[j]*highper; } }else{ if(args==2){ weightarray[j]=weightarray[j]*lowper; }else{ weightarray[j]=weightarray[j]/lowper; } } } j=0; } } i=0; weightacc=0; for(unsigned int hh=0;hh<numberoffeatures;hh++){ weightacc=weightacc+weightarray[hh]; } //weights are now set in the weightarray!! Must update oldCases oldCases[oldcaseindex].weight_nr_of_objects=(weightarray[0]/(weightacc/5)); oldCases[oldcaseindex].weight_largest_object=(weightarray[1]/(weightacc/5)); oldCases[oldcaseindex].weight_avg_object=(weightarray[2]/(weightacc/5)); oldCases[oldcaseindex].weight_avg_intensity=(weightarray[3]/(weightacc/5)); oldCases[oldcaseindex].weight_change_intensity=(weightarray[4]/(weightacc/5)); } void Cbr::Retain(int args, struct a_case thenewcase, int oldcaseindex, int second, int third){ //if a new case is to be created the weights must be set and the weights of the retrieved case must be updated: if(args==1){ cout << "a new case is to be created. please enter a textual description of the case here:" << endl; char result[100]; cin.getline(result,100); cin.ignore(); string ress = result; logg << "A new case is to be created because no matching cases were found in the database." << "\n"; cout << "user entered:" << result << endl; if(thenewcase.alarm_situation==1){ Cbr::RaiseAlarm(1); }else{ Cbr::RaiseAlarm(0); } if(casecount>3){ Cbr::UpdateWeight(1, thenewcase, oldcaseindex); Cbr::UpdateWeight(1, thenewcase, second); Cbr::UpdateWeight(1, thenewcase, third); } else{ logg << "The weights of the retrieved case was not updated because there is so few cases in the database." << "\n"; } thenewcase.weight_largest_object=1; thenewcase.weight_nr_of_objects=1; thenewcase.weight_avg_object=1; thenewcase.weight_avg_intensity=1; thenewcase.weight_change_intensity=1; thenewcase.textual=ress; Cbr::AddNewCase(thenewcase); } else if(args==2){ Cbr::UpdateWeight(2, thenewcase, oldcaseindex); } else if(args==3){ Cbr::UpdateWeight(2, thenewcase, second); Cbr::UpdateWeight(1, thenewcase, oldcaseindex); } else if(args==4){ Cbr::UpdateWeight(2, thenewcase, third); Cbr::UpdateWeight(1, thenewcase, oldcaseindex); Cbr::UpdateWeight(1, thenewcase, second); } else if(args==0){//this is the very first case.. just add it to the database cout << "a very first new case is to be created. please enter a textual description of the case here:" << endl; char text[100]; cin.getline(text, 100); cin.ignore(); string textt=text; cout << " does this image represent an alarm situation? please enter yes or no " << endl; char alarm[100]; cin >> alarm; string alarms=alarm; cin.ignore(); if(alarms=="yes"){ thenewcase.alarm_situation=1; Cbr::RaiseAlarm(1); }else{ thenewcase.alarm_situation=0; Cbr::RaiseAlarm(0); } thenewcase.weight_largest_object=1; thenewcase.weight_nr_of_objects=1; thenewcase.weight_avg_object=1; thenewcase.weight_avg_intensity=1; thenewcase.weight_change_intensity=1; thenewcase.textual=textt; Cbr::AddNewCase(thenewcase); } }