File: optGammaMixtureLS.cpp

package info (click to toggle)
fastml 3.11-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,772 kB
  • sloc: cpp: 48,522; perl: 3,588; ansic: 819; makefile: 386; python: 83; sh: 55
file content (262 lines) | stat: -rw-r--r-- 9,640 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#include "optGammaMixtureLS.h"
#include "likelihoodComputation.h"
#include "numRec.h"
//#include "optimizer.h"
//#include "NRconjugateGradient.h"

#include <fstream>
#include <algorithm>
#include <ctime>
using namespace std;
using namespace likelihoodComputation;

optGammaMixtureLS::optGammaMixtureLS(stochasticProcess* pSp, const sequenceContainer& sc, const tree& inTree, MDOUBLE upperBoundAlpha/*=15.0*/, MDOUBLE upperBoundBeta/*=15.0*/,unObservableData* unObservableData_p)
{
	_pSc = &sc;
	_pTree = &inTree;
	_pSp = pSp; 
	_upperBoundAlpha = upperBoundAlpha;
	_upperBoundBeta = upperBoundBeta;
	_unObservableData_p = unObservableData_p;
}


optGammaMixtureLS::~optGammaMixtureLS()
{
}

MDOUBLE optGammaMixtureLS::optimizeParam(const int maxIterations, const MDOUBLE tol, const Vdouble * pWeights, optAlg optType)
{
	mixtureDistribution * pMixture = static_cast<mixtureDistribution*>(_pSp->distr());
	return optimizeParam(pMixture, maxIterations, tol, pWeights, optType);
}


MDOUBLE optGammaMixtureLS::optimizeParam(mixtureDistribution * pMixture, const int maxIterations, const MDOUBLE tol, const Vdouble * pWeights, optAlg optType)
{
	switch (optType) 
	{
	case ONE_DIM:
		return optimizeParamOneDim(pMixture, maxIterations, tol, pWeights);
		break;
	//case POWELL:
	//	return optimizeParamPowell(pMixture, maxIterations, tol, pWeights, pOutF);
	//	break;
	//case CONJUGATE_DERIVATIVES:
	//	return optimizeParamConjugateDeriv(pMixture, maxIterations, tol, pWeights, pOutF);
	//	break;
	default:
		errorMsg::reportError("unknown optimization algorithm in optGammaMixtureLS::optimizeParam()");
		return -1;
	}
}


