/* -*- mode: c++ -*-
*/
/*
GIFT, a flexible content based image retrieval system.
Copyright (C) 1998, 1999, 2000 CUI, University of Geneva
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _CPSETOFPSETS
#define _CPSETOFPSETS
#include <list>
#include <vector>
#include "CProbabilisticSet.h"
#include "CSelfDestroyPointer.h"
#include "helpers.h"
/**@Doc
In order to judge the consistency of comparisons performed
by the user we have to keep for each comparison (or each group of
comparisons, as remains to be tested) a set of elements with their
degree of conistency with the comparison. This part (for a single set)
is fulfilled by the CProbabilistic Set.
In this structure we keep now a set of such sets,
along with functions which
judge their consistency.
In fact this is a set of probabilistic sets together with
helper functions for hunting pictures.
todo:
We can add a set of PSets to the set (these are the different comparisons)
out of this set is calculated a list of iterator-lists
*/
template<class T>
class CPSetOfPSets{
/*@name Type definitions */
//@{
///An element of the content of this set
typedef CProbabilisticSet<T> CSet;
///An element of the content of this set
typedef pair<double,CSet* > CContentElement;
///The content of this set
typedef vector<CContentElement> CContent;
///
typedef CSet::CSequence CIDSequence;
/** We give the user the possibility to give assumptions.
An assumption is a set of contentelements.
is, that each of the following sets might be
added to this.
We will provide functions to associate a value to an assumption,
making it possible to pick the best one
*/
typedef CContentElement CAssumptionElement;
typedef vector<CAssumptionElement> CAssumption;
//@}
///
CContent mContent;
///
CAssumption* mAssumption;
/// In order to be able to give back a set
/// with the same properties as all other elements
/// in this set of set.
CSelfDestroyPointer<CSet> mSetPrototype;
///The current best guess of this structure.
CSelfDestroyPointer<CSet> mCurrentBest;
///
int mMaximumSize;
///
int mForgetAfterNthInconsistency;
///This is needed for some calculations
int mNumberOfImages;
public:
///
CPSetOfPSets(int inMaximumSize=10);
///
~CPSetOfPSets();
///
CPSetOfPSets(int inMaximumSize,
CSet* inSetPrototype);
///
void addElement(const CContentElement& inSet);
///
double evaluateAssumption(CAssumption* inAssumption);
///
double updateWeights(CContent& inContent)const;
///
double evaluateContent(const CContent& inContent,
bool inWithOutput=false,
string inOutputName="when_adding")const;
///
const T* getCurrentBest()const;
///
int getCurrentBestSize()const;
///
CIDSequence* drawSequenceFromCurrentBest(long inSize)const;
///
CSet* drawSetFromCurrentBest(long inSize)const;
///
void setPrototype(CSet* inPrototype);
///
CSet* getPrototypeClone()const;
///
double combine(CContentElement& inoutChanged,
const CContentElement& inChanger);
///reducing the size, if there are too many sets stored
void reduceToTheMax(CContent& inContent);
///
void setMaximumSize(int inMaximumSize);
///
void setForgetAfterNthInconsistency (int inN);
///
int size()const;
///
void clear();
///
void setNumberOfImages(const int& inNumberOfImages);
///
int getNumberOfImages()const;
};
///
template<class T>
void CPSetOfPSets<T>::setMaximumSize(int inMaximumSize){
mMaximumSize=inMaximumSize;
reduceToTheMax(mContent);
};
///
template<class T>
int CPSetOfPSets<T>::getCurrentBestSize()const{
return mCurrentBest->size();
};
///
template<class T>
const T* CPSetOfPSets<T>::getCurrentBest()const{
return mCurrentBest;
};
///
template<class T>
int CPSetOfPSets<T>::size()const{
return mContent.size();
};
///
template<class T>
void CPSetOfPSets<T>::clear(){
mContent.clear();
mCurrentBest=0;
};
///
template<class T>
CPSetOfPSets<T>::CIDSequence* CPSetOfPSets<T>::drawSequenceFromCurrentBest(long inSize)const{
cout << "EDO-1" << endl;
if(mCurrentBest){
CIDSequence* l=mCurrentBest->drawSequence(inSize);
return l;
}
else
return 0;
};
///
template<class T>
CPSetOfPSets<T>::CSet* CPSetOfPSets<T>::drawSetFromCurrentBest(long inSize)const{
cout << "EDO-1" << endl;
if(mCurrentBest)
return mCurrentBest->drawSet(inSize);
else
return 0;
};
template<class T>
CPSetOfPSets<T>::~CPSetOfPSets(){
};
template<class T>
CPSetOfPSets<T>::CPSetOfPSets(int inMaximumSize):
mAssumption(0),
mSetPrototype(new CSet()),
mCurrentBest(),
mMaximumSize(inMaximumSize)
{
};
template<class T>
CPSetOfPSets<T>::CPSetOfPSets(int inMaximumSize,
CSet* inSetPrototype):
mAssumption(0),
mSetPrototype(inSetPrototype),
mMaximumSize(inMaximumSize)
{
};
template<class T>
void CPSetOfPSets<T>::setPrototype(CSet* inPrototype){
mSetPrototype=inPrototype;
}
template<class T>
CPSetOfPSets<T>::CSet* CPSetOfPSets<T>::getPrototypeClone()const{
return mSetPrototype ? mSetPrototype->clone():0;
}
template<class T>
double CPSetOfPSets<T>::combine(CContentElement& inoutChanged,
const CContentElement& inChanger){
if(inChanger.first>0.5){
return inoutChanged.second->intersect(*inChanger.second);
}else{
return 0;
}
}
template<class T>
void CPSetOfPSets<T>::addElement(const CContentElement& inSet){
cout << "BEFADD:"
<< mContent.end()-mContent.begin()
<< endl;
cout << "A" << flush;
mContent.push_back(inSet);
cout << "BEFADD2:"
<< mContent.end()-mContent.begin()
<< endl;
{
CProbabilisticSet<int>::CElementVector lDiagnosis;
mContent.back().second->getContent(lDiagnosis);
show_ProbabilisticSetElements(lDiagnosis.begin(),
lDiagnosis.end(),
"Added");
}
cout << "B" << flush;
if(mContent.size()>1){
updateWeights(mContent);
evaluateContent(mContent,
true,
"NewState");
mCurrentBest=mContent.back().second;
mContent.pop_back();
cout << endl
<< "---Checking Consistency---"
<< endl;
//pruning: How to get rid of too old elements:
//combine them to one element
if(mContent.end()-mContent.begin()>mMaximumSize){
cout << "+++++flattening+++++"
<< endl;
// Either combine the knowledge of the element
// which has to be compressed with existing
// older and presently believed knowledge
reduceToTheMax(mContent);
}
}else{
cout << "TAKING"
<< endl;
mCurrentBest=mContent.back().second->clone();
}
cout << endl
<< "--------------------a new best choice found, size: "
<< mCurrentBest->size()
<< "Total size"
<< size()
<< endl;
cout << "AFTADD: Number of Distributions: "
<< mContent.end()-mContent.begin()
<< ", Number of elements in current back/best distribution:"
<< mContent.back().second->size()
<< "/"
<< mCurrentBest->size()
<< endl;
};
template<class T>
double CPSetOfPSets<T>::updateWeights(CContent& inContent)const{
assert(inContent.size());
if(inContent.size()==1){
inContent.front().first=1.0;
return 1;
}
CContent::iterator lLast=inContent.end();
lLast--;
CSelfDestroyPointer<CSet> lLastIntersection=
inContent.back().second->clone();
CSet* lCurrentIntersection=inContent.back().second->clone();
cout << "UPDATE" << endl;
double lProbabilityThatFeedback=1;
if(mCurrentBest && inContent.size()){
CSelfDestroyPointer<CSet> lCurrentBest(mCurrentBest->clone());
cout << "HERE"
<< lCurrentIntersection->size()
<<endl;
lProbabilityThatFeedback=lCurrentBest->intersect(*lCurrentIntersection)
/(lCurrentBest->countAboveThreshold()+1);
}
// the probability that the user makes this sequence
// of feedbacks
double lCurrentProbability=1;
double lLastProbability=1;
int lZeroCounter=0;
if(inContent.size()>1){
CContent::iterator i=lLast;
while(i!=inContent.begin()
&& (lZeroCounter<mForgetAfterNthInconsistency)){
cout << "X" << flush;
i--;
cout << "Distance to the beginning:"
<< i-inContent.begin()
<< ","
<< i->first
<< ","
<< int(i->second)
<< endl
<< flush;
lCurrentProbability *= lCurrentIntersection->intersect(*(i->second));
cout << "here"
<< endl;
#ifndef CLEAN
if(lCurrentProbability!=0 && !lZeroCounter){
#endif //CLEAN
i->first=1;
cout << "if1" << endl;
lLastProbability=lCurrentProbability;
lLastIntersection=lCurrentIntersection->clone();
cout << "if1b" << endl;
#ifndef CLEAN
}else{
lZeroCounter++;
//inconsistency detected
i->first=0;
assert(lLastIntersection);
{
lCurrentProbability=lLastProbability;
delete lCurrentIntersection;
lCurrentIntersection=lLastIntersection->clone();
cout << "###DETECTED INCONSISTENCY###" << endl;
}
cout << "if2" << endl;
}
#endif //CLEAN
}
while(i!=inContent.begin()){
(--i)->first=0;
cout << "###forgetting###"
<< endl;
}
}
inContent.push_back(make_pair(lProbabilityThatFeedback/mNumberOfImages,
lCurrentIntersection));
/* #else */
/* lCurrentIntersection->intersect(*inContent.front().second); */
/* inContent.push_back(make_pair(lProbabilityThatFeedback/mNumberofImages, */
/* lCurrentIntersection)); */
/* #endif */
return 1+lProbabilityThatFeedback/mNumberOfImages;
}
template<class T>
double CPSetOfPSets<T>::evaluateContent(const CContent& inContent,
bool inWithOutput,
string inOutputName)const{
double lReturnValue=0;//a measure for the quality of the inContent
for(CContent::const_iterator i=inContent.begin();
i!=inContent.end();
i++){
//cout << ":" << i->first << endl;
assert((i->first>=0)&&(i->first<=1));
lReturnValue+=i->first;
}
if(lReturnValue>0){
lReturnValue =
inContent.back().second
->calculateInformation()//too much information is bad
*
sqrt(lReturnValue);//too much size is bad
}
{
CProbabilisticSet<int>::CElementVector lDiagnosis;
inContent.back().second->getContent(lDiagnosis);
if(inWithOutput){
show_ProbabilisticSetElements(lDiagnosis.begin(),
lDiagnosis.end(),
inOutputName);
}
}
return lReturnValue ;
}
template<class T>
double CPSetOfPSets<T>::evaluateAssumption(CAssumption* inAssumption){
mAssumption
=
inAssumption;
double lReturnValue=0;
if(mAssumption->size()){
//allocate a vector
CContent lContentPlusAssumption(mContent.begin(),
mContent.end());
// add each element of the assumption to the vector
// which we have just built up. Evaluate its
// goodness and then make a weighted average of this
for(CAssumption::const_iterator i=inAssumption->begin();
i!=mAssumption->end();
i++){
cout << "bis hier"
<< flush;
CSet* lCurrentAssumption=i->second->clone();
lContentPlusAssumption.push_back(make_pair(1,
lCurrentAssumption));
double lProbability=updateWeights(lContentPlusAssumption);
double lAssumptionValue=evaluateContent(lContentPlusAssumption);
lReturnValue +=
//a-priory weight given by the user (will maybe stay unused)
i->first
//probability that this element of the assumption
//is taken by the user
* lProbability
//value of this assumptionElement
* lAssumptionValue
;
cout << "Probability :"
<< lProbability
<< endl;
//very dirty
delete lContentPlusAssumption.back().second;
lContentPlusAssumption.pop_back();
delete lContentPlusAssumption.back().second;
lContentPlusAssumption.pop_back();
}
/*if(lContentPlusAssumption.size())
for(CContent::iterator i = lContentPlusAssumption.begin();
i != lContentPlusAssumption.end();
i++){
cout << "deleteing" << i->second << endl << flush;
delete (i->second);
}*/
}
return lReturnValue;
}
template<class T>
void CPSetOfPSets<T>::reduceToTheMax(CContent& inContent){
if(!mMaximumSize){
cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%clean pichunter: take what comes"
<< endl;
if(inContent.size()>=2){
CContent::iterator lSecondOldestElement=inContent.begin();
lSecondOldestElement++;
inContent.front().second->intersect(*lSecondOldestElement->second);
inContent.front().second->normalize();
inContent.erase(lSecondOldestElement);//newly added
mCurrentBest=mContent.front().second->clone();
}
}else{
cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Target tracker case "
<< endl;
if(inContent.front().first>0.5){
CContent::iterator lSecondOldestElement=inContent.begin();
lSecondOldestElement++;
combine(inContent.front(),
*lSecondOldestElement);
inContent.erase(lSecondOldestElement);
}else{
/// or delete the old unbelieved knowledge
inContent.erase(inContent.begin());
}
}
}
///
template<class T>
void CPSetOfPSets<T>::setForgetAfterNthInconsistency (int inN){
mForgetAfterNthInconsistency=inN;
};
///
template<class T>
void CPSetOfPSets<T>::setNumberOfImages(const int& inNumberOfImages){
mNumberOfImages= inNumberOfImages;
};
///
template<class T>
int CPSetOfPSets<T>::getNumberOfImages()const{
return mNumberOfImages;
};
#endif
Documentation generated by muellerw@pc7170 on Son Okt 8 16:04:40 CEST 2000