[liblinear] 09/26: Imported Upstream version 2.01

Christian Kastner ckk at moszumanska.debian.org
Sun Sep 6 13:33:10 UTC 2015


This is an automated email from the git hooks/post-receive script.

ckk pushed a commit to branch master
in repository liblinear.

commit e4709192e8b28962e0d75d1b2416985b568e35ef
Author: Christian Kastner <ckk at kvr.at>
Date:   Fri Sep 4 18:33:32 2015 +0200

    Imported Upstream version 2.01
---
 COPYRIGHT                    |   2 +-
 Makefile                     |  17 +-
 Makefile.win                 |   8 +-
 README                       |  79 +++++++-
 blas/Makefile                |  22 ---
 blas/blas.h                  |  25 ---
 blas/blasp.h                 | 430 -------------------------------------------
 blas/daxpy.c                 |  49 -----
 blas/ddot.c                  |  50 -----
 blas/dnrm2.c                 |  62 -------
 blas/dscal.c                 |  44 -----
 linear.cpp                   | 305 ++++++++++++++++++++++++++++--
 linear.def                   |   3 +
 linear.h                     |   5 +
 matlab/Makefile              |  25 +--
 matlab/README                |  14 +-
 matlab/libsvmread.c          |   7 +-
 matlab/libsvmwrite.c         |  13 +-
 matlab/linear_model_matlab.c |   4 +-
 matlab/make.m                |  41 ++---
 matlab/predict.c             |  12 +-
 matlab/train.c               | 119 +++++++++---
 predict.c                    |   4 +-
 python/README                |  37 ++++
 python/liblinear.py          |  76 ++++++--
 python/liblinearutil.py      |  24 ++-
 train.c                      |  54 +++++-
 tron.cpp                     |  22 ++-
 tron.h                       |   3 +-
 windows/liblinear.dll        | Bin 155648 -> 0 bytes
 windows/libsvmread.mexw64    | Bin 11264 -> 0 bytes
 windows/libsvmwrite.mexw64   | Bin 10240 -> 0 bytes
 windows/predict.exe          | Bin 118784 -> 0 bytes
 windows/predict.mexw64       | Bin 16384 -> 0 bytes
 windows/train.exe            | Bin 155136 -> 0 bytes
 windows/train.mexw64         | Bin 61952 -> 0 bytes
 36 files changed, 711 insertions(+), 845 deletions(-)

diff --git a/COPYRIGHT b/COPYRIGHT
index 7484947..054c8d0 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,5 +1,5 @@
 
-Copyright (c) 2007-2013 The LIBLINEAR Project.
+Copyright (c) 2007-2015 The LIBLINEAR Project.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/Makefile b/Makefile
index 7a74e26..99fdece 100644
--- a/Makefile
+++ b/Makefile
@@ -1,25 +1,24 @@
 CXX ?= g++
 CC ?= gcc
 CFLAGS = -Wall -Wconversion -O3 -fPIC
-LIBS = blas/blas.a
-SHVER = 1
+LIBS =
+SHVER = 3
 OS = $(shell uname)
-#LIBS = -lblas
 
 all: train predict
 
-lib: linear.o tron.o blas/blas.a
+lib: linear.o tron.o
 	if [ "$(OS)" = "Darwin" ]; then \
 		SHARED_LIB_FLAG="-dynamiclib -Wl,-install_name,liblinear.so.$(SHVER)"; \
 	else \
 		SHARED_LIB_FLAG="-shared -Wl,-soname,liblinear.so.$(SHVER)"; \
 	fi; \
-	$(CXX) $${SHARED_LIB_FLAG} linear.o tron.o blas/blas.a -o liblinear.so.$(SHVER)
+	$(CXX) $${SHARED_LIB_FLAG} linear.o tron.o -o liblinear.so.$(SHVER)
 
-train: tron.o linear.o train.c blas/blas.a
+train: tron.o linear.o train.c
 	$(CXX) $(CFLAGS) -o train train.c tron.o linear.o $(LIBS)
 
-predict: tron.o linear.o predict.c blas/blas.a
+predict: tron.o linear.o predict.c
 	$(CXX) $(CFLAGS) -o predict predict.c tron.o linear.o $(LIBS)
 
 tron.o: tron.cpp tron.h
@@ -28,10 +27,6 @@ tron.o: tron.cpp tron.h
 linear.o: linear.cpp linear.h
 	$(CXX) $(CFLAGS) -c -o linear.o linear.cpp
 
