package wcet.dsvmfp.model.smo.classification;
import com.jopdesign.sys.Const;
import com.jopdesign.sys.Native;
import wcet.dsvmfp.model.smo.kernel.FP;
import wcet.dsvmfp.model.smo.kernel.KFP;
// Fixed point guide
// 1. comparison ok without FP
// 2. ==0 ok
// 3. postfix int vars with "_fp"
// 4. postfix method name with "FP" if it returns an int_fp
/**
* Class SMOBinaryClassifier, which is the model for performing a binary
* classification task. It will receive an input set to train it self. After
* training of the model it will retire the datapoints that are not part of the
* model. Only the support vectors are kept. The original index of the data
* points are kept. <br>
* Internal responsibilities: 1. Provide support for binary classification.<br>
* External responsibilities: 1. Provide the classification of the training
* points. 2. Provide the classification of test points.
*/
public class SMOBinaryClassifierFP{
final static boolean PRINT = false;
/** Number of lagrange multipliers in deployed RT model */
public final static int ALPHA_RT = 5;
static boolean info;
static public boolean printSMOInfo;
/** The F cache. */
static public int[] fcache_fp;
/** Kernel cache i==i kernels. */
static public int[] kernelCache_fp;
/**
* The index set. The value is an int that determines if the point belongs to
* index set. It is updated after each <code>takestep</code>. <br>
* 0: 0<a<C <br>
* 1: y_fp=+1,a=0 <br>
* 2: y_fp=-1,a=C <br>
* 3: y_fp=+1,a=C <br>
* 4: y_fp=-1,a=0
*/
static public int[] findexset;
/**
* A full length array that has holds the position of the point in findexset0.
* Only entries that ==0 in findexset are valid.
*/
static public int[] findexset0pos;
/**
* Index set 0: 0 <a <C. The length of the set is changed dynamically to match
* the number of NB points.
*/
static public int[] findexset0;
/**
* Length of findexset0.
*/
static public int findexset0Size;
/** The [m] Lagrange multipliers. */
static public int[] alpha_fp;
/** Sorted to have largest alpha index on [0] and so on.*/
static public int[] alpha_index_sorted;
/** The target vector of {-1,+1}. */
static public int[] y_fp;
/** The data vector [rows][columns]. */
static public int[][] data_fp;
/** The high bound. */
static public int c_fp;
/** The error tolerance. */
static public int tol_fp;
/** The error tolerance, that is used for KKT violation checks. */
static public int eps_fp;
/**
* Accuracy used when dividing the alpha_fp values into sets. For example: if
* (a <alphaTol_fp) then a = 0
*/
static public int alphaTol_fp;
/** Parameters used for keeping the indices of the low and high Fs. */
static public int b_up_fp;
static public int b_low_fp;
static public int i_low, i_up;
/** The bias_fp. */
static public int bias_fp;
static public int i1, i2;
/**
* The number of training points. It is declared final to avoid
* synchronization problems.
*/
public static int m;
/** The input space dimensinality. */
static public int n;
static public boolean takeStepFlag;
static public boolean takeStepResult;
// ////////////Performance Variables////////////////////
static public int takeStepCount;
static public int numChanged;
static public boolean examineAll;
static public int loop;
/**
* Method mainRoutine, which estimates the SVM parameters. The parameters are
* intialized before the training of the SVM is conducted.
*
* @return true if the trainng went well
*/
static public boolean mainRoutine() {
int time = 0;
if (PRINT) System.out.println("SMO.mainroutine");
time = Native.rd(Const.IO_US_CNT);
//for(int i=0;i<1000000;i++);
info = false;
// FP.init();
// The number of updated that significantly changed the
// Lagrange multipliers
numChanged = 0;
// Indicates if all examples has been tested
examineAll = true;
// Reset alpha_fp array , errorarray , b, and C
takeStepCount = 0;
initParams();
// System.out.println("main:bef manual call");
// printSMOInfo = true;
// while(printSMOInfo)
// smo.waitForNextPeriod();
// i1 = 0;
// i2 = 1;
// takeStep();
// System.out.println("main:aft manual call");
// while(printSMOInfo)
// smo.waitForNextPeriod();
// while(i1>-10); //foreverloop
loop = 0;
while (numChanged > 0 || examineAll) { // @WCA loop=2
// while (loop>=0) { //temp debug forever loop
// System.out.print("Starting loop=");
// System.out.println(loop);
loop++;
// System.out.print("numChanged=");
// System.out.println(numChanged);
// if (examineAll)
// System.out.println("examineAll=true");
// else
// System.out.println("examineAll=false");
for (int i = 0; i < 100000; i++) // @WCA loop=2
; // slow it down to print
numChanged = 0;
if (examineAll) {
for (i2 = 0; i2 < m; i2++) { // @WCA loop=2
if (examineExample()) {
numChanged++;
}
}
} else {
// Inner loop success
numChanged = innerLoop();
//numChanged = 0; // TODO: remove
}
if (examineAll) {
examineAll = false;
} else if (numChanged == 0) {
examineAll = true;
}
//break;
}
if (PRINT) System.out.println("SMO.mainroutine.trained");
sortAlphaIndex();
time = Native.rd(Const.IO_US_CNT)-time;
if (PRINT) {
System.out.println("Done!");
smoInfo();
System.out.print("total time:");
System.out.println(time);
}
return true;
}
// METHODS////////////////////////////////////////
/**
* Method examineExample, which will take a step using a number of heuristics.
* The points coming into this method is from the outer in the SMO main
* routine: first choice heuristic
*
* @param i2 -
* zero based index of second point to classify, which is chosen by
* the outer loop in smo
* @return true if it was possible to take a step
*/
static boolean examineExample() {
i1 = -1;
// Target
// double y2_fp;
// Lagrange multiplier
// double alph2_fp;
// Index of first point
// Functional output
// double f2_fp;
// Assignment to local variables
int f2_fp;
{
// System.out.println("eaa");
f2_fp = getfFP(i2);
// System.out.println("ea1");
fcache_fp[i2] = f2_fp;
// System.out.println("ea2");
// Update (b_low_fp, i_low), (b_up_fp, i_up) using (F2,i2)
if ((findexset[i2] == 1 || findexset[i2] == 2) && (f2_fp < b_up_fp)) {
b_up_fp = f2_fp;
i_up = i2;
} else if ((findexset[i2] == 3 || findexset[i2] == 4)
&& (f2_fp > b_low_fp)) {
b_low_fp = f2_fp;
i_low = i2;
}
}
// System.out.println("eb");
// Check optimality using current blow and bup and, if violated,
// find and index i1 to do joint optimization with i2
boolean optimality = true;
if (findexset[i2] == 0 || findexset[i2] == 1 || findexset[i2] == 2) {
if (FP.sub(b_low_fp, f2_fp) > FP.mul(FP.intToFp(2), tol_fp)) {
optimality = false;
i1 = i_low;
}
}
if (findexset[i2] == 0 || findexset[i2] == 3 || findexset[i2] == 4) {
if (FP.sub(f2_fp, b_up_fp) > FP.mul(FP.intToFp(2), tol_fp)) {
optimality = false;
i1 = i_up;
}
}
if (optimality) {
return false;
}
// For i2 choose the better i1...
if (findexset[i2] == 0) {
if (FP.sub(b_low_fp, f2_fp) > FP.sub(f2_fp, b_up_fp)) {
i1 = i_low;
} else {
i1 = i_up;
}
}
takeStep();
return takeStepResult;
}
/**
* Method takeStep, which optimizes two lagrange multipliers at a time. The
* method uses DsvmUtilFP.epsEqual to determine if there was positive
* progress.
*
* @param i1 -
* second choice heuristics
* @param i2 -
* first choice heuristics
* @return true if a positive step has occured
*/
public static boolean takeStep() {
if (i1 == i2) {
takeStepResult = false;
takeStepFlag = false;
return false;
}
int alph1_fp = alpha_fp[i1];
int alph2_fp = alpha_fp[i2];
int f1_fp = getfFP(i1);
// System.out.println("ts here3a");
int f2_fp = getfFP(i2);
// System.out.println("ts here4");
int s_fp = FP.mul(y_fp[i1], y_fp[i2]);
// System.out.println("ts here5");
int eta_fp = getEtaFP(i1, i2);
// System.out.println("ts here5");
int l_fp = getLowerClipFP(i1, i2);
// System.out.println("ts here6");
int h_fp = getUpperClipFP(i1, i2); // TODO: It returned 6 (393216_fp)
// System.out.println("ts here7");
// on
int a2_fp, a1_fp;
// inner loop with 1,2,3 example
if (eta_fp < 0) {
// a2 = alph2 - y2 * (f1 - f2) / eta;
a2_fp = FP.sub(alph2_fp, FP.mul(y_fp[i2], FP.div(FP.sub(f1_fp, f2_fp),
eta_fp))); // TODO: This one is wrong on first inner loop.
// a2 evaluates to zero
if (a2_fp < l_fp) {
a2_fp = l_fp;
} else if (a2_fp > h_fp) {
a2_fp = h_fp;
}
} else {
// TODO: Check how often this is called and tune
// getObjectivefunction
// if needed
int tempAlpha2_fp = alpha_fp[i2];
alpha_fp[i2] = l_fp;
int lObj_fp = getObjectiveFunctionFP();
alpha_fp[i2] = h_fp;
int hObj_fp = getObjectiveFunctionFP();
alpha_fp[i2] = tempAlpha2_fp;
if (lObj_fp > FP.add(hObj_fp, eps_fp)) {
a2_fp = l_fp;
} else if (lObj_fp < FP.sub(hObj_fp, eps_fp)) {
a2_fp = h_fp;
} else {
a2_fp = alph2_fp;
}
} // Return false if no significant optimization has taken place
if (FP.abs(FP.sub(a2_fp, alph2_fp)) < FP.mul(eps_fp, FP.add(a2_fp, FP.add(
alph2_fp, eps_fp)))) {
takeStepResult = false;
takeStepFlag = false;
return false;
}
// System.out.println("ts:y");
a1_fp = FP.add(alph1_fp, FP.mul(s_fp, FP.sub(alph2_fp, a2_fp)));
if (a1_fp < alphaTol_fp) {
a1_fp = 0;
}
if (a2_fp < alphaTol_fp) {
a2_fp = 0;
}
if (a1_fp > FP.add(c_fp, alphaTol_fp)) {
System.out.println("a1_fp too large");// a1_fp = c_fp; //
// TODO: Can this be
// removed
}
if (a2_fp > FP.add(c_fp, alphaTol_fp)) {
System.out.println("a2_fp too large");// a2_fp = c_fp; //
// TODO: Can this be
// removed
}
// System.out.println("ts:update fcache");
// Update fcache_fp for i in I_0 using new Lagrange multipliers
int fcache_fp_tmpi1 = 0;
int fcache_fp_tmpi2 = 0;
int fcache_fp_tmp_sum = 0;
for (int i = 0; i < findexset0Size; i++) { // @WCA loop=2
fcache_fp_tmpi1 = FP.mul(y_fp[i1], FP.mul(FP.sub(a1_fp, alph1_fp),
getKernelOutputFP(i1, findexset0[i], true)));
fcache_fp_tmpi2 = FP.mul(y_fp[i2], FP.mul(FP.sub(a2_fp, alph2_fp),
getKernelOutputFP(i2, findexset0[i], true)));
fcache_fp_tmp_sum = FP.add(fcache_fp_tmpi1, fcache_fp_tmpi2);
fcache_fp[findexset0[i]] = FP.add(fcache_fp[findexset0[i]],
fcache_fp_tmp_sum);
}
// Update the alphas //TODO: Check if FP 516 is too low
alpha_fp[i1] = a1_fp;
alpha_fp[i2] = a2_fp;
// and F1 if not covered by I_0 //TODO:Check this for first run
if (findexset[i1] != 0) {
fcache_fp_tmpi1 = FP.mul(FP.mul(y_fp[i1], FP.sub(a1_fp, alph1_fp)),
getKernelOutputFP(i1, i1, true));
fcache_fp_tmpi2 = FP.mul(FP.mul(y_fp[i2], FP.sub(a2_fp, alph2_fp)),
getKernelOutputFP(i1, i2, true));
fcache_fp_tmp_sum = FP.add(fcache_fp_tmpi1, fcache_fp_tmpi2);
fcache_fp[i1] = FP.add(f1_fp, fcache_fp_tmp_sum);
}
// and F2 if not covered by I_0
if (findexset[i2] != 0) {
fcache_fp_tmpi1 = FP.mul(FP.mul(y_fp[i1], FP.sub(a1_fp, alph1_fp)),
getKernelOutputFP(i1, i2, true));
fcache_fp_tmpi2 = FP.mul(FP.mul(y_fp[i2], FP.sub(a2_fp, alph2_fp)),
getKernelOutputFP(i2, i2, true));
fcache_fp_tmp_sum = FP.add(fcache_fp_tmpi1, fcache_fp_tmpi2);
fcache_fp[i2] = FP.add(f2_fp, fcache_fp_tmp_sum);
}
// System.out.println("tsII start");
updatefindex(i1);
updatefindex(i2);
updateiandbpartially();
bias_fp = FP.div(FP.add(b_low_fp, b_up_fp), FP.TWO);
takeStepCount++;
takeStepResult = true;
takeStepFlag = false;
return true;
}
static int changed;
static boolean inner_loop_success;
/**
* Method innerLoop, which is the inner loop that iterates until the examples
* in the inner loop are self consistent.
*
* @return the number of changed examples
*/
static int innerLoop() {
changed = 0;
inner_loop_success = true;
do {
i1 = i_up;
i2 = i_low;
takeStep();
takeStepFlag = true;
inner_loop_success = takeStepResult;
if (inner_loop_success) {
changed++;
}
if (!inner_loop_success) {
break;
}
if (b_up_fp > FP.sub(b_low_fp, FP.mul(FP.TWO, tol_fp))) {
break;
}
if ((i1 == i_up && i2 == i_low) || (i1 == i_low && i2 == i_up)) // avoid
// deadlock
break;
} while (true);
return changed;
}
/**
* Method initParams, which will init the parameters of the SMO algorithm.
* This method should only be called once, which would be just before the
* mainRoutine().
*/
static void initParams() {
takeStepFlag = false;
m = y_fp.length;
n = data_fp[0].length;
alpha_fp = new int[m];
alpha_index_sorted = new int[m];
findexset = new int[m];
findexset0 = new int[m];
findexset0Size = 0;
findexset0pos = new int[m];
// System.out.println("A initParams()");
c_fp = FP.mul(FP.ONE, FP.intToFp(1));
// System.out.println("Bd initParams()");
bias_fp = FP.intToFp(0);
// System.out.println("Ca initParams()");
eps_fp = FP.div(FP.ONE, FP.intToFp(100));
// System.out.println("Cb initParams()");
tol_fp = FP.div(FP.ONE, FP.intToFp(10));
// System.out.println("Cc initParams()");
alphaTol_fp = FP.div(FP.ONE, FP.intToFp(100));
KFP.setSigma2(FP.mul(FP.ONE, FP.ONE));
KFP.setKernelType(KFP.DOTKERNEL);// GAUSSIANKERNEL or DOTKERNEL
// Kernel type must be set first
KFP.setData(data_fp);
for (int i = 0; i < m; i++) {
findexset0pos[i] = -1;
findexset0[i] = -1;
findexset[i] = calculatefindex(i);
alpha_index_sorted[i] = i;
}
fcache_fp = new int[m];
// Kernel cache init
kernelCache_fp = new int[m];
for (int i = 0; i < m; i++) {
kernelCache_fp[i] = getKernelOutputFP(i, i, false);
}
b_up_fp = FP.intToFp(-1);
b_low_fp = FP.intToFp(1);
for (int i = 0; i < m; i++) {
if (y_fp[i] == FP.ONE) {// Classs 1
i_up = i;
fcache_fp[i] = FP.intToFp(-1);
} else if (y_fp[i] == -FP.ONE) // Class 2
{
i_low = i;
fcache_fp[i] = FP.intToFp(1);
}
}
// System.out.println("D initParams()");
// 1 / 100000000;
int loopStartInit = 1;
// System.out.println("E initParams()");
// constants
// logFile = null;
}
/**
* Method calculatefindex, which return which set the point belongs to based
* on the alpha_fp value and the target.
*
* @param alpha_array -
* the alpha_fp value
* @return target - the target value
*/
static int calculatefindex(int i) {
int retVal = -1;
if (alpha_fp[i] > alphaTol_fp) {
if (alpha_fp[i] < FP.sub(c_fp, alphaTol_fp)) {
retVal = 0;
} else if (y_fp[i] == FP.ONE) {
retVal = 3;
} else {
retVal = 2;
}
} else if (y_fp[i] == FP.ONE) {
retVal = 1;
} else {
retVal = 4;
}
if (retVal == -1) {
System.out.println("calculatefindex not working!");
System.exit(1);
}
return retVal;
}
/**
* Method updatefindex, which is a cache maintainer that updates findexset,
* findexset0, findexset0pos.
*
* @param i -
* the point
*/
static void updatefindex(int i) {
int index = calculatefindex(i);
// Only do the work if the index has changed
if (index != findexset[i]) {
// The point entered I_0
if (index == 0) {
// Updated index code based on a stack principle based on idea
// from Group A, DDM Class, 2005
findexset0[findexset0Size] = i;
findexset0pos[i] = findexset0Size;
findexset0Size++;
/*
* // Create the new array with new element in the end int[]
* newfindexset0 = new int[findexset0.length + 1]; // Assign the i'th
* element to the new position newfindexset0[findexset0.length] = i; //
* Update the position array findexset0pos[i] = findexset0.length; //
* Copy the old array into the new System.arraycopy(findexset0, 0,
* newfindexset0, 0, findexset0.length); findexset0 = null; findexset0 =
* newfindexset0;
*/
}
// The point has left I_0
if (findexset[i] == 0) {
if (findexset0pos[i] != findexset0Size - 1) {
findexset0[findexset0pos[i]] = findexset0[findexset0Size - 1];
findexset0pos[findexset0[findexset0Size - 1]] = findexset0pos[i];
}
findexset0Size--;
}
// Update findexset
findexset[i] = index;
}
}
/**
* Method getf, which calculates and returns the functional output without
* using a bias_fp. see keerti99
*
* @param i -
* index
* @return the non-biased functional output.
*/
static int getfFP(int i) {
// First check if i is in I_0 or i_low or i_up
// System.out.println("g:"); // +(cnt++));
if (findexset[i] == 0 || i == i_low || i == i_up) {
return fcache_fp[i];
} else {
// Calculate f using I_0
int f_fp = 0;
int f_fp_tmp = 0;
for (int j = 0; j < m; j++) {
f_fp_tmp = FP.mul(y_fp[j], alpha_fp[j]);
f_fp_tmp = FP.mul(f_fp_tmp, getKernelOutputFP(i, j, true));
f_fp = FP.add(f_fp, f_fp_tmp);
}
f_fp = FP.sub(f_fp, y_fp[i]);
return f_fp;
}
}
/**
* Method updateI0cache, which will update the fcache_fp. It is needed when
* the the kernel has been changed. A little trick is used to get the getf
* method to update the fcache_fp.
*/
static void updatefCache() {
for (int i = 0; i < findexset0Size; i++) {
// This will make getf to recalculate
findexset[findexset0[i]] = -1;
fcache_fp[findexset0[i]] = getfFP(findexset0[i]);
findexset[findexset0[i]] = 0;
}
// Now check if i_low is not in I0 and update if not
if (findexset[i_low] != 0) {
fcache_fp[i_low] = getfFP(i_low);
}
// Now check if i_low is not in I0 and update if not
if (findexset[i_up] != 0) {
fcache_fp[i_up] = getfFP(i_up);
}
}
/**
* Method updateI0indices, which will update the findexset arrray.
*/
static void updatesetindices() {
for (int i = 0; i < m; i++) {
updatefindex(i);
}
}
/**
* Method updateiandbfully, which will update b_low_fp, b_up_fp, i_low, i_up.
* The update is a partial one using only the point previously in I0 or i_low
* i_up itself. The method loops over all examples.
*/
static void updateiandbfully() {
// Compute i_low, b_low_fp and i_up, b_up_fp
// System.out.println("updatefully A");
// printScalar("b_low_fp",b_low_fp);
b_low_fp = FP.intToFp(-10000);
// b_low_fp = FP.MIN;
b_up_fp = FP.intToFp(10000);// FP.MAX;
i_low = -1;
i_up = -1;
for (int i = 0; i < m; i++) {
// I0
if (findexset[i] == 0) {
if (y_fp[i] == FP.ONE) {
if (b_up_fp >= fcache_fp[i]) {
b_up_fp = fcache_fp[i];
i_up = i;
}
} else {// y_fp == -1
if (b_low_fp < fcache_fp[i]) {
b_low_fp = fcache_fp[i];
i_low = i;
}
}
} else if (findexset[i] == 1 || findexset[i] == 2) {
if (b_up_fp > fcache_fp[i]) {
b_up_fp = fcache_fp[i];
i_up = i;
}
} else if (findexset[i] == 3 || findexset[i] == 4) {
if (b_low_fp < fcache_fp[i]) {
b_low_fp = fcache_fp[i];
i_low = i;
}
}
}
if (i_low == -1 || i_up == -1) {
System.out
.println("updateiandbfully() problem: i_low or i_up is not set");
System.exit(-1);
}
if (i_low == i_up) {
System.out
.println("updateiandbfully() problem: i_low or i_up is the same point");
System.exit(-1);
}
// System.out.println("exit updatefully");
}
/**
* Method updateiandb, which will update b_low_fp, b_up_fp, i_low, i_up. The
* update is a partial one using only the point previously in I0 or i_low i_up
* itself. b_low is max(I0,I3,I4)<br>
* b_max is min(I0,I1,I2)
*/
static void updateiandbpartially() {
// Compute i_low, b_low_fp and i_up, b_up_fp
b_low_fp = FP.intToFp(-10000);// FP.MIN;
b_up_fp = FP.intToFp(10000);// FP.MAX;
i_low = -1;
i_up = -1;// TODO: check below
for (int i = 0; i < findexset0Size; i++) {
if (fcache_fp[findexset0[i]] >= b_low_fp) {
b_low_fp = fcache_fp[findexset0[i]];
i_low = findexset0[i];
}
if (fcache_fp[findexset0[i]] < b_up_fp) {
b_up_fp = fcache_fp[findexset0[i]];
i_up = findexset0[i];
}
}
// Now check i1 if not in I_0
if (findexset[i1] != 0) {
if (findexset[i1] == 1 || findexset[i1] == 2) { // I_1 or I_2
if (b_up_fp > fcache_fp[i1] || findexset0Size == 1) { // TODO:
b_up_fp = fcache_fp[i1];
i_up = i1;
}
} else { // I_3 or I_4
if (b_low_fp < fcache_fp[i1] || findexset0Size == 1) {
b_low_fp = fcache_fp[i1];
i_low = i1;
}
}
}
// Now check i2 if not in I_0
if (findexset[i2] != 0) {
if (findexset[i2] == 1 || findexset[i2] == 2) {
if (b_up_fp > fcache_fp[i2] || findexset0Size == 1) {
b_up_fp = fcache_fp[i2];
i_up = i2;
}
} else { // I_3 or I_4
if (b_low_fp < fcache_fp[i2] || findexset0Size == 1) {
b_low_fp = fcache_fp[i2];
i_low = i2;
}
}
}
if (i_low == -1 || i_up == -1) {
System.out
.println("updateiandbpartially() problem: i_low or i_up is not set");
System.out.println("findexset0Size:"+findexset0Size);
System.out.println("i1:"+i1);
System.out.println("i2:"+i2);
System.out.println("i_low:"+i_low);
System.out.println("i_up:"+i_up);
System.out.println("findexset[i1]:"+findexset[i1]);
System.out.println("findexset[i2]:"+findexset[i2]);
for (int i = 0; i < findexset0Size; i++) {
System.out.print("fcache_fp[findexset0[");
System.out.print(i);
System.out.print("]]:");
System.out.print(fcache_fp[findexset0[i]]);
System.out.print(" ");
System.out.println(FP.fpToInt(fcache_fp[findexset0[i]]));
}
System.exit(-1);
}
if (i_low == i_up) {
System.out
.println("updateiandbpartially() problem: i_low or i_up is the same point");
System.exit(-1);
}
}
/**
* Method to check if the example violates the KKT conditions. The method
* assumes that the constrained Lagrange multipliers has been explicitly set
* to the the appropriate boundary value zero or C. This equation relates to
* equation 12.2 in Platts paper.
*
* @param p
* the example to check
* @return true if example violates KKT
*/
static boolean isKktViolated(int p) {
boolean violation = true;
int f_fp = getFunctionOutputFP(p);
// Is alpha_fp on lower bound?
if (alpha_fp[p] == 0) {
if (FP.mul(y_fp[p], f_fp) >= FP.sub(1, eps_fp)) {
violation = false;
}
} // or is alpha_fp in non-bound, NB, set?
else if (alpha_fp[p] > 0 && alpha_fp[p] < c_fp) {
if (FP.mul(y_fp[p], f_fp) > FP.sub(1, eps_fp)
&& FP.mul(y_fp[p], f_fp) < FP.add(1, eps_fp)) {
violation = false;
}
} // alpha_fp is on upper bound
else {
if (FP.mul(y_fp[p], f_fp) <= FP.add(1, eps_fp)) {
violation = false;
}
}
return violation;
}
/**
* Method getObjectiveFunction, which calculates and returns the value of the
* objective function based on the values in the alpha_fp array.
*
* @return the objective function (6.1 in Christianini).
*/
static int getObjectiveFunctionFP() {
// TODO: Check how often this is called and tune if possible
int objfunc_fp = 0;
for (int i = 0; i < m; i++) {
// Don't do the calculation for zero alphas
if (alpha_fp[i] > 0) {
objfunc_fp = FP.add(objfunc_fp, alpha_fp[i]);
for (int j = 0; j < m; j++) {
if (alpha_fp[j] > 0) {
objfunc_fp = FP.sub(objfunc_fp, FP.mul(FP.mul(FP.mul(FP.mul(FP.mul(
FP.HALF, y_fp[i]), y_fp[j]), alpha_fp[i]), alpha_fp[j]),
getKernelOutputFP(i, j, true)));
}
}
}
}
return objfunc_fp;
}
/**
* Method calculatedError, which calculates the error from from scratch.
*
* @param p -
* point to calculte error for
* @return calculated error
*/
static int getCalculatedErrorFP(int p) {
return FP.sub(getFunctionOutputFP(p), y_fp[p]);
}
/**
* Method getFunctionOutput, which will return the functional output for point
* p.
*
* @param p -
* the point index
* @return the functinal output
*/
static int getFunctionOutputFP(int p) {
int functionalOutput_fp = 0;
int kernelOutput_fp = 0;
for (int i = 0; i < m; i++) {
// Don't do the kernel if it is epsequal
if (alpha_fp[i] > 0) {
kernelOutput_fp = getKernelOutputFP(i, p, true);
functionalOutput_fp = FP.add(functionalOutput_fp, FP.mul(FP.mul(
alpha_fp[i], y_fp[i]), kernelOutput_fp));
}
} // Make a check here to see any alphas has been modified after
functionalOutput_fp = FP.sub(functionalOutput_fp, bias_fp);
return functionalOutput_fp;
}
/**
* Method getKernelOutput, which returns the kernel of two points.
*
* @param i1 -
* index of alpha_fp 1
* @param i2 -
* index of alpha_fp 2
* @param useCache
* TODO
* @param useCache -
* will use the cache if possible
* @return kernel output
*/
static int getKernelOutputFP(int i1, int i2, boolean useCache) {
if (i1 == i2 && useCache) {
return kernelCache_fp[i1];
}
return KFP.kernel(i1, i2);
}
/**
* Method getEta, which returns eta_fp = 2*k12-k11-k22
*
* @param i1 -
* index of first point
* @param i2
* -index of second point
* @return double - eta_fp
*/
static int getEtaFP(int i1, int i2) {
int eta_fp;
int eta_fp_tmp;
int kernel11_fp, kernel22_fp, kernel12_fp;
kernel11_fp = getKernelOutputFP(i1, i1, true);
kernel22_fp = getKernelOutputFP(i2, i2, true);
kernel12_fp = getKernelOutputFP(i1, i2, true);
eta_fp = FP.sub(FP.sub(FP.mul(FP.TWO, kernel12_fp), kernel11_fp),
kernel22_fp);
return eta_fp;
}
/**
* Method getLowerClip, which returns the lower clip value for some pair of
* Lagrange multipliers. Pls. refer to Nello's book for more info.
*
* @param i1 -
* first point
* @param i2 -
* second point
* @return the lower clip value
*/
static int getLowerClipFP(int i1, int i2) {
int u_fp = 0;
if (y_fp[i1] == y_fp[i2]) {
u_fp = FP.sub(FP.add(alpha_fp[i1], alpha_fp[i2]), c_fp);
if (u_fp < 0) {
u_fp = 0;
}
} else {
u_fp = FP.sub(alpha_fp[i2], alpha_fp[i1]);
if (u_fp < 0) {
u_fp = 0;
}
}
return u_fp;
}
/**
* Method getUpperClip, which will return the upper clip based on two Lagrange
* multipliers.
*
* @param i1 -
* first point
* @param i2 -
* second point
* @return the upper clip
*/
static int getUpperClipFP(int i1, int i2) {
int v_fp = 0;
if (y_fp[i1] == y_fp[i2]) {
v_fp = FP.add(alpha_fp[i1], alpha_fp[i2]);
if (v_fp > c_fp) {
v_fp = c_fp;
}
} else {
v_fp = FP.add(c_fp, FP.sub(alpha_fp[i2], alpha_fp[i1]));
if (v_fp > c_fp) {
v_fp = c_fp;
}
}
return v_fp;
}
static public int getTrainingErrorCountFP() {
int errorCount = 0;
for (int i = 0; i < m; i++) {
int fout_fp = getFunctionOutputFP(i);
if (fout_fp > 0 && y_fp[i] < 0) {
errorCount++;
} else if (fout_fp < 0 && y_fp[i] > 0) {
errorCount++;
}
}
return errorCount;
}
/**
* Method calculateW, which calculates the weight vector. This is used for
* linear SVMs.
*
* @return the weight [n] vector
*/
static int[] calculateWFP() {
int[] w_fp;
w_fp = new int[n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
w_fp[j] = FP.add(w_fp[j], FP.mul(FP.mul(y_fp[i], alpha_fp[i]),
data_fp[i][j]));
}
}
return w_fp;
}
/**
* Method isExampleBound, which will return true if the point p is on the
* bound as defined as less then (0+tol_fp) or greater than (C-tol_fp).
*
* @param p -
* index of point
* @return true if p is on bound
*/
static boolean isExampleOnBound(int p) {
return alpha_fp[p] < tol_fp || alpha_fp[p] > FP.sub(c_fp, tol_fp);
}
/**
* Method getFunctionOutput, which will return the functional output for point
* represented by a input vector only.
*
* @param xtest -
* the input vector
* @return the functinal output
*/
static public int getFunctionOutputTestPointFP(int[] xtest) {
int functionalOutput_fp = 0;
int[][] data_fp_local = data_fp;
int m = data_fp_local.length;
int func_out = 0;
//System.out.println("---ALIVE1m---" + m);
int n = xtest.length;
int n2 = data_fp_local[0].length;
for (int i = 0; i < ALPHA_RT; i++) { // @WCA loop=5
n = xtest.length;
while (n != 0) { // @WCA loop=2
n = n - 1;
func_out += (data_fp_local[alpha_index_sorted[i]][n] >> 8) * (xtest[n] >> 8);
}
if (alpha_fp[alpha_index_sorted[i]] > 0) {
functionalOutput_fp += func_out;
}
func_out = 0;
}
functionalOutput_fp -= bias_fp;
return functionalOutput_fp;
}
/**
* Method getFunctionOutput, which will return the functional output for point
* represented by a input vector only.
*
* @param xtest -
* the input vector
* @return the functinal output
*/
static public int getFunctionOutputTestPointFP_OOAD(int[] xtest) {
int functionalOutput_fp = 0;
int kernelOutput_fp = 0;
KFP.setX(xtest);
for (int i = 0; i < m; i++) {
// Don't do the kernel if it is epsequal
if (alpha_fp[i] > 0) {
kernelOutput_fp = KFP.kernelX(i);
functionalOutput_fp = FP.add(functionalOutput_fp, FP.mul(FP.mul(
alpha_fp[i], y_fp[i]), kernelOutput_fp));
}
} // Make a check here to see any alphas has been modified after
functionalOutput_fp = FP.sub(functionalOutput_fp, bias_fp);
return functionalOutput_fp;
}
static public void setData_fp(int[][] data_fp) {
SMOBinaryClassifierFP.data_fp = data_fp;
}
static public void setY_fp(int[] y_fp) {
SMOBinaryClassifierFP.y_fp = y_fp;
}
static void gccheck() {
System.out.print("GC free words ");
// System.out.println(GC.free());
}
static void sp() {
System.out.print("sp=");
System.out.println(Native.rd(com.jopdesign.sys.Const.IO_WD));
}
static public void smoInfo10() {
for (int i = 0; i < 10; i++) {
printSMOInfo = true;
// while (printSMOInfo)
// smo.waitForNextPeriod();
}
}
static public void smoInfo() {
// printScalar("wd",Native.rd(Const.IO_WD)); //TODO: Can it be read?
System.out.println("======SMO INFO START======");
// printScalar("sp",Native.rd(com.jopdesign.sys.Const.IO_WD));
printScalar("i1", i1);
printScalar("i2", i2);
printScalar("i_low", i_low);
printScalar("i_up", i_up);
printScalar("b_low_fp", b_low_fp);
printScalar("b_up_fp", b_up_fp);
printScalar("bias_fp", bias_fp);
printScalar("m", m);
printScalar("n", n);
printMatrix("data_fp", data_fp);
printVector("y_fp", y_fp);
printVector("fcache_fp", fcache_fp);
printVector("kernelCache_fp", kernelCache_fp);
printVector("findexset", findexset);
printVector("findexset0pos", findexset0pos);
printVector("findexset0", findexset0);
printScalar("findexset0Size", findexset0Size);
printVector("alpha_fp", alpha_fp);
printScalar("alphaTol_fp", alphaTol_fp);
printScalar("c_fp", c_fp);
printScalar("tol_fp", tol_fp);
printScalar("eps_fp", eps_fp);
printBoolean("takeStepFlag", takeStepFlag);
printBoolean("takeStepResult", takeStepResult);
printScalar("takeStepCount", takeStepCount);
int svs = 0;
for(int i=0;i<m;i++){
if(alpha_fp[i]>alphaTol_fp)
svs++;
}
printScalar("#sv", svs);
printScalar("training err cnt",getTrainingErrorCountFP());
for (int i = 0; i < 100000; i++)
;
System.out.println("======SMO INFO END======");
}
static void printBoolean(String str, boolean b) {
System.out.print(str);
System.out.print(':');
if (b)
System.out.println("true");
else
System.out.println("false");
}
static void printScalar(String str, int sca) {
System.out.print(str);
System.out.print(':');
System.out.println(sca);
for (int i = 0; i < 100; i++)
;
}
static void printVector(String str, int[] ve) {
System.out.print(str);
System.out.print(" {");
for (int i = 0; i < ve.length; i++) {
System.out.print(i);
System.out.print(':');
System.out.print(ve[i]);
if (i < (ve.length - 1))
System.out.print(", ");
for (int j = 0; j < 1000; j++)
;
}
System.out.println("}");
for (int i = 0; i < 1000; i++)
;
}
static void printMatrix(String str, int[][] ma) {
for (int i = 0; i < ma.length; i++) {
System.out.print(str);
System.out.print("[");
System.out.print(i);
System.out.print("]");
System.out.print(":");
printVector("", ma[i]);
}
}
static public int getSV(){
int svs = 0;
for(int i=0;i<m;i++){
if(alpha_fp[i]>alphaTol_fp)
svs++;
}
return svs;
}
// sorts the indeces of the alphas
static void sortAlphaIndex(){
int changed;
if (PRINT) System.out.println("SMO.sortalphaindex");
do {
changed = 0;
if (PRINT) System.out.println("SMO.sort1");
for(int i = 0; i < (m-1); i++){
if(alpha_fp[alpha_index_sorted[i]] < alpha_fp[alpha_index_sorted[i+1]]) {
int tmp = alpha_index_sorted[i];
alpha_index_sorted[i] = alpha_index_sorted[i+1];
alpha_index_sorted[i+1] = tmp;
changed++;
}
}
if (PRINT) System.out.println("SMO.sort2");
if (PRINT) {
System.out.println("Sorting...");
}
} while(changed > 0);
}
/**
* Do not instanciate me.
*/
private SMOBinaryClassifierFP(){}
}