//this function finds the best mixture param using a line search maximization. Each time only one parameter is optimized using the regular brent algorithm.
//CAN BE USED FOR 2 COMPONENTS ONLY (the maximization on components probabilities maximize only P1, the prob of the first component, while the prob of the second is set to 1-P1)
// ...Note: if more than 2 components, all the others are scaled by P1
//total there are 5 parameters to optimize: alpha1, beta1, alpha2, beta2, and P1
MDOUBLE optGammaMixtureLS::optimizeParamOneDim(mixtureDistribution * pMixture, const int maxIterations, const MDOUBLE tol, const Vdouble * pWeights)
{
	MDOUBLE lowerBound = 0.0;	
	
	MDOUBLE newL = VERYSMALL; //newL is the LL after a single param optimization.
	//MDOUBLE curL = VERYSMALL; //the current LL.
	MDOUBLE curL = likelihoodComputation::getTreeLikelihoodAllPosAlphTheSame(*_pTree,*_pSc,*_pSp,pWeights,_unObservableData_p); //the current LL.
	MDOUBLE prevIterL = VERYSMALL; //The LL of the previous iteration. the loop quit if the increase in LL between iterations is smaller than tol
	MDOUBLE bestA=0, bestB=0, bestW = 0;
			
	for (int it = 0; it < maxIterations; ++it)
	{
		//prevIterL = newL;
		prevIterL = curL;

		for (int comp = 0; comp < pMixture->getComponentsNum(); ++comp)
		{
			//optimize alpha 
			MDOUBLE oldAlpha = pMixture->getAlpha(comp);
			newL = -brent(lowerBound,oldAlpha, _upperBoundAlpha, C_evalAlphaMixture(*_pTree,*_pSc,_pSp,comp,pWeights,_unObservableData_p), tol, &bestA);
			if (newL < curL) 
			{
				//the Likelihood wend down
				pMixture->setAlpha(oldAlpha, comp);
				if(_unObservableData_p){
					_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
				}
				LOG(5, <<"likelihood went down in optGammaMixtureLS::optimizeParam()"<<endl<<"old L= "<<curL<<" newL = "<<newL<<endl);
			}
			else
			{
				pMixture->setAlpha(bestA, comp);
				if(_unObservableData_p){
					_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
				}
				curL = newL;
				LOG(7, <<"iteration: "<<it<<" Optimize alpha comp"<<comp<<" new Likelihood = "<<curL<<endl);
			}
		
			//optimize beta 
			MDOUBLE oldBeta = pMixture->getBeta(comp);
			newL = -brent(lowerBound,oldBeta,_upperBoundBeta, C_evalBetaMixture(*_pTree,*_pSc,_pSp,comp,pWeights,_unObservableData_p), tol, &bestB);
			if (newL < curL)
			{
				//the Likelihood wend down
				pMixture->setBeta(oldBeta, comp);
				if(_unObservableData_p){
					_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
				}
				LOG(5, <<"likelihood went down in optGammaMixtureLS::optimizeParam()"<<endl<<"old L= "<<curL<<" newL = "<<newL<<endl);
			}
			else
			{
				pMixture->setBeta(bestB, comp);
				if(_unObservableData_p){
					_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
				}
				curL = newL;
				LOG(7, <<"iteration: "<<it<<" Optimize beta comp"<<comp<<" new Likelihood = "<<curL<<endl);
			}
			//optimize components probability. 
            if (pMixture->getComponentsNum() == 1)
				continue;
		
			MDOUBLE upperBound = 0.0;
			MDOUBLE lowerBound = 1.0;
			MDOUBLE oldWeight = pMixture->getComponentWeight(comp);
			newL = -brent(lowerBound, oldWeight, upperBound, C_evalProbMixture(*_pTree,*_pSc, _pSp, comp, pWeights), tol, &bestW);
			if (newL < curL)
			{
				//the Likelihood wend down
				pMixture->setComponentWeight(oldWeight, comp);
				if(_unObservableData_p){
					_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
				}
				LOG(5, <<"likelihood went down in optGammaMixtureLS::optimizeParam()"<<endl<<"old L= "<<curL<<" newL = "<<newL<<endl);
			}
			else
			{
				pMixture->setComponentWeight(bestW, comp);
				if(_unObservableData_p){
					_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
				}
				curL = newL;
				LOG(7, <<"iteration: "<<it<<" Optimize Prob"<<" new Likelihood = "<<curL<<endl);
			}
		}
		pMixture->normalizeProbabilities();	// why again ???
		printIter(pMixture, it, curL);
		if (curL < prevIterL + tol){
			//if(_unObservableData_p){
			//	_unObservableData_p->setLforMissingData(*_pTree,_pSp);				
			//}
			return max(curL,prevIterL); // not to reduce likelihood
		}
	}
	return curL;
}