-blas/blas.a: blas/*.c blas/*.h
-	make -C blas OPTFLAGS='$(CFLAGS)' CC='$(CC)';
-
 clean:
-	make -C blas clean
 	make -C matlab clean
 	rm -f *~ tron.o linear.o train predict liblinear.so.$(SHVER)
diff --git a/Makefile.win b/Makefile.win
index 84aa489..c4ad3bf 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -1,11 +1,5 @@
-#You must ensure nmake.exe, cl.exe, link.exe are in system path.
-#VCVARS32.bat
-#Under dosbox prompt
-#nmake -f Makefile.win
-
-##########################################
 CXX = cl.exe
-CFLAGS = -nologo -O2 -EHsc -I. -D __WIN32__ -D _CRT_SECURE_NO_DEPRECATE
+CFLAGS = /nologo /O2 /EHsc /I. /D _WIN64 /D _CRT_SECURE_NO_DEPRECATE
 TARGET = windows
 
 all: $(TARGET)\train.exe $(TARGET)\predict.exe
diff --git a/README b/README
index 3a659e0..589d04a 100644
--- a/README
+++ b/README
@@ -123,7 +123,7 @@ options:
 	-s 1, 3, 4 and 7
 		Dual maximal violation <= eps; similar to libsvm (default 0.1)
 	-s 5 and 6
-		|f'(w)|_inf <= eps*min(pos,neg)/l*|f'(w0)|_inf,
+		|f'(w)|_1 <= eps*min(pos,neg)/l*|f'(w0)|_1,
 		where f is the primal function (default 0.01)
 	-s 12 and 13\n"
 		|f'(alpha)|_1 <= eps |f'(alpha0)|,
@@ -131,11 +131,16 @@ options:
 -B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)
 -wi weight: weights adjust the parameter C of different classes (see README for details)
 -v n: n-fold cross validation mode
+-C : find parameter C (only for -s 0 and 2)
 -q : quiet mode (no outputs)
 
 Option -v randomly splits the data into n parts and calculates cross
 validation accuracy on them.
 
+Option -C conducts cross validation under different C values and finds
+the best one. This options is supported only by -s 0 and -s 2. If
+the solver is not specified, -s 2 is used.
+
 Formulations:
 
 For L2-regularized logistic regression (-s 0), we solve
@@ -241,10 +246,27 @@ Train a logistic regression model.
 
 > train -v 5 -e 0.001 data_file
 
-Do five-fold cross-validation using L2-loss svm.
+Do five-fold cross-validation using L2-loss SVM.
 Use a smaller stopping tolerance 0.001 than the default
 0.1 if you want more accurate solutions.
 
+> train -C data_file
+
+Conduct cross validation many times by L2-loss SVM 
+and find the parameter C which achieves the best cross 
+validation accuracy.
+
+> train -C -s 0 -v 3 -c 0.5 -e 0.0001 data_file
+
+For parameter selection by -C, users can specify other 
+solvers (currently -s 0 and -s 2 are supported) and 
+different number of CV folds. Further, users can use 
+the -c option to specify the smallest C value of the 
+search range. This setting is useful when users want 
+to rerun the parameter selection procedure from a 
+specified C under a different setting, such as a stricter 
+stopping tolerance -e 0.0001 in the above example.
+
 > train -c 10 -w1 2 -w2 5 -w3 2 four_class_data_file
 
 Train four classifiers:
@@ -407,6 +429,22 @@ Library Usage
 
     The format of prob is same as that for train().
 
+- Function: void find_parameter_C(const struct problem *prob, 
+            const struct parameter *param, int nr_fold, double start_C, 
+	    double max_C, double *best_C, double *best_rate);
+
+    This function is similar to cross_validation. However, instead of
+    conducting cross validation under a specified parameter C, it 
+    conducts cross validation many times under parameters C = start_C, 
+    2*start_C, 4*start_C, 8*start_C, ..., and finds the best one with
+    the highest cross validation accuracy.
+    
+    If start_C <= 0, then this procedure calculates a small enough C 
+    for prob as the start_C. The procedure stops when the models of 
+    all folds become stable or C reaches max_C. The best C and the 
+    corresponding accuracy are assigned to *best_C and *best_rate,
+    respectively.
+
 - Function: double predict(const model *model_, const feature_node *x);
 
     For a classification model, the predicted class for x is returned.
@@ -418,11 +456,11 @@ Library Usage
 
     This function gives nr_w decision values in the array dec_values. 
     nr_w=1 if regression is applied or the number of classes is two. An exception is
-    multi-class svm by Crammer and Singer (-s 4), where nr_w = 2 if there are two classes. For all other situations, nr_w is the 
+    multi-class SVM by Crammer and Singer (-s 4), where nr_w = 2 if there are two classes. For all other situations, nr_w is the 
     number of classes.
 
     We implement one-vs-the rest multi-class strategy (-s 0,1,2,3,5,6,7) 
-    and multi-class svm by Crammer and Singer (-s 4) for multi-class SVM.
+    and multi-class SVM by Crammer and Singer (-s 4) for multi-class SVM.
     The class with the highest decision value is returned.
 
 - Function: double predict_probability(const struct model *model_,
@@ -448,6 +486,24 @@ Library Usage
     This function outputs the name of labels into an array called label.
     For a regression model, label is unchanged.
 
+- Function: double get_decfun_coef(const struct model *model_, int feat_idx,
+            int label_idx);
+
+    This function gives the coefficient for the feature with feature index =
+    feat_idx and the class with label index = label_idx. Note that feat_idx
+    starts from 1, while label_idx starts from 0. If feat_idx is not in the
+    valid range (1 to nr_feature), then a zero value will be returned. For
+    classification models, if label_idx is not in the valid range (0 to
+    nr_class-1), then a zero value will be returned; for regression models,
+    label_idx is ignored.
+
+- Function: double get_decfun_bias(const struct model *model_, int label_idx);
+
+    This function gives the bias term corresponding to the class with the
+    label_idx. For classification models, if label_idx is not in a valid range
+    (0 to nr_class-1), then a zero value will be returned; for regression
+    models, label_idx is ignored.
+
 - Function: const char *check_parameter(const struct problem *prob,
             const struct parameter *param);
 
@@ -456,6 +512,16 @@ Library Usage
     train() and cross_validation(). It returns NULL if the
     parameters are feasible, otherwise an error message is returned.
 
+- Function: int check_probability_model(const struct model *model);
+
+    This function returns 1 if the model supports probability output;
+    otherwise, it returns 0.
+
+- Function: int check_regression_model(const struct model *model);
+
+    This function returns 1 if the model is a regression model; otherwise
+    it returns 0.
+
 - Function: int save_model(const char *model_file_name,
             const struct model *model_);
 
@@ -495,7 +561,7 @@ Visual C++, use the following steps:
 1. Open a dos command box and change to liblinear directory. If
 environment variables of VC++ have not been set, type
 
-"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
+""C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\vcvars64.bat""
 
 You may have to modify the above command according which version of
 VC++ or where it is installed.
@@ -504,6 +570,9 @@ VC++ or where it is installed.
 
 nmake -f Makefile.win clean all
 
+2. (Optional) To build 32-bit windows binaries, you must
+	(1) Setup "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat" instead of vcvars64.bat
+	(2) Change CFLAGS in Makefile.win: /D _WIN64 to /D _WIN32
 
 MATLAB/OCTAVE Interface
 =======================
diff --git a/blas/Makefile b/blas/Makefile
deleted file mode 100644
index 895fd24..0000000
--- a/blas/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-AR     = ar rcv
-RANLIB = ranlib 
-
-HEADERS = blas.h blasp.h
-FILES = dnrm2.o daxpy.o ddot.o dscal.o 
-
-CFLAGS = $(OPTFLAGS) 
-FFLAGS = $(OPTFLAGS)
-
-blas: $(FILES) $(HEADERS)
-	$(AR) blas.a $(FILES)  
-	$(RANLIB) blas.a
-
-clean:
-	- rm -f *.o
-	- rm -f *.a
-	- rm -f *~
-
-.c.o:
-	$(CC) $(CFLAGS) -c $*.c
-
-
diff --git a/blas/blas.h b/blas/blas.h
deleted file mode 100644
index 558893a..0000000
--- a/blas/blas.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* blas.h  --  C header file for BLAS                         Ver 1.0 */
-/* Jesse Bennett                                       March 23, 2000 */
-
-/**  barf  [ba:rf]  2.  "He suggested using FORTRAN, and everybody barfed."
-
-	- From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
-
-#ifndef BLAS_INCLUDE
-#define BLAS_INCLUDE
-
-/* Data types specific to BLAS implementation */
-typedef struct { float r, i; } fcomplex;
-typedef struct { double r, i; } dcomplex;
-typedef int blasbool;
-
-#include "blasp.h"    /* Prototypes for all BLAS functions */
-
-#define FALSE 0
-#define TRUE  1
-
-/* Macro functions */
-#define MIN(a,b) ((a) <= (b) ? (a) : (b))
-#define MAX(a,b) ((a) >= (b) ? (a) : (b))
-
-#endif
diff --git a/blas/blasp.h b/blas/blasp.h
deleted file mode 100644
index 745836d..0000000
--- a/blas/blasp.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/* blasp.h  --  C prototypes for BLAS                         Ver 1.0 */
-/* Jesse Bennett                                       March 23, 2000 */
-
-/* Functions  listed in alphabetical order */
-
-#ifdef F2C_COMPAT
-
-void cdotc_(fcomplex *dotval, int *n, fcomplex *cx, int *incx,
-            fcomplex *cy, int *incy);
-
-void cdotu_(fcomplex *dotval, int *n, fcomplex *cx, int *incx,
-            fcomplex *cy, int *incy);
-
-double sasum_(int *n, float *sx, int *incx);
-
-double scasum_(int *n, fcomplex *cx, int *incx);
-
-double scnrm2_(int *n, fcomplex *x, int *incx);
-
-double sdot_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-double snrm2_(int *n, float *x, int *incx);
-
-void zdotc_(dcomplex *dotval, int *n, dcomplex *cx, int *incx,
-            dcomplex *cy, int *incy);
-
-void zdotu_(dcomplex *dotval, int *n, dcomplex *cx, int *incx,
-            dcomplex *cy, int *incy);
-
-#else
-
-fcomplex cdotc_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-fcomplex cdotu_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-float sasum_(int *n, float *sx, int *incx);
-
-float scasum_(int *n, fcomplex *cx, int *incx);
-
-float scnrm2_(int *n, fcomplex *x, int *incx);
-
-float sdot_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-float snrm2_(int *n, float *x, int *incx);
-
-dcomplex zdotc_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-dcomplex zdotu_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-#endif
-
-/* Remaining functions listed in alphabetical order */
-
-int caxpy_(int *n, fcomplex *ca, fcomplex *cx, int *incx, fcomplex *cy,
-           int *incy);
-
-int ccopy_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-int cgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
-           fcomplex *alpha, fcomplex *a, int *lda, fcomplex *x, int *incx,
-           fcomplex *beta, fcomplex *y, int *incy);
-
-int cgemm_(char *transa, char *transb, int *m, int *n, int *k,
-           fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b, int *ldb,
-           fcomplex *beta, fcomplex *c, int *ldc);
-
-int cgemv_(char *trans, int *m, int *n, fcomplex *alpha, fcomplex *a,
-           int *lda, fcomplex *x, int *incx, fcomplex *beta, fcomplex *y,
-           int *incy);
-
-int cgerc_(int *m, int *n, fcomplex *alpha, fcomplex *x, int *incx,
-           fcomplex *y, int *incy, fcomplex *a, int *lda);
-
-int cgeru_(int *m, int *n, fcomplex *alpha, fcomplex *x, int *incx,
-           fcomplex *y, int *incy, fcomplex *a, int *lda);
-
-int chbmv_(char *uplo, int *n, int *k, fcomplex *alpha, fcomplex *a,
-           int *lda, fcomplex *x, int *incx, fcomplex *beta, fcomplex *y,
-           int *incy);
-
-int chemm_(char *side, char *uplo, int *m, int *n, fcomplex *alpha,
-           fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta,
-           fcomplex *c, int *ldc);
-
-int chemv_(char *uplo, int *n, fcomplex *alpha, fcomplex *a, int *lda,
-           fcomplex *x, int *incx, fcomplex *beta, fcomplex *y, int *incy);
-
-int cher_(char *uplo, int *n, float *alpha, fcomplex *x, int *incx,
-          fcomplex *a, int *lda);
-
-int cher2_(char *uplo, int *n, fcomplex *alpha, fcomplex *x, int *incx,
-           fcomplex *y, int *incy, fcomplex *a, int *lda);
-
-int cher2k_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha,
-            fcomplex *a, int *lda, fcomplex *b, int *ldb, float *beta,
-            fcomplex *c, int *ldc);
-
-int cherk_(char *uplo, char *trans, int *n, int *k, float *alpha,
-           fcomplex *a, int *lda, float *beta, fcomplex *c, int *ldc);
-
-int chpmv_(char *uplo, int *n, fcomplex *alpha, fcomplex *ap, fcomplex *x,
-           int *incx, fcomplex *beta, fcomplex *y, int *incy);
-
-int chpr_(char *uplo, int *n, float *alpha, fcomplex *x, int *incx,
-          fcomplex *ap);
-
-int chpr2_(char *uplo, int *n, fcomplex *alpha, fcomplex *x, int *incx,
-           fcomplex *y, int *incy, fcomplex *ap);
-
-int crotg_(fcomplex *ca, fcomplex *cb, float *c, fcomplex *s);
-
-int cscal_(int *n, fcomplex *ca, fcomplex *cx, int *incx);
-
-int csscal_(int *n, float *sa, fcomplex *cx, int *incx);
-
-int cswap_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-int csymm_(char *side, char *uplo, int *m, int *n, fcomplex *alpha,
-           fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta,
-           fcomplex *c, int *ldc);
-
-int csyr2k_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha,
-            fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta,
-            fcomplex *c, int *ldc);
-
-int csyrk_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha,
-           fcomplex *a, int *lda, fcomplex *beta, fcomplex *c, int *ldc);
-
-int ctbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           fcomplex *a, int *lda, fcomplex *x, int *incx);
-
-int ctbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           fcomplex *a, int *lda, fcomplex *x, int *incx);
-
-int ctpmv_(char *uplo, char *trans, char *diag, int *n, fcomplex *ap,
-           fcomplex *x, int *incx);
-
-int ctpsv_(char *uplo, char *trans, char *diag, int *n, fcomplex *ap,
-           fcomplex *x, int *incx);
-
-int ctrmm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b,
-           int *ldb);
-
-int ctrmv_(char *uplo, char *trans, char *diag, int *n, fcomplex *a,
-           int *lda, fcomplex *x, int *incx);
-
-int ctrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b,
-           int *ldb);
-
-int ctrsv_(char *uplo, char *trans, char *diag, int *n, fcomplex *a,
-           int *lda, fcomplex *x, int *incx);
-
-int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy,
-           int *incy);
-
-int dcopy_(int *n, double *sx, int *incx, double *sy, int *incy);
-
-int dgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
-           double *alpha, double *a, int *lda, double *x, int *incx,
-           double *beta, double *y, int *incy);
-
-int dgemm_(char *transa, char *transb, int *m, int *n, int *k,
-           double *alpha, double *a, int *lda, double *b, int *ldb,
-           double *beta, double *c, int *ldc);
-
-int dgemv_(char *trans, int *m, int *n, double *alpha, double *a,
-           int *lda, double *x, int *incx, double *beta, double *y, 
-           int *incy);
-
-int dger_(int *m, int *n, double *alpha, double *x, int *incx,
-          double *y, int *incy, double *a, int *lda);
-
-int drot_(int *n, double *sx, int *incx, double *sy, int *incy,
-          double *c, double *s);
-
-int drotg_(double *sa, double *sb, double *c, double *s);
-
-int dsbmv_(char *uplo, int *n, int *k, double *alpha, double *a,
-           int *lda, double *x, int *incx, double *beta, double *y, 
-           int *incy);
-
-int dscal_(int *n, double *sa, double *sx, int *incx);
-
-int dspmv_(char *uplo, int *n, double *alpha, double *ap, double *x,
-           int *incx, double *beta, double *y, int *incy);
-
-int dspr_(char *uplo, int *n, double *alpha, double *x, int *incx,
-          double *ap);
-
-int dspr2_(char *uplo, int *n, double *alpha, double *x, int *incx,
-           double *y, int *incy, double *ap);
-
-int dswap_(int *n, double *sx, int *incx, double *sy, int *incy);
-
-int dsymm_(char *side, char *uplo, int *m, int *n, double *alpha,
-           double *a, int *lda, double *b, int *ldb, double *beta,
-           double *c, int *ldc);
-
-int dsymv_(char *uplo, int *n, double *alpha, double *a, int *lda,
-           double *x, int *incx, double *beta, double *y, int *incy);
-
-int dsyr_(char *uplo, int *n, double *alpha, double *x, int *incx,
-          double *a, int *lda);
-
-int dsyr2_(char *uplo, int *n, double *alpha, double *x, int *incx,
-           double *y, int *incy, double *a, int *lda);
-
-int dsyr2k_(char *uplo, char *trans, int *n, int *k, double *alpha,
-            double *a, int *lda, double *b, int *ldb, double *beta,
-            double *c, int *ldc);
-
-int dsyrk_(char *uplo, char *trans, int *n, int *k, double *alpha,
-           double *a, int *lda, double *beta, double *c, int *ldc);
-
-int dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           double *a, int *lda, double *x, int *incx);
-
-int dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           double *a, int *lda, double *x, int *incx);
-
-int dtpmv_(char *uplo, char *trans, char *diag, int *n, double *ap,
-           double *x, int *incx);
-
-int dtpsv_(char *uplo, char *trans, char *diag, int *n, double *ap,
-           double *x, int *incx);
-
-int dtrmm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, double *alpha, double *a, int *lda, double *b, 
-           int *ldb);
-
-int dtrmv_(char *uplo, char *trans, char *diag, int *n, double *a,
-           int *lda, double *x, int *incx);
-
-int dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, double *alpha, double *a, int *lda, double *b, 
-           int *ldb);
-
-int dtrsv_(char *uplo, char *trans, char *diag, int *n, double *a,
-           int *lda, double *x, int *incx);
-
-
-int saxpy_(int *n, float *sa, float *sx, int *incx, float *sy, int *incy);
-
-int scopy_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-int sgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
-           float *alpha, float *a, int *lda, float *x, int *incx,
-           float *beta, float *y, int *incy);
-
-int sgemm_(char *transa, char *transb, int *m, int *n, int *k,
-           float *alpha, float *a, int *lda, float *b, int *ldb,
-           float *beta, float *c, int *ldc);
-
-int sgemv_(char *trans, int *m, int *n, float *alpha, float *a,
-           int *lda, float *x, int *incx, float *beta, float *y, 
-           int *incy);
-
-int sger_(int *m, int *n, float *alpha, float *x, int *incx,
-          float *y, int *incy, float *a, int *lda);
-
-int srot_(int *n, float *sx, int *incx, float *sy, int *incy,
-          float *c, float *s);
-
-int srotg_(float *sa, float *sb, float *c, float *s);
-
-int ssbmv_(char *uplo, int *n, int *k, float *alpha, float *a,
-           int *lda, float *x, int *incx, float *beta, float *y, 
-           int *incy);
-
-int sscal_(int *n, float *sa, float *sx, int *incx);
-
-int sspmv_(char *uplo, int *n, float *alpha, float *ap, float *x,
-           int *incx, float *beta, float *y, int *incy);
-
-int sspr_(char *uplo, int *n, float *alpha, float *x, int *incx,
-          float *ap);
-
-int sspr2_(char *uplo, int *n, float *alpha, float *x, int *incx,
-           float *y, int *incy, float *ap);
-
-int sswap_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-int ssymm_(char *side, char *uplo, int *m, int *n, float *alpha,
-           float *a, int *lda, float *b, int *ldb, float *beta,
-           float *c, int *ldc);
-
-int ssymv_(char *uplo, int *n, float *alpha, float *a, int *lda,
-           float *x, int *incx, float *beta, float *y, int *incy);
-
-int ssyr_(char *uplo, int *n, float *alpha, float *x, int *incx,
-          float *a, int *lda);
-
-int ssyr2_(char *uplo, int *n, float *alpha, float *x, int *incx,
-           float *y, int *incy, float *a, int *lda);
-
-int ssyr2k_(char *uplo, char *trans, int *n, int *k, float *alpha,
-            float *a, int *lda, float *b, int *ldb, float *beta,
-            float *c, int *ldc);
-
-int ssyrk_(char *uplo, char *trans, int *n, int *k, float *alpha,
-           float *a, int *lda, float *beta, float *c, int *ldc);
-
-int stbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           float *a, int *lda, float *x, int *incx);
-
-int stbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           float *a, int *lda, float *x, int *incx);
-
-int stpmv_(char *uplo, char *trans, char *diag, int *n, float *ap,
-           float *x, int *incx);
-
-int stpsv_(char *uplo, char *trans, char *diag, int *n, float *ap,
-           float *x, int *incx);
-
-int strmm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, float *alpha, float *a, int *lda, float *b, 
-           int *ldb);
-
-int strmv_(char *uplo, char *trans, char *diag, int *n, float *a,
-           int *lda, float *x, int *incx);
-
-int strsm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, float *alpha, float *a, int *lda, float *b, 
-           int *ldb);
-
-int strsv_(char *uplo, char *trans, char *diag, int *n, float *a,
-           int *lda, float *x, int *incx);
-
-int zaxpy_(int *n, dcomplex *ca, dcomplex *cx, int *incx, dcomplex *cy,
-           int *incy);
-
-int zcopy_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-int zdscal_(int *n, double *sa, dcomplex *cx, int *incx);
-
-int zgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
-           dcomplex *alpha, dcomplex *a, int *lda, dcomplex *x, int *incx,
-           dcomplex *beta, dcomplex *y, int *incy);
-
-int zgemm_(char *transa, char *transb, int *m, int *n, int *k,
-           dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b, int *ldb,
-           dcomplex *beta, dcomplex *c, int *ldc);
-
-int zgemv_(char *trans, int *m, int *n, dcomplex *alpha, dcomplex *a,
-           int *lda, dcomplex *x, int *incx, dcomplex *beta, dcomplex *y,
-           int *incy);
-
-int zgerc_(int *m, int *n, dcomplex *alpha, dcomplex *x, int *incx,
-           dcomplex *y, int *incy, dcomplex *a, int *lda);
-
-int zgeru_(int *m, int *n, dcomplex *alpha, dcomplex *x, int *incx,
-           dcomplex *y, int *incy, dcomplex *a, int *lda);
-
-int zhbmv_(char *uplo, int *n, int *k, dcomplex *alpha, dcomplex *a,
-           int *lda, dcomplex *x, int *incx, dcomplex *beta, dcomplex *y,
-           int *incy);
-
-int zhemm_(char *side, char *uplo, int *m, int *n, dcomplex *alpha,
-           dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta,
-           dcomplex *c, int *ldc);
-
-int zhemv_(char *uplo, int *n, dcomplex *alpha, dcomplex *a, int *lda,
-           dcomplex *x, int *incx, dcomplex *beta, dcomplex *y, int *incy);
-
-int zher_(char *uplo, int *n, double *alpha, dcomplex *x, int *incx,
-          dcomplex *a, int *lda);
-
-int zher2_(char *uplo, int *n, dcomplex *alpha, dcomplex *x, int *incx,
-           dcomplex *y, int *incy, dcomplex *a, int *lda);
-
-int zher2k_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha,
-            dcomplex *a, int *lda, dcomplex *b, int *ldb, double *beta,
-            dcomplex *c, int *ldc);
-
-int zherk_(char *uplo, char *trans, int *n, int *k, double *alpha,
-           dcomplex *a, int *lda, double *beta, dcomplex *c, int *ldc);
-
-int zhpmv_(char *uplo, int *n, dcomplex *alpha, dcomplex *ap, dcomplex *x,
-           int *incx, dcomplex *beta, dcomplex *y, int *incy);
-
-int zhpr_(char *uplo, int *n, double *alpha, dcomplex *x, int *incx,
-          dcomplex *ap);
-
-int zhpr2_(char *uplo, int *n, dcomplex *alpha, dcomplex *x, int *incx,
-           dcomplex *y, int *incy, dcomplex *ap);
-
-int zrotg_(dcomplex *ca, dcomplex *cb, double *c, dcomplex *s);
-
-int zscal_(int *n, dcomplex *ca, dcomplex *cx, int *incx);
-
-int zswap_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-int zsymm_(char *side, char *uplo, int *m, int *n, dcomplex *alpha,
-           dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta,
-           dcomplex *c, int *ldc);
-
-int zsyr2k_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha,
-            dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta,
-            dcomplex *c, int *ldc);
-
-int zsyrk_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha,
-           dcomplex *a, int *lda, dcomplex *beta, dcomplex *c, int *ldc);
-
-int ztbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           dcomplex *a, int *lda, dcomplex *x, int *incx);
-
-int ztbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
-           dcomplex *a, int *lda, dcomplex *x, int *incx);
-
-int ztpmv_(char *uplo, char *trans, char *diag, int *n, dcomplex *ap,
-           dcomplex *x, int *incx);
-
-int ztpsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *ap,
-           dcomplex *x, int *incx);
-
-int ztrmm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b,
-           int *ldb);
-
-int ztrmv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a,
-           int *lda, dcomplex *x, int *incx);
-
-int ztrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
-           int *n, dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b,
-           int *ldb);
-
-int ztrsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a,
-           int *lda, dcomplex *x, int *incx);
diff --git a/blas/daxpy.c b/blas/daxpy.c
deleted file mode 100644
index 58f345a..0000000
--- a/blas/daxpy.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "blas.h"
-
-int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy,
-           int *incy)
-{
-  long int i, m, ix, iy, nn, iincx, iincy;
-  register double ssa;
-
-  /* constant times a vector plus a vector.   
-     uses unrolled loop for increments equal to one.   
-     jack dongarra, linpack, 3/11/78.   
-     modified 12/3/93, array(1) declarations changed to array(*) */
-
-  /* Dereference inputs */
-  nn = *n;
-  ssa = *sa;
-  iincx = *incx;
-  iincy = *incy;
-
-  if( nn > 0 && ssa != 0.0 )
-  {
-    if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */
-    {
-      m = nn-3;
-      for (i = 0; i < m; i += 4)
-      {
-        sy[i] += ssa * sx[i];
-        sy[i+1] += ssa * sx[i+1];
-        sy[i+2] += ssa * sx[i+2];
-        sy[i+3] += ssa * sx[i+3];
-      }
-      for ( ; i < nn; ++i) /* clean-up loop */
-        sy[i] += ssa * sx[i];
-    }
-    else /* code for unequal increments or equal increments not equal to 1 */
-    {
-      ix = iincx >= 0 ? 0 : (1 - nn) * iincx;
-      iy = iincy >= 0 ? 0 : (1 - nn) * iincy;
-      for (i = 0; i < nn; i++)
-      {
-        sy[iy] += ssa * sx[ix];
-        ix += iincx;
-        iy += iincy;
-      }
-    }
-  }
-
-  return 0;
-} /* daxpy_ */
diff --git a/blas/ddot.c b/blas/ddot.c
deleted file mode 100644
index a64a280..0000000
--- a/blas/ddot.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "blas.h"
-
-double ddot_(int *n, double *sx, int *incx, double *sy, int *incy)
-{
-  long int i, m, nn, iincx, iincy;
-  double stemp;
-  long int ix, iy;
-
-  /* forms the dot product of two vectors.   
-     uses unrolled loops for increments equal to one.   
-     jack dongarra, linpack, 3/11/78.   
-     modified 12/3/93, array(1) declarations changed to array(*) */
-
-  /* Dereference inputs */
-  nn = *n;
-  iincx = *incx;
-  iincy = *incy;
-
-  stemp = 0.0;
-  if (nn > 0)
-  {
-    if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */
-    {
-      m = nn-4;
-      for (i = 0; i < m; i += 5)
-        stemp += sx[i] * sy[i] + sx[i+1] * sy[i+1] + sx[i+2] * sy[i+2] +
-                 sx[i+3] * sy[i+3] + sx[i+4] * sy[i+4];
-
-      for ( ; i < nn; i++)        /* clean-up loop */
-        stemp += sx[i] * sy[i];
-    }
-    else /* code for unequal increments or equal increments not equal to 1 */
-    {
-      ix = 0;
-      iy = 0;
-      if (iincx < 0)
-        ix = (1 - nn) * iincx;
-      if (iincy < 0)
-        iy = (1 - nn) * iincy;
-      for (i = 0; i < nn; i++)
-      {
-        stemp += sx[ix] * sy[iy];
-        ix += iincx;
-        iy += iincy;
-      }
-    }
-  }
-
-  return stemp;
-} /* ddot_ */
diff --git a/blas/dnrm2.c b/blas/dnrm2.c
deleted file mode 100644
index e50cdf7..0000000
--- a/blas/dnrm2.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <math.h>  /* Needed for fabs() and sqrt() */
-#include "blas.h"
-
-double dnrm2_(int *n, double *x, int *incx)
-{
-  long int ix, nn, iincx;
-  double norm, scale, absxi, ssq, temp;
-
-/*  DNRM2 returns the euclidean norm of a vector via the function   
-    name, so that   
-
-       DNRM2 := sqrt( x'*x )   
-
-    -- This version written on 25-October-1982.   
-       Modified on 14-October-1993 to inline the call to SLASSQ.   
-       Sven Hammarling, Nag Ltd.   */
-
-  /* Dereference inputs */
-  nn = *n;
-  iincx = *incx;
-
-  if( nn > 0 && iincx > 0 )
-  {
-    if (nn == 1)
-    {
-      norm = fabs(x[0]);
-    }  
-    else
-    {
-      scale = 0.0;
-      ssq = 1.0;
-
-      /* The following loop is equivalent to this call to the LAPACK 
-         auxiliary routine:   CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
-
-      for (ix=(nn-1)*iincx; ix>=0; ix-=iincx)
-      {
-        if (x[ix] != 0.0)
-        {
-          absxi = fabs(x[ix]);
-          if (scale < absxi)
-          {
-            temp = scale / absxi;
-            ssq = ssq * (temp * temp) + 1.0;
-            scale = absxi;
-          }
-          else
-          {
-            temp = absxi / scale;
-            ssq += temp * temp;
-          }
-        }
-      }
-      norm = scale * sqrt(ssq);
-    }
-  }
-  else
-    norm = 0.0;
-
-  return norm;
-
-} /* dnrm2_ */
diff --git a/blas/dscal.c b/blas/dscal.c
deleted file mode 100644
index a0eca0c..0000000
--- a/blas/dscal.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "blas.h"
-
-int dscal_(int *n, double *sa, double *sx, int *incx)
-{
-  long int i, m, nincx, nn, iincx;
-  double ssa;
-
-  /* scales a vector by a constant.   
-     uses unrolled loops for increment equal to 1.   
-     jack dongarra, linpack, 3/11/78.   
-     modified 3/93 to return if incx .le. 0.   
-     modified 12/3/93, array(1) declarations changed to array(*) */
-
-  /* Dereference inputs */
-  nn = *n;
-  iincx = *incx;
-  ssa = *sa;
-
-  if (nn > 0 && iincx > 0)
-  {
-    if (iincx == 1) /* code for increment equal to 1 */
-    {
-      m = nn-4;
-      for (i = 0; i < m; i += 5)
-      {
-        sx[i] = ssa * sx[i];
-        sx[i+1] = ssa * sx[i+1];
-        sx[i+2] = ssa * sx[i+2];
-        sx[i+3] = ssa * sx[i+3];
-        sx[i+4] = ssa * sx[i+4];
-      }
-      for ( ; i < nn; ++i) /* clean-up loop */
-        sx[i] = ssa * sx[i];
-    }
-    else /* code for increment not equal to 1 */
-    {
-      nincx = nn * iincx;
-      for (i = 0; i < nincx; i += iincx)
-        sx[i] = ssa * sx[i];
-    }
-  }
-
-  return 0;
-} /* dscal_ */
diff --git a/linear.cpp b/linear.cpp
index 6843833..deb0169 100644
--- a/linear.cpp
+++ b/linear.cpp
@@ -27,6 +27,7 @@ static void print_string_stdout(const char *s)
 	fputs(s,stdout);
 	fflush(stdout);
 }
+static void print_null(const char *s) {}
 
 static void (*liblinear_print_string) (const char *) = &print_string_stdout;
 
@@ -1010,7 +1011,7 @@ static void solve_l2r_l1l2_svr(
 	double d, G, H;
 	double Gmax_old = INF;
 	double Gmax_new, Gnorm1_new;
-	double Gnorm1_init;
+	double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
 	double *beta = new double[l];
 	double *QD = new double[l];
 	double *y = prob->y;
@@ -1409,7 +1410,7 @@ static void solve_l1r_l2_svc(
 	double d, G_loss, G, H;
 	double Gmax_old = INF;
 	double Gmax_new, Gnorm1_new;
-	double Gnorm1_init;
+	double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
 	double d_old, d_diff;
 	double loss_old, loss_new;
 	double appxcond, cond;
@@ -1699,7 +1700,7 @@ static void solve_l1r_lr(
 	double sigma = 0.01;
 	double w_norm, w_norm_new;
 	double z, G, H;
-	double Gnorm1_init;
+	double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
 	double Gmax_old = INF;
 	double Gmax_new, Gnorm1_new;
 	double QP_Gmax_old = INF;
@@ -2051,8 +2052,8 @@ static void transpose(const problem *prob, feature_node **x_space_ret, problem *
 	int i;
 	int l = prob->l;
 	int n = prob->n;
-	long int nnz = 0;
-	long int *col_ptr = new long int [n+1];
+	size_t nnz = 0;
+	size_t *col_ptr = new size_t [n+1];
 	feature_node *x_space;
 	prob_col->l = l;
 	prob_col->n = n;
@@ -2180,14 +2181,18 @@ static void group_classes(const problem *prob, int *nr_class_ret, int **label_re
 
 static void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn)
 {
-	double eps=param->eps;
+	//inner and outer tolerances for TRON
+	double eps = param->eps;
+	double eps_cg = 0.1;
+	if(param->init_sol != NULL)
+		eps_cg = 0.5;
+
 	int pos = 0;
 	int neg = 0;
 	for(int i=0;i<prob->l;i++)
 		if(prob->y[i] > 0)
 			pos++;
 	neg = prob->l - pos;
-
 	double primal_solver_tol = eps*max(min(pos,neg), 1)/prob->l;
 
 	function *fun_obj=NULL;
@@ -2204,7 +2209,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
 					C[i] = Cn;
 			}
 			fun_obj=new l2r_lr_fun(prob, C);
-			TRON tron_obj(fun_obj, primal_solver_tol);
+			TRON tron_obj(fun_obj, primal_solver_tol, eps_cg);
 			tron_obj.set_print_string(liblinear_print_string);
 			tron_obj.tron(w);
 			delete fun_obj;
@@ -2222,7 +2227,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
 					C[i] = Cn;
 			}
 			fun_obj=new l2r_l2_svc_fun(prob, C);
-			TRON tron_obj(fun_obj, primal_solver_tol);
+			TRON tron_obj(fun_obj, primal_solver_tol, eps_cg);
 			tron_obj.set_print_string(liblinear_print_string);
 			tron_obj.tron(w);
 			delete fun_obj;
@@ -2287,6 +2292,36 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
 	}
 }
 
+// Calculate the initial C for parameter selection
+static double calc_start_C(const problem *prob, const parameter *param)
+{
+	int i;
+	double xTx,max_xTx;
+	max_xTx = 0;
+	for(i=0; i<prob->l; i++)
+	{
+		xTx = 0;
+		feature_node *xi=prob->x[i];
+		while(xi->index != -1)
+		{
+			double val = xi->value;
+			xTx += val*val;
+			xi++;
+		}
+		if(xTx > max_xTx)
+			max_xTx = xTx;
+	}
+
+	double min_C = 1.0;
+	if(param->solver_type == L2R_LR)
+		min_C = 1.0 / (prob->l * max_xTx);
+	else if(param->solver_type == L2R_L2LOSS_SVC)
+		min_C = 1.0 / (2 * prob->l * max_xTx);
+
+	return pow( 2, floor(log(min_C) / log(2.0)) );
+}
+
+
 //
 // Interface functions
 //
@@ -2305,14 +2340,14 @@ model* train(const problem *prob, const parameter *param)
 	model_->param = *param;
 	model_->bias = prob->bias;
 
-	if(param->solver_type == L2R_L2LOSS_SVR ||
-	   param->solver_type == L2R_L1LOSS_SVR_DUAL ||
-	   param->solver_type == L2R_L2LOSS_SVR_DUAL)
+	if(check_regression_model(model_))
 	{
 		model_->w = Malloc(double, w_size);
+		for(i=0; i<w_size; i++)
+			model_->w[i] = 0;
 		model_->nr_class = 2;
 		model_->label = NULL;
-		train_one(prob, param, &model_->w[0], 0, 0);
+		train_one(prob, param, model_->w, 0, 0);
 	}
 	else
 	{
@@ -2382,8 +2417,15 @@ model* train(const problem *prob, const parameter *param)
 					sub_prob.y[k] = +1;
 				for(; k<sub_prob.l; k++)
 					sub_prob.y[k] = -1;
+				
+				if(param->init_sol != NULL)
+					for(i=0;i<w_size;i++)
+						model_->w[i] = param->init_sol[i];
+				else
+					for(i=0;i<w_size;i++)
+						model_->w[i] = 0;
 
-				train_one(&sub_prob, param, &model_->w[0], weighted_C[0], weighted_C[1]);
+				train_one(&sub_prob, param, model_->w, weighted_C[0], weighted_C[1]);
 			}
 			else
 			{
@@ -2402,6 +2444,13 @@ model* train(const problem *prob, const parameter *param)
 					for(; k<sub_prob.l; k++)
 						sub_prob.y[k] = -1;
 
+					if(param->init_sol != NULL)
+						for(j=0;j<w_size;j++)
+							w[j] = param->init_sol[j*nr_class+i];
+					else
+						for(j=0;j<w_size;j++)
+							w[j] = 0;
+
 					train_one(&sub_prob, param, w, weighted_C[i], param->C);
 
 					for(int j=0;j<w_size;j++)
@@ -2482,6 +2531,158 @@ void cross_validation(const problem *prob, const parameter *param, int nr_fold,
 	free(perm);
 }
 
+void find_parameter_C(const problem *prob, const parameter *param, int nr_fold, double start_C, double max_C, double *best_C, double *best_rate)
+{
+	// variables for CV
+	int i;
+	int *fold_start;
+	int l = prob->l;
+	int *perm = Malloc(int, l);
+	double *target = Malloc(double, prob->l);
+	struct problem *subprob = Malloc(problem,nr_fold);
+
+	// variables for warm start
+	double ratio = 2;
+	double **prev_w = Malloc(double*, nr_fold);
+	for(i = 0; i < nr_fold; i++)
+		prev_w[i] = NULL;
+	int num_unchanged_w = 0;
+	struct parameter param1 = *param;
+	void (*default_print_string) (const char *) = liblinear_print_string;
+
+	if (nr_fold > l)
+	{
+		nr_fold = l;
+		fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
+	}
+	fold_start = Malloc(int,nr_fold+1);
+	for(i=0;i<l;i++) perm[i]=i;
+	for(i=0;i<l;i++)
+	{
+		int j = i+rand()%(l-i);
+		swap(perm[i],perm[j]);
+	}
+	for(i=0;i<=nr_fold;i++)
+		fold_start[i]=i*l/nr_fold;
+
+	for(i=0;i<nr_fold;i++)
+	{
+		int begin = fold_start[i];
+		int end = fold_start[i+1];
+		int j,k;
+
+		subprob[i].bias = prob->bias;
+		subprob[i].n = prob->n;
+		subprob[i].l = l-(end-begin);
+		subprob[i].x = Malloc(struct feature_node*,subprob[i].l);
+		subprob[i].y = Malloc(double,subprob[i].l);
+
+		k=0;
+		for(j=0;j<begin;j++)
+		{
+			subprob[i].x[k] = prob->x[perm[j]];
+			subprob[i].y[k] = prob->y[perm[j]];
+			++k;
+		}
+		for(j=end;j<l;j++)
+		{
+			subprob[i].x[k] = prob->x[perm[j]];
+			subprob[i].y[k] = prob->y[perm[j]];
+			++k;
+		}
+
+	}
+
+	*best_rate = 0;
+	if(start_C <= 0)
+		start_C = calc_start_C(prob,param);
+	param1.C = start_C;
+
+	while(param1.C <= max_C)
+	{
+		//Output diabled for running CV at a particular C
+		set_print_string_function(&print_null);
+
+		for(i=0; i<nr_fold; i++)
+		{
+			int j;
+			int begin = fold_start[i];
+			int end = fold_start[i+1];
+
+			param1.init_sol = prev_w[i];
+			struct model *submodel = train(&subprob[i],&param1);
+
+			int total_w_size;
+			if(submodel->nr_class == 2)
+				total_w_size = subprob[i].n;
+			else
+				total_w_size = subprob[i].n * submodel->nr_class;
+
+			if(prev_w[i] == NULL)
+			{
+				prev_w[i] = Malloc(double, total_w_size);
+				for(j=0; j<total_w_size; j++)
+					prev_w[i][j] = submodel->w[j];
+			}
+			else if(num_unchanged_w >= 0)
+			{
+				double norm_w_diff = 0;
+				for(j=0; j<total_w_size; j++)
+				{
+					norm_w_diff += (submodel->w[j] - prev_w[i][j])*(submodel->w[j] - prev_w[i][j]);
+					prev_w[i][j] = submodel->w[j];
+				}
+				norm_w_diff = sqrt(norm_w_diff);
+
+				if(norm_w_diff > 1e-15)
+					num_unchanged_w = -1;
+			}
+			else
+			{
+				for(j=0; j<total_w_size; j++)
+					prev_w[i][j] = submodel->w[j];
+			}
+
+			for(j=begin; j<end; j++)
+				target[perm[j]] = predict(submodel,prob->x[perm[j]]);
+
+			free_and_destroy_model(&submodel);
+		}
+		set_print_string_function(default_print_string);
+
+		int total_correct = 0;
+		for(i=0; i<prob->l; i++)
+			if(target[i] == prob->y[i])
+				++total_correct;
+		double current_rate = (double)total_correct/prob->l;
+		if(current_rate > *best_rate)
+		{
+			*best_C = param1.C;
+			*best_rate = current_rate;
+		}
+
+		info("log2c=%7.2f\trate=%g\n",log(param1.C)/log(2.0),100.0*current_rate);
+		num_unchanged_w++;
+		if(num_unchanged_w == 3)
+			break;
+		param1.C = param1.C*ratio;
+	}
+
+	if(param1.C > max_C && max_C > start_C) 
+		info("warning: maximum C reached.\n");
+	free(fold_start);
+	free(perm);
+	free(target);
+	for(i=0; i<nr_fold; i++)
+	{
+		free(subprob[i].x);
+		free(subprob[i].y);
+		free(prev_w[i]);
+	}
+	free(prev_w);
+	free(subprob);
+}
+
 double predict_values(const struct model *model_, const struct feature_node *x, double *dec_values)
 {
 	int idx;
@@ -2512,9 +2713,7 @@ double predict_values(const struct model *model_, const struct feature_node *x,
 
 	if(nr_class==2)
 	{
-		if(model_->param.solver_type == L2R_L2LOSS_SVR ||
-		   model_->param.solver_type == L2R_L1LOSS_SVR_DUAL ||
-		   model_->param.solver_type == L2R_L2LOSS_SVR_DUAL)
+		if(check_regression_model(model_))
 			return dec_values[0];
 		else
 			return (dec_values[0]>0)?model_->label[0]:model_->label[1];
@@ -2596,7 +2795,11 @@ int save_model(const char *model_file_name, const struct model *model_)
 	FILE *fp = fopen(model_file_name,"w");
 	if(fp==NULL) return -1;
 
-	char *old_locale = strdup(setlocale(LC_ALL, NULL));
+	char *old_locale = setlocale(LC_ALL, NULL);
+	if (old_locale)
+	{
+		old_locale = strdup(old_locale);
+	}
 	setlocale(LC_ALL, "C");
 
 	int nr_w;
@@ -2651,7 +2854,11 @@ struct model *load_model(const char *model_file_name)
 
 	model_->label = NULL;
 
-	char *old_locale = strdup(setlocale(LC_ALL, NULL));
+	char *old_locale = setlocale(LC_ALL, NULL);
+	if (old_locale)
+	{
+		old_locale = strdup(old_locale);
+	}
 	setlocale(LC_ALL, "C");
 
 	char cmd[81];
@@ -2764,6 +2971,53 @@ void get_labels(const model *model_, int* label)
 			label[i] = model_->label[i];
 }
 
+// use inline here for better performance (around 20% faster than the non-inline one)
+static inline double get_w_value(const struct model *model_, int idx, int label_idx) 
+{
+	int nr_class = model_->nr_class;
+	int solver_type = model_->param.solver_type;
+	const double *w = model_->w;
+
+	if(idx < 0 || idx > model_->nr_feature)
+		return 0;
+	if(check_regression_model(model_))
+		return w[idx];
+	else 
+	{
+		if(label_idx < 0 || label_idx >= nr_class)
+			return 0;
+		if(nr_class == 2 && solver_type != MCSVM_CS)
+		{
+			if(label_idx == 0)
+				return w[idx];
+			else
+				return -w[idx];
+		}
+		else
+			return w[idx*nr_class+label_idx];
+	}
+}
+
+// feat_idx: starting from 1 to nr_feature
+// label_idx: starting from 0 to nr_class-1 for classification models;
+//            for regression models, label_idx is ignored.
+double get_decfun_coef(const struct model *model_, int feat_idx, int label_idx)
+{
+	if(feat_idx > model_->nr_feature)
+		return 0;
+	return get_w_value(model_, feat_idx-1, label_idx);
+}
+
+double get_decfun_bias(const struct model *model_, int label_idx)
+{
+	int bias_idx = model_->nr_feature;
+	double bias = model_->bias;
+	if(bias <= 0)
+		return 0;
+	else
+		return bias*get_w_value(model_, bias_idx, label_idx);
+}
+
 void free_model_content(struct model *model_ptr)
 {
 	if(model_ptr->w != NULL)
@@ -2788,6 +3042,8 @@ void destroy_param(parameter* param)
 		free(param->weight_label);
 	if(param->weight != NULL)
 		free(param->weight);
+	if(param->init_sol != NULL)
+		free(param->init_sol);
 }
 
 const char *check_parameter(const problem *prob, const parameter *param)
@@ -2814,6 +3070,10 @@ const char *check_parameter(const problem *prob, const parameter *param)
 		&& param->solver_type != L2R_L1LOSS_SVR_DUAL)
 		return "unknown solver type";
 
+	if(param->init_sol != NULL 
+		&& param->solver_type != L2R_LR && param->solver_type != L2R_L2LOSS_SVC)
+		return "Initial-solution specification supported only for solver L2R_LR and L2R_L2LOSS_SVC";
+
 	return NULL;
 }
 
@@ -2824,6 +3084,13 @@ int check_probability_model(const struct model *model_)
 			model_->param.solver_type==L1R_LR);
 }
 
+int check_regression_model(const struct model *model_)
+{
+	return (model_->param.solver_type==L2R_L2LOSS_SVR ||
+			model_->param.solver_type==L2R_L1LOSS_SVR_DUAL ||
+			model_->param.solver_type==L2R_L2LOSS_SVR_DUAL);
+}
+
 void set_print_string_function(void (*print_func)(const char*))
 {
 	if (print_func == NULL)
diff --git a/linear.def b/linear.def
index 2425996..96e2620 100644
--- a/linear.def
+++ b/linear.def
@@ -16,3 +16,6 @@ EXPORTS
 	check_parameter	@14
 	check_probability_model	@15
 	set_print_string_function	@16
+    get_decfun_coef @17
+    get_decfun_bias @18
+    check_regression_model  @19
diff --git a/linear.h b/linear.h
index 22a3567..bc6aaf8 100644
--- a/linear.h
+++ b/linear.h
@@ -32,6 +32,7 @@ struct parameter
 	int *weight_label;
 	double* weight;
 	double p;
+	double *init_sol;
 };
 
 struct model
@@ -46,6 +47,7 @@ struct model
 
 struct model* train(const struct problem *prob, const struct parameter *param);
 void cross_validation(const struct problem *prob, const struct parameter *param, int nr_fold, double *target);
+void find_parameter_C(const struct problem *prob, const struct parameter *param, int nr_fold, double start_C, double max_C, double *best_C, double *best_rate);
 
 double predict_values(const struct model *model_, const struct feature_node *x, double* dec_values);
 double predict(const struct model *model_, const struct feature_node *x);
@@ -57,6 +59,8 @@ struct model *load_model(const char *model_file_name);
 int get_nr_feature(const struct model *model_);
 int get_nr_class(const struct model *model_);
 void get_labels(const struct model *model_, int* label);
+double get_decfun_coef(const struct model *model_, int feat_idx, int label_idx);
+double get_decfun_bias(const struct model *model_, int label_idx);
 
 void free_model_content(struct model *model_ptr);
 void free_and_destroy_model(struct model **model_ptr_ptr);
@@ -64,6 +68,7 @@ void destroy_param(struct parameter *param);
 
 const char *check_parameter(const struct problem *prob, const struct parameter *param);
 int check_probability_model(const struct model *model);
+int check_regression_model(const struct model *model);
 void set_print_string_function(void (*print_func) (const char*));
 
 #ifdef __cplusplus
diff --git a/matlab/Makefile b/matlab/Makefile
index f05fab4..e0db5f6 100644
--- a/matlab/Makefile
+++ b/matlab/Makefile
@@ -7,33 +7,24 @@ CC ?= gcc
 CFLAGS = -Wall -Wconversion -O3 -fPIC -I$(MATLABDIR)/extern/include -I..
 
 MEX = $(MATLABDIR)/bin/mex
-MEX_OPTION = CC\#$(CXX) CXX\#$(CXX) CFLAGS\#"$(CFLAGS)" CXXFLAGS\#"$(CFLAGS)"
+MEX_OPTION = CC="$(CXX)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CFLAGS)"
 # comment the following line if you use MATLAB on a 32-bit computer
 MEX_OPTION += -largeArrayDims
 MEX_EXT = $(shell $(MATLABDIR)/bin/mexext)
 
-OCTAVEDIR ?= /usr/include/octave
-OCTAVE_MEX = env CC=$(CXX) mkoctfile
-OCTAVE_MEX_OPTION = --mex
-OCTAVE_MEX_EXT = mex
-OCTAVE_CFLAGS = -Wall -O3 -fPIC -I$(OCTAVEDIR) -I..
-
 all:	matlab
 
 matlab:	binary
 
 octave:
-	@make MEX="$(OCTAVE_MEX)" MEX_OPTION="$(OCTAVE_MEX_OPTION)" \
-	MEX_EXT="$(OCTAVE_MEX_EXT)" CFLAGS="$(OCTAVE_CFLAGS)" \
-	binary
-
+	@echo "please type make under Octave"
 binary: train.$(MEX_EXT) predict.$(MEX_EXT) libsvmread.$(MEX_EXT) libsvmwrite.$(MEX_EXT)
 
-train.$(MEX_EXT): train.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
-	$(MEX) $(MEX_OPTION) train.c ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
+train.$(MEX_EXT): train.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o
+	$(MEX) $(MEX_OPTION) train.c ../tron.o ../linear.o linear_model_matlab.o
 
-predict.$(MEX_EXT): predict.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
-	$(MEX) $(MEX_OPTION) predict.c ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
+predict.$(MEX_EXT): predict.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o
+	$(MEX) $(MEX_OPTION) predict.c ../tron.o ../linear.o linear_model_matlab.o
 
 libsvmread.$(MEX_EXT):	libsvmread.c
 	$(MEX) $(MEX_OPTION) libsvmread.c
@@ -50,9 +41,5 @@ linear_model_matlab.o: linear_model_matlab.c ../linear.h
 ../tron.o: ../tron.cpp ../tron.h 
 	make -C .. tron.o
 
-../blas/blas.a: ../blas/*.c ../blas/*.h
-	make -C ../blas OPTFLAGS='$(CFLAGS)' CC='$(CC)';
-
 clean:
-	make -C ../blas clean
 	rm -f *~ *.o *.mex* *.obj ../linear.o ../tron.o
diff --git a/matlab/README b/matlab/README
index 00e1358..f53f435 100644
--- a/matlab/README
+++ b/matlab/README
@@ -117,7 +117,7 @@ The 'train' function returns a model which can be used for future
 prediction.  It is a structure and is organized as [Parameters, nr_class,
 nr_feature, bias, Label, w]:
 
-        -Parameters: Parameters
+        -Parameters: Parameters (now only solver type is provided)
         -nr_class: number of classes; = 2 for regression
         -nr_feature: number of features in training data (without including the bias term)
         -bias: If >= 0, we assume one additional feature is added to the end
@@ -131,7 +131,12 @@ nr_feature, bias, Label, w]:
 
 If the '-v' option is specified, cross validation is conducted and the
 returned model is just a scalar: cross-validation accuracy for 
-classification and mean-squared error for regression.
+classification and mean-squared error for regression. If the '-C' option
+is specified, the best parameter C is found by cross validation. The 
+returned model is a two dimensional vector, where the first value is 
+the best C and the second value is the corresponding cross-validation 
+accuracy. The parameter selection utility is supported by only -s 0
+and -s 2.
 
 Result of Prediction
 ====================
@@ -184,6 +189,11 @@ For probability estimates, you need '-b 1' only in the testing phase:
 
 matlab> [predict_label, accuracy, prob_estimates] = predict(heart_scale_label, heart_scale_inst, model, '-b 1');
 
+Use the best parameter to train (only supported by -s 0 and -s 2):
+
+matlab> best = train(heart_scale_label, heart_scale_inst, '-C -s 0');
+matlab> model = train(heart_scale_label, heart_scale_inst, sprintf('-c %f -s 0', best(1))); % use the same solver: -s 0 
+
 Additional Information
 ======================
 
diff --git a/matlab/libsvmread.c b/matlab/libsvmread.c
index a6365d1..d2fe0f5 100644
--- a/matlab/libsvmread.c
+++ b/matlab/libsvmread.c
@@ -56,14 +56,13 @@ static char* readline(FILE *input)
 // read in a problem (in libsvm format)
 void read_problem(const char *filename, int nlhs, mxArray *plhs[])
 {
-	int max_index, min_index, inst_max_index, i;
-	long elements, k;
+	int max_index, min_index, inst_max_index;
+	size_t elements, k, i, l=0;
 	FILE *fp = fopen(filename,"r");
-	int l = 0;
 	char *endptr;
 	mwIndex *ir, *jc;
 	double *labels, *samples;
-	
+
 	if(fp == NULL)
 	{
 		mexPrintf("can't open input file %s\n",filename);
diff --git a/matlab/libsvmwrite.c b/matlab/libsvmwrite.c
index d7fae76..9c93fd3 100644
--- a/matlab/libsvmwrite.c
+++ b/matlab/libsvmwrite.c
@@ -26,9 +26,8 @@ static void fake_answer(int nlhs, mxArray *plhs[])
 void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *instance_mat)
 {
 	FILE *fp = fopen(filename,"w");
-	int i, k, low, high, l;
-	mwIndex *ir, *jc;
-	int label_vector_row_num;
+	mwIndex *ir, *jc, k, low, high;
+	size_t i, l, label_vector_row_num;
 	double *samples, *labels;
 	mxArray *instance_mat_col; // instance sparse matrix in column format
 
@@ -52,8 +51,8 @@ void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *
 	}
 
 	// the number of instance
-	l = (int) mxGetN(instance_mat_col);
-	label_vector_row_num = (int) mxGetM(label_vec);
+	l = mxGetN(instance_mat_col);
+	label_vector_row_num = mxGetM(label_vec);
 
 	if(label_vector_row_num!=l)
 	{
@@ -71,9 +70,9 @@ void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *
 	{
 		fprintf(fp,"%g", labels[i]);
 
-		low = (int) jc[i], high = (int) jc[i+1];
+		low = jc[i], high = jc[i+1];
 		for(k=low;k<high;k++)
-			fprintf(fp," %ld:%g", ir[k]+1, samples[k]);		
+			fprintf(fp," %lu:%g", (size_t)ir[k]+1, samples[k]);		
 
 		fprintf(fp,"\n");
 	}
diff --git a/matlab/linear_model_matlab.c b/matlab/linear_model_matlab.c
index 7b5129e..f11b451 100644
--- a/matlab/linear_model_matlab.c
+++ b/matlab/linear_model_matlab.c
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 #include <string.h>
-#include "../linear.h"
+#include "linear.h"
 
 #include "mex.h"
 
@@ -145,7 +145,7 @@ const char *matlab_matrix_to_model(struct model *model_, const mxArray *matlab_s
 
 	// bias
 	ptr = mxGetPr(rhs[id]);
-	model_->bias = (int)ptr[0];
+	model_->bias = ptr[0];
 	id++;
 
 	if(model_->bias>=0)
diff --git a/matlab/make.m b/matlab/make.m
index 3a01890..7e14eb4 100644
--- a/matlab/make.m
+++ b/matlab/make.m
@@ -1,21 +1,20 @@
-% This make.m is for MATLAB and OCTAVE under Windows, Mac, and Unix
-
-try
-	Type = ver;
-	% This part is for OCTAVE
-	if(strcmp(Type(1).Name, 'Octave') == 1)
-		mex libsvmread.c
-		mex libsvmwrite.c
-		mex train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/*.c
-		mex predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/*.c
-	% This part is for MATLAB
-	% Add -largeArrayDims on 64-bit machines of MATLAB
-	else
-		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmread.c
-		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmwrite.c
-		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims train.c linear_model_matlab.c ../linear.cpp ../tron.cpp "../blas/*.c"
-		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp "../blas/*.c"
-	end
-catch
-	fprintf('If make.m fails, please check README about detailed instructions.\n');
-end
+% This make.m is for MATLAB and OCTAVE under Windows, Mac, and Unix
+
+try
+	% This part is for OCTAVE
+	if(exist('OCTAVE_VERSION', 'builtin'))
+		mex libsvmread.c
+		mex libsvmwrite.c
+		mex -I.. train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+		mex -I.. predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+	% This part is for MATLAB
+	% Add -largeArrayDims on 64-bit machines of MATLAB
+	else
+		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmread.c
+		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmwrite.c
+		mex CFLAGS="\$CFLAGS -std=c99" -I.. -largeArrayDims train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+		mex CFLAGS="\$CFLAGS -std=c99" -I.. -largeArrayDims predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+	end
+catch
+	fprintf('If make.m fails, please check README about detailed instructions.\n');
+end
diff --git a/matlab/predict.c b/matlab/predict.c
index 36c6046..e0ee5bd 100644
--- a/matlab/predict.c
+++ b/matlab/predict.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "../linear.h"
+#include "linear.h"
 
 #include "mex.h"
 #include "linear_model_matlab.h"
@@ -23,8 +23,8 @@ int col_format_flag;
 
 void read_sparse_instance(const mxArray *prhs, int index, struct feature_node *x, int feature_number, double bias)
 {
-	int i, j, low, high;
-	mwIndex *ir, *jc;
+	int j;
+	mwIndex *ir, *jc, low, high, i;
 	double *samples;
 
 	ir = mxGetIr(prhs);
@@ -33,7 +33,7 @@ void read_sparse_instance(const mxArray *prhs, int index, struct feature_node *x
 
 	// each column is one instance
 	j = 0;
-	low = (int) jc[index], high = (int) jc[index+1];
+	low = jc[index], high = jc[index+1];
 	for(i=low; i<high && (int) (ir[i])<feature_number; i++)
 	{
 		x[j].index = (int) ir[i]+1;
@@ -176,9 +176,7 @@ void do_predict(int nlhs, mxArray *plhs[], const mxArray *prhs[], struct model *
 		++total;
 	}
 
-	if(model_->param.solver_type==L2R_L2LOSS_SVR ||
-	   model_->param.solver_type==L2R_L1LOSS_SVR_DUAL ||
-	   model_->param.solver_type==L2R_L2LOSS_SVR_DUAL)
+	if(check_regression_model(model_))
 	{
 		info("Mean squared error = %g (regression)\n",error/total);
 		info("Squared correlation coefficient = %g (regression)\n",
diff --git a/matlab/train.c b/matlab/train.c
index 1301ed5..5c3ef4a 100644
--- a/matlab/train.c
+++ b/matlab/train.c
@@ -1,9 +1,8 @@
-#include <stdio.h>
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include "../linear.h"
+#include "linear.h"
 
 #include "mex.h"
 #include "linear_model_matlab.h"
@@ -60,6 +59,7 @@ void exit_with_help()
 	"-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)\n"
 	"-wi weight: weights adjust the parameter C of different classes (see README for details)\n"
 	"-v n: n-fold cross validation mode\n"
+	"-C : find parameter C (only for -s 0 and 2)\n"
 	"-q : quiet mode (no outputs)\n"
 	"col:\n"
 	"	if 'col' is setted, training_instance_matrix is parsed in column format, otherwise is in row format\n"
@@ -71,11 +71,28 @@ struct parameter param;		// set by parse_command_line
 struct problem prob;		// set by read_problem
 struct model *model_;
 struct feature_node *x_space;
-int cross_validation_flag;
+int flag_cross_validation;
+int flag_find_C;
+int flag_C_specified;
+int flag_solver_specified;
 int col_format_flag;
 int nr_fold;
 double bias;
 
+
+void do_find_parameter_C(double *best_C, double *best_rate)
+{
+	double start_C;
+	double max_C = 1024;
+	if (flag_C_specified)
+		start_C = param.C;
+	else
+		start_C = -1.0;
+	find_parameter_C(&prob, &param, nr_fold, start_C, max_C, best_C, best_rate);
+	mexPrintf("Best C = %lf  CV accuracy = %g%%\n", *best_C, 100.0**best_rate);	
+}
+
+
 double do_cross_validation()
 {
 	int i;
@@ -101,8 +118,8 @@ double do_cross_validation()
                         sumyy += y*y;
                         sumvy += v*y;
                 }
-                printf("Cross Validation Mean squared error = %g\n",total_error/prob.l);
-                printf("Cross Validation Squared correlation coefficient = %g\n",
+                mexPrintf("Cross Validation Mean squared error = %g\n",total_error/prob.l);
+                mexPrintf("Cross Validation Squared correlation coefficient = %g\n",
                         ((prob.l*sumvy-sumv*sumy)*(prob.l*sumvy-sumv*sumy))/
                         ((prob.l*sumvv-sumv*sumv)*(prob.l*sumyy-sumy*sumy))
                         );
@@ -113,7 +130,7 @@ double do_cross_validation()
 		for(i=0;i<prob.l;i++)
 			if(target[i] == prob.y[i])
 				++total_correct;
-		printf("Cross Validation Accuracy = %g%%\n",100.0*total_correct/prob.l);
+		mexPrintf("Cross Validation Accuracy = %g%%\n",100.0*total_correct/prob.l);
 		retval = 100.0*total_correct/prob.l;
 	}
 
@@ -137,8 +154,12 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
 	param.nr_weight = 0;
 	param.weight_label = NULL;
 	param.weight = NULL;
-	cross_validation_flag = 0;
+	param.init_sol = NULL;
+	flag_cross_validation = 0;
 	col_format_flag = 0;
+	flag_C_specified = 0;
+	flag_solver_specified = 0;
+	flag_find_C = 0;
 	bias = -1;
 
 
@@ -166,15 +187,17 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
 	{
 		if(argv[i][0] != '-') break;
 		++i;
-		if(i>=argc && argv[i-1][1] != 'q') // since option -q has no parameter
+		if(i>=argc && argv[i-1][1] != 'q' && argv[i-1][1] != 'C') // since options -q and -C have no parameter
 			return 1;
 		switch(argv[i-1][1])
 		{
 			case 's':
 				param.solver_type = atoi(argv[i]);
+				flag_solver_specified = 1;
 				break;
 			case 'c':
 				param.C = atof(argv[i]);
+				flag_C_specified = 1;
 				break;
 			case 'p':
 				param.p = atof(argv[i]);
@@ -186,7 +209,7 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
 				bias = atof(argv[i]);
 				break;
 			case 'v':
-				cross_validation_flag = 1;
+				flag_cross_validation = 1;
 				nr_fold = atoi(argv[i]);
 				if(nr_fold < 2)
 				{
@@ -205,6 +228,10 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
 				print_func = &print_null;
 				i--;
 				break;
+			case 'C':
+				flag_find_C = 1;
+				i--;
+				break;
 			default:
 				mexPrintf("unknown option\n");
 				return 1;
@@ -213,6 +240,23 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
 
 	set_print_string_function(print_func);
 
+	// default solver for parameter selection is L2R_L2LOSS_SVC
+	if(flag_find_C)
+	{
+		if(!flag_cross_validation)
+			nr_fold = 5;
+		if(!flag_solver_specified)
+		{
+			mexPrintf("Solver not specified. Using -s 2\n");
+			param.solver_type = L2R_L2LOSS_SVC;
+		}
+		else if(param.solver_type != L2R_LR && param.solver_type != L2R_L2LOSS_SVC)
+		{
+			mexPrintf("Warm-start parameter search only available for -s 0 and -s 2\n");
+			return 1;
+		}
+	}
+
 	if(param.eps == INF)
 	{
 		switch(param.solver_type)
@@ -252,9 +296,10 @@ static void fake_answer(int nlhs, mxArray *plhs[])
 
 int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
 {
-	int i, j, k, low, high;
-	mwIndex *ir, *jc;
-	int elements, max_index, num_samples, label_vector_row_num;
+	mwIndex *ir, *jc, low, high, k;
+	// using size_t due to the output type of matlab functions
+	size_t i, j, l, elements, max_index, label_vector_row_num;
+	mwSize num_samples;
 	double *samples, *labels;
 	mxArray *instance_mat_col; // instance sparse matrix in column format
 
@@ -279,10 +324,11 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
 	}
 
 	// the number of instance
-	prob.l = (int) mxGetN(instance_mat_col);
-	label_vector_row_num = (int) mxGetM(label_vec);
+	l = mxGetN(instance_mat_col);
+	label_vector_row_num = mxGetM(label_vec);
+	prob.l = (int) l;
 
-	if(label_vector_row_num!=prob.l)
+	if(label_vector_row_num!=l)
 	{
 		mexPrintf("Length of label vector does not match # of instances.\n");
 		return -1;
@@ -294,23 +340,23 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
 	ir = mxGetIr(instance_mat_col);
 	jc = mxGetJc(instance_mat_col);
 
-	num_samples = (int) mxGetNzmax(instance_mat_col);
+	num_samples = mxGetNzmax(instance_mat_col);
 
-	elements = num_samples + prob.l*2;
-	max_index = (int) mxGetM(instance_mat_col);
+	elements = num_samples + l*2;
+	max_index = mxGetM(instance_mat_col);
 
-	prob.y = Malloc(double, prob.l);
-	prob.x = Malloc(struct feature_node*, prob.l);
+	prob.y = Malloc(double, l);
+	prob.x = Malloc(struct feature_node*, l);
 	x_space = Malloc(struct feature_node, elements);
 
 	prob.bias=bias;
 
 	j = 0;
-	for(i=0;i<prob.l;i++)
+	for(i=0;i<l;i++)
 	{
 		prob.x[i] = &x_space[j];
 		prob.y[i] = labels[i];
-		low = (int) jc[i], high = (int) jc[i+1];
+		low = jc[i], high = jc[i+1];
 		for(k=low;k<high;k++)
 		{
 			x_space[j].index = (int) ir[k]+1;
@@ -319,7 +365,7 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
 	 	}
 		if(prob.bias>=0)
 		{
-			x_space[j].index = max_index+1;
+			x_space[j].index = (int) max_index+1;
 			x_space[j].value = prob.bias;
 			j++;
 		}
@@ -327,9 +373,9 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
 	}
 
 	if(prob.bias>=0)
-		prob.n = max_index+1;
+		prob.n = (int) max_index+1;
 	else
-		prob.n = max_index;
+		prob.n = (int) max_index;
 
 	return 0;
 }
@@ -356,12 +402,20 @@ void mexFunction( int nlhs, mxArray *plhs[],
 	{
 		int err=0;
 
-		if(!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1])) {
+		if(!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]))
+		{
 			mexPrintf("Error: label vector and instance matrix must be double\n");
 			fake_answer(nlhs, plhs);
 			return;
 		}
 
+		if(mxIsSparse(prhs[0]))
+		{
+			mexPrintf("Error: label vector should not be in sparse format");
+			fake_answer(nlhs, plhs);
+			return;
+		}
+
 		if(parse_command_line(nrhs, prhs, NULL))
 		{
 			exit_with_help();
@@ -396,7 +450,18 @@ void mexFunction( int nlhs, mxArray *plhs[],
 			return;
 		}
 
-		if(cross_validation_flag)
+		if (flag_find_C)
+		{
+			double best_C, best_rate, *ptr;
+			
+			do_find_parameter_C(&best_C, &best_rate);	
+			
+			plhs[0] = mxCreateDoubleMatrix(2, 1, mxREAL);
+			ptr = mxGetPr(plhs[0]);
+			ptr[0] = best_C;
+			ptr[1] = best_rate;
+		}
+		else if(flag_cross_validation)
 		{
 			double *ptr;
 			plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
diff --git a/predict.c b/predict.c
index c5b3f1d..a043181 100644
--- a/predict.c
+++ b/predict.c
@@ -158,9 +158,7 @@ void do_predict(FILE *input, FILE *output)
 		sumpt += predict_label*target_label;
 		++total;
 	}
-	if(model_->param.solver_type==L2R_L2LOSS_SVR ||
-	   model_->param.solver_type==L2R_L1LOSS_SVR_DUAL ||
-	   model_->param.solver_type==L2R_L2LOSS_SVR_DUAL)
+	if(check_regression_model(model_))
 	{
 		info("Mean squared error = %g (regression)\n",error/total);
 		info("Squared correlation coefficient = %g (regression)\n",
diff --git a/python/README b/python/README
index e12b298..47e0b4a 100644
--- a/python/README
+++ b/python/README
@@ -205,6 +205,36 @@ LIBLINEAR shared library:
     >>> nr_class = model_.get_nr_class()
     >>> class_labels = model_.get_labels()
     >>> is_prob_model = model_.is_probability_model()
+    >>> is_regression_model = model_.is_regression_model()
+
+    The decision function is W*x + b, where
+        W is an nr_class-by-nr_feature matrix, and
+        b is a vector of size nr_class.
+    To access W_kj (i.e., coefficient for the k-th class and the j-th feature)
+    and b_k (i.e., bias for the k-th class), use the following functions.
+
+    >>> W_kj = model_.get_decfun_coef(feat_idx=j, label_idx=k)
+    >>> b_k = model_.get_decfun_bias(label_idx=k)
+
+    We also provide a function to extract w_k (i.e., the k-th row of W) and
+    b_k directly as follows.
+
+    >>> [w_k, b_k] = model_.get_decfun(label_idx=k)
+
+    Note that w_k is a Python list of length nr_feature, which means that
+        w_k[0] = W_k1.
+    For regression models, W is just a vector of length nr_feature. Either
+	set label_idx=0 or omit the label_idx parameter to access the coefficients.
+
+    >>> W_j = model_.get_decfun_coef(feat_idx=j)
+    >>> b = model_.get_decfun_bias()
+    >>> [W, b] = model_.get_decfun()
+
+    Note that in get_decfun_coef, get_decfun_bias, and get_decfun, feat_idx
+    starts from 1, while label_idx starts from 0. If label_idx is not in the
+    valid range (0 to nr_class-1), then a NaN will be returned; and if feat_idx
+    is not in the valid range (1 to nr_feature), then a zero value will be
+    returned. For regression models, label_idx is ignored.
 
 Utility Functions
 =================
@@ -247,6 +277,11 @@ The above command loads
            structure. If '-v' is specified, cross validation is
            conducted and the returned model is just a scalar: cross-validation
            accuracy for classification and mean-squared error for regression.
+           If the '-C' option is specified, the best parameter C is found 
+	   by cross validation. The returned model is a tuple of the best C 
+	   and the corresponding cross-validation accuracy. The parameter 
+	   selection utility is supported by only -s 0 and -s 2.
+
 
     To train the same data many times with different
     parameters, the second and the third ways should be faster..
@@ -260,6 +295,8 @@ The above command loads
     >>> m = train(prob, '-w1 5 -c 5')
     >>> m = train(prob, param)
     >>> CV_ACC = train(y, x, '-v 3')
+    >>> best_C, best_rate = train(y, x, '-C -s 0')
+    >>> m = train(y, x, '-c {0} -s 0'.format(best_C)) # use the same solver: -s 0
 
 - Function: predict
 
diff --git a/python/liblinear.py b/python/liblinear.py
index a207c49..d650062 100644
--- a/python/liblinear.py
+++ b/python/liblinear.py
@@ -5,12 +5,18 @@ from ctypes.util import find_library
 from os import path
 import sys
 
+__all__ = ['liblinear', 'feature_node', 'gen_feature_nodearray', 'problem',
+           'parameter', 'model', 'toPyModel', 'L2R_LR', 'L2R_L2LOSS_SVC_DUAL',
+           'L2R_L2LOSS_SVC', 'L2R_L1LOSS_SVC_DUAL', 'MCSVM_CS', 
+           'L1R_L2LOSS_SVC', 'L1R_LR', 'L2R_LR_DUAL', 'L2R_L2LOSS_SVR', 
+           'L2R_L2LOSS_SVR_DUAL', 'L2R_L1LOSS_SVR_DUAL', 'print_null']
+
 try:
 	dirname = path.dirname(path.abspath(__file__))
 	if sys.platform == 'win32':
 		liblinear = CDLL(path.join(dirname, r'..\windows\liblinear.dll'))
 	else:
-		liblinear = CDLL(path.join(dirname, '../liblinear.so.1'))
+		liblinear = CDLL(path.join(dirname, '../liblinear.so.3'))
 except:
 # For unix the prefix 'lib' is not considered.
 	if find_library('linear'):
@@ -20,13 +26,17 @@ except:
 	else:
 		raise Exception('LIBLINEAR library not found.')
 
-# Construct constants
-SOLVER_TYPE = ['L2R_LR', 'L2R_L2LOSS_SVC_DUAL', 'L2R_L2LOSS_SVC', 'L2R_L1LOSS_SVC_DUAL',\
-		'MCSVM_CS', 'L1R_L2LOSS_SVC', 'L1R_LR', 'L2R_LR_DUAL', \
-		None, None, None, \
-		'L2R_L2LOSS_SVR', 'L2R_L2LOSS_SVR_DUAL', 'L2R_L1LOSS_SVR_DUAL']
-for i, s in enumerate(SOLVER_TYPE): 
-	if s is not None: exec("%s = %d" % (s , i))
+L2R_LR = 0
+L2R_L2LOSS_SVC_DUAL = 1 
+L2R_L2LOSS_SVC = 2 
+L2R_L1LOSS_SVC_DUAL = 3
+MCSVM_CS = 4 
+L1R_L2LOSS_SVC = 5 
+L1R_LR = 6 
+L2R_LR_DUAL = 7  
+L2R_L2LOSS_SVR = 11
+L2R_L2LOSS_SVR_DUAL = 12
+L2R_L1LOSS_SVR_DUAL = 13
 
 PRINT_STRING_FUN = CFUNCTYPE(None, c_char_p)
 def print_null(s): 
@@ -117,8 +127,8 @@ class problem(Structure):
 
 
 class parameter(Structure):
-	_names = ["solver_type", "eps", "C", "nr_weight", "weight_label", "weight", "p"]
-	_types = [c_int, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double), c_double]
+	_names = ["solver_type", "eps", "C", "nr_weight", "weight_label", "weight", "p", "init_sol"]
+	_types = [c_int, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double), c_double, POINTER(c_double)]
 	_fields_ = genFields(_names, _types)
 
 	def __init__(self, options = None):
@@ -142,10 +152,14 @@ class parameter(Structure):
 		self.C = 1
 		self.p = 0.1
 		self.nr_weight = 0
-		self.weight_label = (c_int * 0)()
-		self.weight = (c_double * 0)()
+		self.weight_label = None
+		self.weight = None
+		self.init_sol = None
 		self.bias = -1
-		self.cross_validation = False
+		self.flag_cross_validation = False
+		self.flag_C_specified = False
+		self.flag_solver_specified = False
+		self.flag_find_C = False
 		self.nr_fold = 0
 		self.print_func = cast(None, PRINT_STRING_FUN)
 
@@ -166,9 +180,11 @@ class parameter(Structure):
 			if argv[i] == "-s":
 				i = i + 1
 				self.solver_type = int(argv[i])
+				self.flag_solver_specified = True
 			elif argv[i] == "-c":
 				i = i + 1
 				self.C = float(argv[i])
+				self.flag_C_specified = True
 			elif argv[i] == "-p":
 				i = i + 1
 				self.p = float(argv[i])
@@ -180,18 +196,20 @@ class parameter(Structure):
 				self.bias = float(argv[i])
 			elif argv[i] == "-v":
 				i = i + 1
-				self.cross_validation = 1
+				self.flag_cross_validation = 1
 				self.nr_fold = int(argv[i])
 				if self.nr_fold < 2 :
 					raise ValueError("n-fold cross validation: n must >= 2")
 			elif argv[i].startswith("-w"):
 				i = i + 1
 				self.nr_weight += 1
-				nr_weight = self.nr_weight
 				weight_label += [int(argv[i-1][2:])]
 				weight += [float(argv[i])]
 			elif argv[i] == "-q":
 				self.print_func = PRINT_STRING_FUN(print_null)
+			elif argv[i] == "-C":
+				self.flag_find_C = True
+
 			else :
 				raise ValueError("Wrong options")
 			i += 1
@@ -203,6 +221,16 @@ class parameter(Structure):
 			self.weight[i] = weight[i]
 			self.weight_label[i] = weight_label[i]
 
+		# default solver for parameter selection is L2R_L2LOSS_SVC
+		if self.flag_find_C:
+			if not self.flag_cross_validation:
+				self.nr_fold = 5
+			if not self.flag_solver_specified:
+				self.solver_type = L2R_L2LOSS_SVC
+				self.flag_solver_specified = True
+			elif self.solver_type not in [L2R_LR, L2R_L2LOSS_SVC]:
+				raise ValueError("Warm-start parameter search only available for -s 0 and -s 2")
+
 		if self.eps == float('inf'):
 			if self.solver_type in [L2R_LR, L2R_L2LOSS_SVC]:
 				self.eps = 0.01
@@ -240,9 +268,23 @@ class model(Structure):
 		liblinear.get_labels(self, labels)
 		return labels[:nr_class]
 
+	def get_decfun_coef(self, feat_idx, label_idx=0):
+		return liblinear.get_decfun_coef(self, feat_idx, label_idx)
+
+	def get_decfun_bias(self, label_idx=0):
+		return liblinear.get_decfun_bias(self, label_idx)
+
+	def get_decfun(self, label_idx=0):
+		w = [liblinear.get_decfun_coef(self, feat_idx, label_idx) for feat_idx in range(1, self.nr_feature+1)]
+		b = liblinear.get_decfun_bias(self, label_idx)
+		return (w, b)
+
 	def is_probability_model(self):
 		return (liblinear.check_probability_model(self) == 1)
 
+	def is_regression_model(self):
+		return (liblinear.check_regression_model(self) == 1)
+
 def toPyModel(model_ptr):
 	"""
 	toPyModel(model_ptr) -> model
@@ -256,6 +298,7 @@ def toPyModel(model_ptr):
 	return m
 
 fillprototype(liblinear.train, POINTER(model), [POINTER(problem), POINTER(parameter)])
+fillprototype(liblinear.find_parameter_C, None, [POINTER(problem), POINTER(parameter), c_int, c_double, c_double, POINTER(c_double), POINTER(c_double)])
 fillprototype(liblinear.cross_validation, None, [POINTER(problem), POINTER(parameter), c_int, POINTER(c_double)])
 
 fillprototype(liblinear.predict_values, c_double, [POINTER(model), POINTER(feature_node), POINTER(c_double)])
@@ -268,10 +311,13 @@ fillprototype(liblinear.load_model, POINTER(model), [c_char_p])
 fillprototype(liblinear.get_nr_feature, c_int, [POINTER(model)])
 fillprototype(liblinear.get_nr_class, c_int, [POINTER(model)])
 fillprototype(liblinear.get_labels, None, [POINTER(model), POINTER(c_int)])
+fillprototype(liblinear.get_decfun_coef, c_double, [POINTER(model), c_int, c_int])
+fillprototype(liblinear.get_decfun_bias, c_double, [POINTER(model), c_int])
 
 fillprototype(liblinear.free_model_content, None, [POINTER(model)])
 fillprototype(liblinear.free_and_destroy_model, None, [POINTER(POINTER(model))])
 fillprototype(liblinear.destroy_param, None, [POINTER(parameter)])
 fillprototype(liblinear.check_parameter, c_char_p, [POINTER(problem), POINTER(parameter)])
 fillprototype(liblinear.check_probability_model, c_int, [POINTER(model)])
+fillprototype(liblinear.check_regression_model, c_int, [POINTER(model)])
 fillprototype(liblinear.set_print_string_function, None, [CFUNCTYPE(None, c_char_p)])
diff --git a/python/liblinearutil.py b/python/liblinearutil.py
index d63e088..5ba5efa 100644
--- a/python/liblinearutil.py
+++ b/python/liblinearutil.py
@@ -3,6 +3,12 @@
 import os, sys
 sys.path = [os.path.dirname(os.path.abspath(__file__))] + sys.path 
 from liblinear import *
+from liblinear import __all__ as liblinear_all
+from ctypes import c_double
+
+__all__ = ['svm_read_problem', 'load_model', 'save_model', 'evaluations',
+           'train', 'predict'] + liblinear_all
+
 
 def svm_read_problem(data_file_name):
 	"""
@@ -144,7 +150,21 @@ def train(arg1, arg2=None, arg3=None):
 	if err_msg :
 		raise ValueError('Error: %s' % err_msg)
 
-	if param.cross_validation:
+	if param.flag_find_C:
+		nr_fold = param.nr_fold
+		best_C = c_double()
+		best_rate = c_double()		
+		max_C = 1024
+		if param.flag_C_specified:
+			start_C = param.C
+		else:
+			start_C = -1.0
+		liblinear.find_parameter_C(prob, param, nr_fold, start_C, max_C, best_C, best_rate)
+		print("Best C = %lf  CV accuracy = %g%%\n"% (best_C.value, 100.0*best_rate.value))
+		return best_C.value,best_rate.value
+
+
+	elif param.flag_cross_validation:
 		l, nr_fold = prob.l, param.nr_fold
 		target = (c_double * l)()
 		liblinear.cross_validation(prob, param, nr_fold, target)
@@ -241,7 +261,7 @@ def predict(y, x, m, options=""):
 		y = [0] * len(x)
 	ACC, MSE, SCC = evaluations(y, pred_labels)
 	l = len(y)
-	if solver_type in [L2R_L2LOSS_SVR, L2R_L2LOSS_SVR_DUAL, L2R_L1LOSS_SVR_DUAL]:
+	if m.is_regression_model():
 		info("Mean squared error = %g (regression)" % MSE)
 		info("Squared correlation coefficient = %g (regression)" % SCC)
 	else:
diff --git a/train.c b/train.c
index d388175..53f6dbb 100644
--- a/train.c
+++ b/train.c
@@ -49,6 +49,7 @@ void exit_with_help()
 	"-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)\n"
 	"-wi weight: weights adjust the parameter C of different classes (see README for details)\n"
 	"-v n: n-fold cross validation mode\n"
+	"-C : find parameter C (only for -s 0 and 2)\n"
 	"-q : quiet mode (no outputs)\n"
 	);
 	exit(1);
@@ -84,12 +85,16 @@ static char* readline(FILE *input)
 void parse_command_line(int argc, char **argv, char *input_file_name, char *model_file_name);
 void read_problem(const char *filename);
 void do_cross_validation();
+void do_find_parameter_C();
 
 struct feature_node *x_space;
 struct parameter param;
 struct problem prob;
 struct model* model_;
 int flag_cross_validation;
+int flag_find_C;
+int flag_C_specified;
+int flag_solver_specified;
 int nr_fold;
 double bias;
 
@@ -109,7 +114,11 @@ int main(int argc, char **argv)
 		exit(1);
 	}
 
-	if(flag_cross_validation)
+	if (flag_find_C)
+	{
+		do_find_parameter_C();
+	}
+	else if(flag_cross_validation)
 	{
 		do_cross_validation();
 	}
@@ -132,6 +141,19 @@ int main(int argc, char **argv)
 	return 0;
 }
 
+void do_find_parameter_C()
+{
+	double start_C, best_C, best_rate;
+	double max_C = 1024;
+	if (flag_C_specified)
+		start_C = param.C;
+	else
+		start_C = -1.0;
+	printf("Doing parameter search with %d-fold cross validation.\n", nr_fold);
+	find_parameter_C(&prob, &param, nr_fold, start_C, max_C, &best_C, &best_rate);
+	printf("Best C = %lf  CV accuracy = %g%%\n", best_C, 100.0*best_rate);
+}
+
 void do_cross_validation()
 {
 	int i;
@@ -186,7 +208,11 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
 	param.nr_weight = 0;
 	param.weight_label = NULL;
 	param.weight = NULL;
+	param.init_sol = NULL;
 	flag_cross_validation = 0;
+	flag_C_specified = 0;
+	flag_solver_specified = 0;
+	flag_find_C = 0;
 	bias = -1;
 
 	// parse options
@@ -199,10 +225,12 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
 		{
 			case 's':
 				param.solver_type = atoi(argv[i]);
+				flag_solver_specified = 1;
 				break;
 
 			case 'c':
 				param.C = atof(argv[i]);
+				flag_C_specified = 1;
 				break;
 
 			case 'p':
@@ -240,6 +268,11 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
 				i--;
 				break;
 
+			case 'C':
+				flag_find_C = 1;
+				i--;
+				break;
+
 			default:
 				fprintf(stderr,"unknown option: -%c\n", argv[i-1][1]);
 				exit_with_help();
@@ -267,6 +300,23 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
 		sprintf(model_file_name,"%s.model",p);
 	}
 
+	// default solver for parameter selection is L2R_L2LOSS_SVC
+	if(flag_find_C)
+	{
+		if(!flag_cross_validation)
+			nr_fold = 5;
+		if(!flag_solver_specified)
+		{
+			fprintf(stderr, "Solver not specified. Using -s 2\n");
+			param.solver_type = L2R_L2LOSS_SVC;
+		}
+		else if(param.solver_type != L2R_LR && param.solver_type != L2R_L2LOSS_SVC)
+		{
+			fprintf(stderr, "Warm-start parameter search only available for -s 0 and -s 2\n");
+			exit_with_help();
+		}
+	}
+
 	if(param.eps == INF)
 	{
 		switch(param.solver_type)
@@ -300,7 +350,7 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
 void read_problem(const char *filename)
 {
 	int max_index, inst_max_index, i;
-	long int elements, j;
+	size_t elements, j;
 	FILE *fp = fopen(filename,"r");
 	char *endptr;
 	char *idx, *val, *label;
diff --git a/tron.cpp b/tron.cpp
index 7d1fd6e..3ea60f6 100644
--- a/tron.cpp
+++ b/tron.cpp
@@ -41,10 +41,11 @@ void TRON::info(const char *fmt,...)
 	(*tron_print_string)(buf);
 }
 
-TRON::TRON(const function *fun_obj, double eps, int max_iter)
+TRON::TRON(const function *fun_obj, double eps, double eps_cg, int max_iter)
 {
 	this->fun_obj=const_cast<function *>(fun_obj);
 	this->eps=eps;
+	this->eps_cg=eps_cg;
 	this->max_iter=max_iter;
 	tron_print_string = default_print;
 }
@@ -68,23 +69,28 @@ void TRON::tron(double *w)
 	int search = 1, iter = 1, inc = 1;
 	double *s = new double[n];
 	double *r = new double[n];
-	double *w_new = new double[n];
 	double *g = new double[n];
 
+	// calculate gradient norm at w=0 for stopping condition.
+	double *w0 = new double[n];
 	for (i=0; i<n; i++)
-		w[i] = 0;
+		w0[i] = 0;
+	fun_obj->fun(w0);
+	fun_obj->grad(w0, g);
+	double gnorm0 = dnrm2_(&n, g, &inc);
+	delete [] w0;
 
 	f = fun_obj->fun(w);
 	fun_obj->grad(w, g);
 	delta = dnrm2_(&n, g, &inc);
-	double gnorm1 = delta;
-	double gnorm = gnorm1;
+	double gnorm = delta;
 
-	if (gnorm <= eps*gnorm1)
+	if (gnorm <= eps*gnorm0)
 		search = 0;
 
 	iter = 1;
 
+	double *w_new = new double[n];
 	while (iter <= max_iter && search)
 	{
 		cg_iter = trcg(delta, g, s, r);
@@ -130,7 +136,7 @@ void TRON::tron(double *w)
 			fun_obj->grad(w, g);
 
 			gnorm = dnrm2_(&n, g, &inc);
-			if (gnorm <= eps*gnorm1)
+			if (gnorm <= eps*gnorm0)
 				break;
 		}
 		if (f < -1.0e+32)
@@ -172,7 +178,7 @@ int TRON::trcg(double delta, double *g, double *s, double *r)
 		r[i] = -g[i];
 		d[i] = r[i];
 	}
-	cgtol = 0.1*dnrm2_(&n, g, &inc);
+	cgtol = eps_cg*dnrm2_(&n, g, &inc);
 
 	int cg_iter = 0;
 	rTr = ddot_(&n, r, &inc, r, &inc);
diff --git a/tron.h b/tron.h
index 3045c2e..56002dc 100644
--- a/tron.h
+++ b/tron.h
@@ -15,7 +15,7 @@ public:
 class TRON
 {
 public:
-	TRON(const function *fun_obj, double eps = 0.1, int max_iter = 1000);
+	TRON(const function *fun_obj, double eps = 0.1, double eps_cg = 0.1, int max_iter = 1000);
 	~TRON();
 
 	void tron(double *w);
@@ -26,6 +26,7 @@ private:
 	double norm_inf(int n, double *x);
 
 	double eps;
+	double eps_cg;
 	int max_iter;
 	function *fun_obj;
 	void info(const char *fmt,...);
diff --git a/windows/liblinear.dll b/windows/liblinear.dll
deleted file mode 100644
index 345e8a0..0000000
Binary files a/windows/liblinear.dll and /dev/null differ
diff --git a/windows/libsvmread.mexw64 b/windows/libsvmread.mexw64
deleted file mode 100644
index 61cd009..0000000
Binary files a/windows/libsvmread.mexw64 and /dev/null differ
diff --git a/windows/libsvmwrite.mexw64 b/windows/libsvmwrite.mexw64
deleted file mode 100644
index 6d7c319..0000000
Binary files a/windows/libsvmwrite.mexw64 and /dev/null differ
diff --git a/windows/predict.exe b/windows/predict.exe
deleted file mode 100644
index 510800e..0000000
Binary files a/windows/predict.exe and /dev/null differ
diff --git a/windows/predict.mexw64 b/windows/predict.mexw64
deleted file mode 100644
index dcb7c37..0000000
Binary files a/windows/predict.mexw64 and /dev/null differ
diff --git a/windows/train.exe b/windows/train.exe
deleted file mode 100644
index 8f481de..0000000
Binary files a/windows/train.exe and /dev/null differ
diff --git a/windows/train.mexw64 b/windows/train.mexw64
deleted file mode 100644
index c3a7d8b..0000000
Binary files a/windows/train.mexw64 and /dev/null differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/liblinear.git



More information about the debian-science-commits mailing list