00001
00002
00003
00004
00005 #ifndef PSYCHOMETRIC_H
00006 #define PSYCHOMETRIC_H
00007
00008 #include <vector>
00009 #include <cmath>
00010 #include <algorithm>
00011 #include "core.h"
00012 #include "sigmoid.h"
00013 #include "errors.h"
00014 #include "prior.h"
00015 #include "data.h"
00016 #include "linalg.h"
00017
00037 class PsiPsychometric {
00038 private:
00039 int Nalternatives;
00040 double guessingrate;
00041 bool gammaislambda;
00042 PsiCore * Core;
00043 PsiSigmoid * Sigmoid;
00044 std::vector<PsiPrior*> priors;
00045 protected:
00046 PsiPsychometric (
00047 int nAFC,
00048 PsiCore * core,
00049 PsiSigmoid * sigmoid,
00050 unsigned int nparameters
00051 );
00052 public:
00053 PsiPsychometric (
00054 int nAFC,
00055 PsiCore * core,
00056 PsiSigmoid * sigmoid
00057 );
00058 ~PsiPsychometric ( void );
00059 virtual double evaluate (
00060 double x,
00061 const std::vector<double>& prm
00062 ) const;
00063 virtual double negllikeli (
00064 const std::vector<double>& prm,
00065 const PsiData* data
00066 ) const;
00067 virtual double neglpost (
00068 const std::vector<double>& prm,
00069 const PsiData* data
00070 ) const;
00071 virtual double leastfavourable (
00072 const std::vector<double>& prm,
00073 const PsiData* data,
00074 double cut,
00075 bool threshold=true
00076 ) const;
00077 virtual double deviance (
00078 const std::vector<double>& prm,
00079 const PsiData* data
00080 ) const;
00081 virtual Matrix * ddnegllikeli (
00082 const std::vector<double>& prm,
00083 const PsiData* data
00084 ) const;
00085 virtual std::vector<double> dnegllikeli (
00086 const std::vector<double>& prm,
00087 const PsiData* data
00088 ) const;
00089 const PsiCore* getCore ( void ) const { return Core; }
00090 const PsiSigmoid* getSigmoid ( void ) const { return Sigmoid; }
00091 void setPrior ( unsigned int index, PsiPrior* prior ) throw(BadArgumentError);
00092 double evalPrior ( unsigned int index, double x ) const {return priors[index]->pdf(x);}
00093 virtual double randPrior ( unsigned int index ) const { return priors[index]->rand(); }
00094 const PsiPrior* getPrior ( unsigned int index ) const { return priors[index]; }
00095 int getNalternatives ( void ) const { return Nalternatives; }
00096 virtual unsigned int getNparams ( void ) const { return (Nalternatives==1 ? (gammaislambda ? 3 : 4 ) : 3 ); }
00097 virtual std::vector<double> getStart ( const PsiData* data ) const ;
00098 double getThres (
00099 const std::vector<double>& prm,
00100 double cut
00101 ) const { return Core->inv(Sigmoid->inv(cut),prm); }
00102 double getSlope (
00103 const std::vector<double>& prm,
00104 double x
00105 ) const { return Sigmoid->df ( Core->g ( x, prm ) ) * Core->dgx ( x, prm ); }
00106 std::vector<double> getDevianceResiduals (
00107 const std::vector<double>& prm,
00108 const PsiData* data
00109 ) const;
00110 double getRpd (
00111 const std::vector<double>& devianceresiduals,
00112 const std::vector<double>& prm,
00113 const PsiData* data
00114 ) const;
00115 double getRkd ( const std::vector<double>& devianceresiduals, const PsiData* data ) const;
00116 double dllikeli (
00117 std::vector<double> prm,
00118 const PsiData* data,
00119 unsigned int i
00120 ) const;
00121 double dlposteri (
00122 std::vector<double> prm,
00123 const PsiData* data,
00124 unsigned int i
00125 ) const;
00126 void setgammatolambda ( void ) { gammaislambda=true; };
00127 double getGuess ( const std::vector<double>& prm ) const { return (gammaislambda ? prm[2] : ( getNalternatives() < 2 ? prm[3] : 1./Nalternatives )); }
00128 double dpredict ( const std::vector<double>& prm, double x, unsigned int i ) const;
00129 double ddpredict ( const std::vector<double>& prm, double x, unsigned int i, unsigned int j ) const;
00130 };
00131
00139 class BetaPsychometric : public PsiPsychometric {
00140 private:
00141 double fznull ( unsigned int z, const PsiData* data, double nu ) const;
00142 double negllikelinull ( const PsiData* data, double nu ) const;
00143 public:
00144 BetaPsychometric ( int nAFC, PsiCore * core, PsiSigmoid * sigmoid ) : PsiPsychometric ( nAFC, core, sigmoid, ( nAFC<2 ? 5 : 4 ) ) {}
00145 double negllikeli (
00146 const std::vector<double>& prm,
00147 const PsiData* data
00148 ) const;
00149 std::vector<double> dnegllikeli (
00150 const std::vector<double>& prm,
00151 const PsiData* data
00152 ) const;
00153 Matrix * ddnegllikeli (
00154 const std::vector<double>& prm,
00155 const PsiData* data
00156 ) const;
00157 unsigned int getNparams ( void ) const { return PsiPsychometric::getNparams()+1; }
00158 double deviance (
00159 const std::vector<double>& prm,
00160 const PsiData * data
00161 ) const;
00162
00163 std::vector<double> getStart ( const PsiData* data ) const { std::vector<double> out (PsiPsychometric::getStart ( data )); out[out.size()-1] = .99999; return out;}
00164 };
00165
00181 class OutlierModel : public PsiPsychometric {
00182 private:
00183 unsigned int jout;
00184 double getp ( const std::vector<double>& prm ) const;
00185 public:
00186 OutlierModel (
00187 int nAFC,
00188 PsiCore * core,
00189 PsiSigmoid * sigmoid,
00190 unsigned int exclude
00191 ) : PsiPsychometric ( nAFC, core, sigmoid ), jout(exclude) {};
00192 void setexclude ( unsigned int exclude ) { jout = exclude; }
00193 double negllikeli (
00194 const std::vector<double>& prm,
00195 const PsiData * data
00196 ) const;
00197 double neglpost (
00198 const std::vector<double>& prm,
00199 const PsiData * data
00200 ) const;
00201 double deviance (
00202 const std::vector<double>& prm,
00203 const PsiData* data
00204 ) const;
00205 unsigned int getNparams ( void ) const { return PsiPsychometric::getNparams()+1; }
00206 double randPrior ( unsigned int index ) const { return ( index<PsiPsychometric::getNparams() ? PsiPsychometric::randPrior(index) : PsiRandom().rngcall() ); }
00207 };
00208
00209 #endif