/*
//this function uses a line search maximization. The difference is that it does not use the naive method (optimize each parameter seperatly untill convergence)
//but uses Powel's quadratically convergent method (Numerical Recipes pp 420).
//CAN BE USED FOR 2 COMPONENTS ONLY (the maximization on components probabilities maximize only P1, the prob of the first component, while the prob of the second is set to 1-P1)
//total there are 5 parameters to optimize: alpha1, beta1, alpha2, beta2, and P1
MDOUBLE optGammaMixtureLS::optimizeParamPowell(mixtureDistribution* pMixture, const int maxIterations, const MDOUBLE tol, const Vdouble * pWeights, ofstream* pOutF)
{
	if (pMixture->getComponentsNum() == 1)
		return optimizeParam1CompPowel(pMixture, maxIterations, tol, pWeights, pOutF);
	else return optimizeParamManyCompPowel(pMixture, maxIterations, tol, pWeights, pOutF);
}


MDOUBLE optGammaMixtureLS::optimizeParam1CompPowel(mixtureDistribution * pMixture, const int maxIterations, const MDOUBLE tol, const Vdouble * pWeights, ofstream* pOutF)
{
	tree tree1(*_pTree);
	sequenceContainer sc1(*_pSc);

	C_evalGammaMixture optPowell(&tree1, &sc1, _pSp, NULL);
	optimizer<C_evalGammaMixture> opt(optPowell);
	Vdouble param(2);
	param[0] = pMixture->getAlpha(0);
	param[1] = pMixture->getBeta(0);

	MDOUBLE res = opt.findmin(param);
	return res;
}

MDOUBLE optGammaMixtureLS::optimizeParamManyCompPowel(mixtureDistribution * pMixture, const int maxIterations, const MDOUBLE tol, const Vdouble * pWeights, ofstream* pOutF)
{
	tree tree1(*_pTree);
	sequenceContainer sc1(*_pSc);

    Vdouble param(pMixture->getComponentsNum() * 3 - 1);
	int paramNum = 0;
	for (int comp = 0; comp < pMixture->getComponentsNum(); ++comp)
	{
        param[paramNum++] = pMixture->getAlpha(comp);
        param[paramNum++] = pMixture->getBeta(comp);
		param[paramNum++] = pMixture->getComponentWeight(comp);
	}
	C_evalGammaMixture optPowell(&tree1, &sc1, _pSp, NULL);
	optimizer<C_evalGammaMixture> opt(optPowell);
	MDOUBLE res = opt.findmin(param);
	cerr <<"optimized Powell result = "<< res<<endl;
	return res;
}
*/

/*
MDOUBLE optGammaMixtureLS::optimizeParamConjugateDeriv(
	mixtureDistribution * pMixture, const int maxIterations, 
	const MDOUBLE tol, const Vdouble * pWeights, ofstream* pOutF)
{
	tree tree1(*_pTree);
	sequenceContainer sc1(*_pSc);

    Vdouble param(pMixture->getComponentsNum() * 3);
	int paramNum = 0;
	int comp;
	for (comp = 0; comp < pMixture->getComponentsNum(); ++comp)
	{
        param[paramNum++] = pMixture->getAlpha(comp);
        param[paramNum++] = pMixture->getBeta(comp);
		param[paramNum++] = pMixture->getComponentWeight(comp);
	}
	C_evalGammaMixture func(&tree1, &sc1, _pSp, pWeights);
	NRconjugateGradient<C_evalGammaMixture> opt;
	if (pOutF != NULL)
	{
		*pOutF <<endl<<endl<<"starting NRconjugateGradient optimization..."<<endl;
		printIter(pMixture, 0, 0.0, pOutF);
	}

	MDOUBLE res = opt.findmin(param, &func, tol);

	paramNum = 0;
	for (comp = 0; comp < pMixture->getComponentsNum(); ++comp)
	{
		pMixture->setAlpha(param[paramNum++], comp);
		pMixture->setBeta(param[paramNum++], comp);			
		pMixture->setComponentWeight(param[paramNum++], comp);			
	}
	pMixture->normalizeProbabilities();
	if (pOutF != NULL)
	{
		*pOutF <<endl<<endl<<"after NRconjugateGradient optimization"<<endl;
		printIter(pMixture, 0, res, pOutF);
	}
	cerr <<"optimized Conjugate Deriv result = "<< res<<endl;
	return res;
}
*/


void optGammaMixtureLS::printIter(const mixtureDistribution * pMixture, const int it, const MDOUBLE curL)  
{
	LOG(4,<< "iter " << it <<": cur likelihood= " << curL <<endl);
	for (int k = 0; k < pMixture->getComponentsNum(); ++k)
	{
		LOG(4, << "comp="<<k<<" Alp/Beta= "<<pMixture->getAlpha(k)/pMixture->getBeta(k)<<" alpha= "<<pMixture->getAlpha(k) << " beta= " <<pMixture->getBeta(k)<<" Prob= "<<pMixture->getComponentProb(k)<<endl);  
	}
}