void srTGenTrjDat::CompTrjKickMatr(SRWLKickM* arKickM, int nKickM, double sStart, double sEnd, long ns, double* pInPrecPar, double* pOutBtX, double* pOutX, double* pOutBtY, double* pOutY, double* pOutBtZ, double* pOutZ) { if((arKickM == 0) || (nKickM <= 0)) throw SRWL_INCORRECT_PARAM_FOR_TRJ_COMP; if(ns <= 0) throw SRWL_INCORRECT_PARAM_FOR_TRJ_COMP; //sort arKickM to find groups of kick-matrices with non-overlapping longitudinal intervals vector<pair<int, pair<double, double> > > vKickStInd; SRWLKickM *t_arKickM = arKickM; for(int i=0; i<nKickM; i++) { double curHalfRange = 0.5*t_arKickM->rz; pair<double, double> curRange(t_arKickM->z - curHalfRange, t_arKickM->z + curHalfRange); pair<int, pair<double, double> > curPair(i, curRange); vKickStInd.push_back(curPair); } sort(vKickStInd.begin(), vKickStInd.end(), CAuxParse::LessInPairBasedOnFirstInNestedPair<int, double, double>); vector<vector<int> > vIndNonOverlapKickGroups; vector<pair<double, double> > vIndNonOverlapKickGroupRanges; vector<int> vIndKickM; vIndKickM.push_back(vKickStInd[0].first); double curGroupStart = vKickStInd[0].second.first; double curGroupEnd = vKickStInd[0].second.second; for(int j=1; j<nKickM; j++) { double newStart = vKickStInd[j].second.first; double newEnd = vKickStInd[j].second.second; if((newEnd <= curGroupStart) || (newStart >= curGroupEnd)) {//end current group vIndNonOverlapKickGroups.push_back(vIndKickM); pair<double, double> curRange(curGroupStart, curGroupEnd); vIndNonOverlapKickGroupRanges.push_back(curRange); vIndKickM.erase(vIndKickM.begin(), vIndKickM.end()); curGroupStart = newStart; curGroupEnd = newEnd; } else {//continue stuffing current group vIndKickM.push_back(vKickStInd[j].first); if(curGroupStart > newStart) curGroupStart = newStart; if(curGroupEnd < newEnd) curGroupEnd = newEnd; } } if(!vIndKickM.empty()) { vIndNonOverlapKickGroups.push_back(vIndKickM); pair<double, double> curRange(curGroupStart, curGroupEnd); vIndNonOverlapKickGroupRanges.push_back(curRange); vIndKickM.erase(vIndKickM.begin(), vIndKickM.end()); } //sorting completed bool trjShouldBeAdded = (pInPrecPar[0] == 1); const double sResEdgeToler = 1.E-12; double sAbsEdgeToler = (sEnd - sStart)*sResEdgeToler; bool integOnLeftIsNeeded = (sStart < -sAbsEdgeToler); bool integOnRightIsNeeded = (sEnd > sAbsEdgeToler); double sStep = (ns <= 1)? 0 : (sEnd - sStart)/(ns - 1); double initCond[] = {EbmDat.x0, EbmDat.dxds0, EbmDat.z0, EbmDat.dzds0, EbmDat.s0}; //? double inv_B_pho = EbmDat.Inv_B_rho(); //[1/(T*m)] double gamEm2 = EbmDat.GammaEm2, btx, bty; long is0 = 0; double s0Act = 0.; if(integOnLeftIsNeeded) { double *tOutBtX = pOutBtX, *tOutX = pOutX; double *tOutBtY = pOutBtY, *tOutY = pOutY; double *tOutBtZ = pOutBtZ, *tOutZ = pOutZ; if(sEnd < -sAbsEdgeToler) //i.e. < 0 {//need to "arrive" to sEnd without storing trajectory data; step can be re-adjusted long auxNp = (long)fabs(sEnd/sStep) + 1; if(auxNp <= 1) auxNp = 2; double *auxTrjRes = new double[(auxNp + ns)*5]; if(auxTrjRes == 0) throw MEMORY_ALLOCATION_FAILURE; IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, 0., sEnd, auxNp, auxTrjRes); //gmIntRK.solve(initCond, 0., sMax, auxNp, auxTrjRes); double *pResEnd = auxTrjRes + (auxNp - 1)*5; for(int i=0; i<5; i++) initCond[i] = pResEnd[i]; //arrived to sMax; now solve for the entire main trajectory: if(ns <= 1) { double *t_auxTrjRes = auxTrjRes; for(int i=0; i<5; i++) *(t_auxTrjRes++) = initCond[i]; } else IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, sEnd, sStart, ns, auxTrjRes); //else gmIntRK.solve(initCond, sMax, sMin, ns, auxTrjRes); double *t_auxTrjRes = auxTrjRes + (ns*5 - 1); for(int j=0; j<ns; j++) { if(trjShouldBeAdded) { //if(pOutZ) *(tOutZ++) += *t_auxTrjRes; //longitudinal position is not modified in this case t_auxTrjRes--; *tOutBtY += *(t_auxTrjRes--); bty = *(tOutBtY++); *(tOutY++) += *(t_auxTrjRes--); *tOutBtX += *(t_auxTrjRes--); btx = *(tOutBtX++); *(tOutX++) += *(t_auxTrjRes--); if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } else { if(pOutZ) *(tOutZ++) = *t_auxTrjRes; t_auxTrjRes--; bty = *(t_auxTrjRes--); *(tOutBtY++) = bty; *(tOutY++) = *(t_auxTrjRes--); btx = *(t_auxTrjRes--); *(tOutBtX++) = btx; *(tOutX++) = *(t_auxTrjRes--); if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } } delete[] auxTrjRes; } else { is0 = (int)fabs((-sStart + sAbsEdgeToler)/sStep); if(is0 >= ns) is0 = ns - 1; s0Act = sStart + is0*sStep; if(s0Act < -sAbsEdgeToler) {//one small step to s0Act double twoPtTrjRes[2*5]; IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, 0., s0Act, 2, twoPtTrjRes); //gmIntRK.solve(initCond, 0., s0Act, 2, twoPtTrjRes); double *pResEnd = twoPtTrjRes + 5; for(int i=0; i<5; i++) initCond[i] = pResEnd[i]; } //arrived to s0Act; now solve for the left part of the trajectory: int nsLeft = is0 + 1; double *auxTrjRes = new double[nsLeft*5]; if(auxTrjRes == 0) throw MEMORY_ALLOCATION_FAILURE; if(nsLeft <= 1) { double *t_auxTrjRes = auxTrjRes; //*(t_auxTrjRes++) = s0Act; for(int i=0; i<5; i++) *(t_auxTrjRes++) = initCond[i]; } else IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, s0Act, sStart, nsLeft, auxTrjRes); //else gmIntRK.solve(initCond, s0Act, sMin, nsLeft, auxTrjRes); double *t_auxTrjRes = auxTrjRes + nsLeft*5 - 1; for(int j=0; j<nsLeft; j++) { if(trjShouldBeAdded) { //if(pOutZ) *(tOutZ++) += *t_auxTrjRes; //longitudinal position is not modified in this case t_auxTrjRes--; *tOutBtY += *(t_auxTrjRes--); bty = *(tOutBtY++); *(tOutY++) += *(t_auxTrjRes--); *tOutBtX += *(t_auxTrjRes--); btx = *(tOutBtX++); *(tOutX++) += *(t_auxTrjRes--); if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } else { if(pOutZ) *(tOutZ++) = *t_auxTrjRes; t_auxTrjRes--; bty = *(t_auxTrjRes--); *(tOutBtY++) = bty; *(tOutY++) = *(t_auxTrjRes--); btx = *(t_auxTrjRes--); *(tOutBtX++) = btx; *(tOutX++) = *(t_auxTrjRes--); if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } } delete[] auxTrjRes; } } if(integOnRightIsNeeded) { double *tOutBtX = pOutBtX + is0, *tOutX = pOutX + is0; double *tOutBtY = pOutBtY + is0, *tOutY = pOutY + is0; double *tOutBtZ = pOutBtZ + is0, *tOutZ = pOutZ + is0; if(sStart > sAbsEdgeToler) {//need to "arrive" to sMin without storing trajectory data; step can be re-adjusted int auxNp = (int)fabs(sStart/sStep) + 1; if(auxNp <= 1) auxNp = 2; double *auxTrjRes = new double[(auxNp + ns)*5]; if(auxTrjRes == 0) throw MEMORY_ALLOCATION_FAILURE; IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, 0., sStart, auxNp, auxTrjRes); //gmIntRK.solve(initCond, 0., sMin, auxNp, auxTrjRes); double *pResEnd = auxTrjRes + (auxNp - 1)*5; for(int i=0; i<5; i++) initCond[i] = pResEnd[i]; //arrived to sMax; now solve for the entire main trajectory: if(ns <= 1) { double *t_auxTrjRes = auxTrjRes; //*(t_auxTrjRes++) = sMin; for(int i=0; i<5; i++) *(t_auxTrjRes++) = initCond[i]; } else IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, sStart, sEnd, ns, auxTrjRes); //else gmIntRK.solve(initCond, sMin, sMax, ns, auxTrjRes); double *t_auxTrjRes = auxTrjRes; for(int j=0; j<ns; j++) { if(trjShouldBeAdded) { *(tOutX++) += *(t_auxTrjRes++); *tOutBtX += *(t_auxTrjRes++); btx = *(tOutBtX++); *(tOutY++) += *(t_auxTrjRes++); *tOutBtY += *(t_auxTrjRes++); bty = *(tOutBtY++); //if(pOutZ) *(tOutZ++) += *t_auxTrjRes; //longitudinal position is not modified in this case t_auxTrjRes++; if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } else { *(tOutX++) = *(t_auxTrjRes++); btx = *(t_auxTrjRes++); *(tOutBtX++) = btx; *(tOutY++) = *(t_auxTrjRes++); bty = *(t_auxTrjRes++); *(tOutBtY++) = bty; if(pOutZ) *(tOutZ++) = *t_auxTrjRes; t_auxTrjRes++; if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } } delete[] auxTrjRes; } else { //normally, initial conditions should be already set here int nsRight = ns - is0; if(nsRight < 1) nsRight = 1; double *auxTrjRes = new double[nsRight*5]; if(auxTrjRes == 0) throw MEMORY_ALLOCATION_FAILURE; if(nsRight <= 1) { double *t_auxTrjRes = auxTrjRes; //*(t_auxTrjRes++) = s0Act; for(int i=0; i<5; i++) *(t_auxTrjRes++) = initCond[i]; } //s0Act has been defined above! else IntegrateKicks(arKickM, vIndNonOverlapKickGroups, vIndNonOverlapKickGroupRanges, inv_B_pho, initCond, s0Act, sEnd, nsRight, auxTrjRes); //else gmIntRK.solve(initCond, s0Act, sMax, nsRight, auxTrjRes); double *t_auxTrjRes = auxTrjRes; for(int j=0; j<nsRight; j++) { if(trjShouldBeAdded) { *(tOutX++) += *(t_auxTrjRes++); *tOutBtX += *(t_auxTrjRes++); btx = *(tOutBtX++); *(tOutY++) += *(t_auxTrjRes++); *tOutBtY += *(t_auxTrjRes++); bty = *(tOutBtY++); //if(pOutZ) *(tOutZ++) += *t_auxTrjRes; //longitudinal position is not modified in this case t_auxTrjRes++; if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } else { *(tOutX++) = *(t_auxTrjRes++); btx = *(t_auxTrjRes++); *(tOutBtX++) = btx; *(tOutY++) = *(t_auxTrjRes++); bty = *(t_auxTrjRes++); *(tOutBtY++) = bty; if(pOutZ) *(tOutZ++) = *t_auxTrjRes; t_auxTrjRes++; if(pOutBtZ) *(tOutBtZ++) = CGenMathMeth::radicalOnePlusSmall(-(gamEm2 + btx*btx + bty*bty)); } } delete[] auxTrjRes; } } }
lasp::svm_model lasp::get_model_from_solved_problems(vector<lasp::svm_problem> solvedProblems, vector<lasp::svm_sparse_data> holdoutData, vector<int> orderSeen) { svm_model returnModel; returnModel.orderSeen = orderSeen; //First, we need to fill up returnMode.idMap by assigning an id to each support vector //First, we will create a mapping from {class1 -> {class2 -> 1vs2}} //where we saw class1 before class2 and 1vs2 is an svm_problem that represents //the solution to pitting class1 against class2. map<int, map<int, svm_problem> > comparisonMapping; for(int i = 0; i < solvedProblems.size(); ++i) { int c1 = solvedProblems[i].classifications[0]; int c2 = solvedProblems[i].classifications[1]; //Enforce that the model contains all classes returnModel.modelData[c1]; returnModel.modelData[c2]; int c1ind = -1; int c2ind = -1; for(int j = 0; j < orderSeen.size(); ++j) { if(c1 == orderSeen[j]) c1ind = j; else if(c2 == orderSeen[j]) c2ind = j; } //swap to make sure we're indexing our map correctly if(c1ind > c2ind) { int temp = c1; c1 = c2; c2 = temp; } comparisonMapping[c1][c2] = solvedProblems[i]; } //Now that we have the mapping and the sorted list of classes we've seen, we can //begin to fill in the model. //This assumes that we have at least one solved problem //this is pretty ugly, there's definitely a better way to do this. returnModel.kernelType = solvedProblems[0].options.kernel; returnModel.numFeatures = solvedProblems[0].features; returnModel.degree = solvedProblems[0].options.degree; returnModel.coef = solvedProblems[0].options.coef; returnModel.gamma = solvedProblems[0].options.gamma; //(Yu) using the assumption before, this keeps the means and standard deviation of training data in the model returnModel.means = solvedProblems[0].means; returnModel.standardDeviations = solvedProblems[0].standardDeviations; //Here's the big data-copy loop. for(int i = 0; i < orderSeen.size(); ++i) { for(int j = i+1; j < orderSeen.size(); ++j) { int c1, c2; c1 = orderSeen[i]; c2 = orderSeen[j]; svm_problem currentProblem = comparisonMapping[c1][c2]; returnModel.offsets[c1][c2] = currentProblem.bs.back(); //Now, let's extract the support vectors from each class vector<vector<svm_node> > classOneSV; vector<vector<svm_node> > classTwoSV; vector<double> classOneBetas; vector<double> classTwoBetas; for(int k = 0; k < currentProblem.S.size(); ++k) { int curClassification = currentProblem.y[currentProblem.S[k]] == 1 ? currentProblem.classifications[0] : currentProblem.classifications[1]; vector<svm_node> currentSupportVector; //Note that svm_nodes are indexed from 1. for(int x = 0; x < currentProblem.features; ++x) { double value = currentProblem.xS[k*currentProblem.features+x]; if(fabs(value) > 1E-20) { svm_node newNode; newNode.index = x + 1; newNode.value = value; //cout << newNode.index << "," << newNode.value << endl; currentSupportVector.push_back(newNode); } } //we have reconstructed the sparse representation of a given support vector, //now we just need to put it into the correct list of support vectors if(curClassification == c1) { classOneSV.push_back(currentSupportVector); classOneBetas.push_back(currentProblem.betas.back()[k]); } else { //assume it's in class two. classTwoSV.push_back(currentSupportVector); classTwoBetas.push_back(currentProblem.betas.back()[k]); } } //we now have two vectors containing the sparse representations for each class //and two more vectors representing the corresponding beta values. //Now, we need to put the data into the svm_model's modelData. typedef map<vector<svm_node>, map<int, double>, CompareSparseVectors>::iterator MyIter; for(int k = 0; k < classOneSV.size(); ++k) { returnModel.modelData[c1][classOneSV[k]][c2] += classOneBetas[k]; } for(int k = 0; k < classTwoSV.size(); ++k) { returnModel.modelData[c2][classTwoSV[k]][c1] += classTwoBetas[k]; } //TODO: This should probably be referenced counted or something delete [] currentProblem.xS; currentProblem.xS = 0; } } returnModel.plattScale = (holdoutData.size() != 0); if(returnModel.plattScale) { //now, we train the sigmoid parameters. //First, lets create a mapping from {c1 -> {c2 -> holdout data}} //where we saw c1 before c2. map<int, map<int, svm_sparse_data> > holdoutMapping; for(int i = 0; i < holdoutData.size(); ++i) { vector<int> holdoutClasses; svm_sparse_data curHoldout = holdoutData[i]; for(map<int, vector<vector<svm_node> > >::iterator iter = curHoldout.allData.begin(); iter != curHoldout.allData.end(); ++iter) { holdoutClasses.push_back(iter->first); } if(holdoutClasses.size() != 2) cout << "holdout data had more/less than 2 classes." << endl; int c1 = holdoutClasses[0]; int c2 = holdoutClasses[1]; int c1ind = -1; int c2ind = -1; for(int j = 0; j < orderSeen.size(); ++j) { if(c1 == orderSeen[j]) c1ind = j; else if(c2 == orderSeen[j]) c2ind = j; } //swap to make sure we're indexing our map correctly if(c1ind > c2ind) { int temp = c1; c1 = c2; c2 = temp; } holdoutMapping[c1][c2] = curHoldout; } for(int i = 0; i < orderSeen.size(); ++i) { for(int j = i + 1; j < orderSeen.size(); ++j) { svm_sparse_data curHoldout = holdoutMapping[orderSeen[i]][orderSeen[j]]; pair<double, double> curPair(1.0, 1.0); //= get_optimal_sigmoid_parameters(curHoldout, returnModel); returnModel.plattScaleCoefs[orderSeen[i]][orderSeen[j]] = curPair; } } } //Assume all problems were trained the same way returnModel.pegasos = solvedProblems[0].options.pegasos && solvedProblems[0].options.usebias && solvedProblems[0].options.bias != 0; return returnModel; }