16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_ml.h"
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                COPYRIGHT NOTICE
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                ----------------
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  The code has been derived from libsvm library (version 2.6)
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  (http://www.csie.ntu.edu.tw/~cjlin/libsvm).
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn  Here is the orignal copyright:
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn------------------------------------------------------------------------------------------
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Copyright (c) 2000-2003 Chih-Chung Chang and Chih-Jen Lin
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    All rights reserved.
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Redistribution and use in source and binary forms, with or without
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    modification, are permitted provided that the following conditions
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    are met:
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    1. Redistributions of source code must retain the above copyright
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    notice, this list of conditions and the following disclaimer.
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    2. Redistributions in binary form must reproduce the above copyright
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    notice, this list of conditions and the following disclaimer in the
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    documentation and/or other materials provided with the distribution.
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    3. Neither name of copyright holders nor the names of its contributors
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    may be used to endorse or promote products derived from this software
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    without specific prior written permission.
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_SVM_MIN_CACHE_SIZE  (40 << 20)  /* 40Mb */
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdarg.h>
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <ctype.h>
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if _MSC_VER >= 1200
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#pragma warning( disable: 4514 ) /* unreferenced inline functions */
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if 1
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef float Qfloat;
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define QFLOAT_TYPE CV_32F
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef double Qfloat;
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define QFLOAT_TYPE CV_64F
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Param Grid
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvParamGrid::check() const
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvParamGrid::check" );
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( min_val > max_val )
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Lower bound of the grid must be less then the upper one" );
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( min_val < DBL_EPSILON )
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Lower bound of the grid must be positive" );
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( step < 1. + FLT_EPSILON )
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Grid step must greater then 1" );
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = true;
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvParamGrid CvSVM::get_default_grid( int param_id )
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvParamGrid grid;
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( param_id == CvSVM::C )
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.min_val = 0.1;
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.max_val = 500;
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.step = 5; // total iterations = 5
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( param_id == CvSVM::GAMMA )
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.min_val = 1e-5;
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.max_val = 0.6;
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.step = 15; // total iterations = 4
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( param_id == CvSVM::P )
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.min_val = 0.01;
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.max_val = 100;
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.step = 7; // total iterations = 4
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( param_id == CvSVM::NU )
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.min_val = 0.01;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.max_val = 0.2;
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.step = 3; // total iterations = 3
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( param_id == CvSVM::COEF )
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.min_val = 0.1;
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.max_val = 300;
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.step = 14; // total iterations = 3
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( param_id == CvSVM::DEGREE )
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.min_val = 0.01;
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.max_val = 4;
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        grid.step = 7; // total iterations = 3
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvError( CV_StsBadArg, "CvSVM::get_default_grid", "Invalid type of parameter "
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "(use one of CvSVM::C, CvSVM::GAMMA et al.)", __FILE__, __LINE__ );
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return grid;
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// SVM training parameters
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMParams::CvSVMParams() :
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type(CvSVM::C_SVC), kernel_type(CvSVM::RBF), degree(0),
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    gamma(1), coef0(0), C(1), nu(0), p(0), class_weights(0)
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    term_crit = cvTermCriteria( CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, FLT_EPSILON );
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMParams::CvSVMParams( int _svm_type, int _kernel_type,
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double _degree, double _gamma, double _coef0,
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double _Con, double _nu, double _p,
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* _class_weights, CvTermCriteria _term_crit ) :
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type(_svm_type), kernel_type(_kernel_type),
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    degree(_degree), gamma(_gamma), coef0(_coef0),
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    C(_Con), nu(_nu), p(_p), class_weights(_class_weights), term_crit(_term_crit)
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////////////////////// SVM kernel ///////////////////////////////////////
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMKernel::CvSVMKernel()
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::clear()
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params = 0;
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_func = 0;
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMKernel::~CvSVMKernel()
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMKernel::CvSVMKernel( const CvSVMParams* _params, Calc _calc_func )
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create( _params, _calc_func );
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMKernel::create( const CvSVMParams* _params, Calc _calc_func )
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params = _params;
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_func = _calc_func;
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !calc_func )
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        calc_func = params->kernel_type == CvSVM::RBF ? &CvSVMKernel::calc_rbf :
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    params->kernel_type == CvSVM::POLY ? &CvSVMKernel::calc_poly :
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    params->kernel_type == CvSVM::SIGMOID ? &CvSVMKernel::calc_sigmoid :
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    &CvSVMKernel::calc_linear;
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::calc_non_rbf_base( int vcount, int var_count, const float** vecs,
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     const float* another, Qfloat* results,
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                     double alpha, double beta )
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int j, k;
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( j = 0; j < vcount; j++ )
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const float* sample = vecs[j];
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double s = 0;
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k <= var_count - 4; k += 4 )
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += sample[k]*another[k] + sample[k+1]*another[k+1] +
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 sample[k+2]*another[k+2] + sample[k+3]*another[k+3];
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; k < var_count; k++ )
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += sample[k]*another[k];
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        results[j] = (Qfloat)(s*alpha + beta);
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::calc_linear( int vcount, int var_count, const float** vecs,
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               const float* another, Qfloat* results )
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_non_rbf_base( vcount, var_count, vecs, another, results, 1, 0 );
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::calc_poly( int vcount, int var_count, const float** vecs,
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             const float* another, Qfloat* results )
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat R = cvMat( 1, vcount, QFLOAT_TYPE, results );
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_non_rbf_base( vcount, var_count, vecs, another, results, params->gamma, params->coef0 );
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvPow( &R, &R, params->degree );
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::calc_sigmoid( int vcount, int var_count, const float** vecs,
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                const float* another, Qfloat* results )
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int j;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_non_rbf_base( vcount, var_count, vecs, another, results,
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       -2*params->gamma, -2*params->coef0 );
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // TODO: speedup this
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( j = 0; j < vcount; j++ )
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Qfloat t = results[j];
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double e = exp(-fabs(t));
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( t > 0 )
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            results[j] = (Qfloat)((1. - e)/(1. + e));
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            results[j] = (Qfloat)((e - 1.)/(e + 1.));
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::calc_rbf( int vcount, int var_count, const float** vecs,
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            const float* another, Qfloat* results )
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat R = cvMat( 1, vcount, QFLOAT_TYPE, results );
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double gamma = -params->gamma;
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int j, k;
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( j = 0; j < vcount; j++ )
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const float* sample = vecs[j];
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double s = 0;
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k <= var_count - 4; k += 4 )
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double t0 = sample[k] - another[k];
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double t1 = sample[k+1] - another[k+1];
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += t0*t0 + t1*t1;
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t0 = sample[k+2] - another[k+2];
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            t1 = sample[k+3] - another[k+3];
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += t0*t0 + t1*t1;
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( ; k < var_count; k++ )
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double t0 = sample[k] - another[k];
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            s += t0*t0;
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        results[j] = (Qfloat)(s*gamma);
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvExp( &R, &R );
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMKernel::calc( int vcount, int var_count, const float** vecs,
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        const float* another, Qfloat* results )
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const Qfloat max_val = (Qfloat)(FLT_MAX*1e-3);
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int j;
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (this->*calc_func)( vcount, var_count, vecs, another, results );
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( j = 0; j < vcount; j++ )
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( results[j] > max_val )
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            results[j] = max_val;
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Generalized SMO+SVMlight algorithm
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Solves:
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  min [0.5(\alpha^T Q \alpha) + b^T \alpha]
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      y^T \alpha = \delta
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      y_i = +1 or -1
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      0 <= alpha_i <= Cp for y_i = 1
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//      0 <= alpha_i <= Cn for y_i = -1
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Given:
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  Q, b, y, Cp, Cn, and an initial feasible point \alpha
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  l is the size of vectors and matrices
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  eps is the stopping criterion
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// solution will be put in \alpha, objective value will be put in obj
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVMSolver::clear()
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    G = 0;
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha = 0;
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y = 0;
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    b = 0;
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf[0] = buf[1] = 0;
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage( &storage );
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = 0;
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    select_working_set_func = 0;
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_rho_func = 0;
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows = 0;
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    samples = 0;
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    get_row_func = 0;
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::CvSVMSolver()
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage = 0;
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::~CvSVMSolver()
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::CvSVMSolver( int _sample_count, int _var_count, const float** _samples, schar* _y,
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int _alpha_count, double* _alpha, double _Cp, double _Cn,
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvMemStorage* _storage, CvSVMKernel* _kernel, GetRow _get_row,
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                SelectWorkingSet _select_working_set, CalcRho _calc_rho )
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage = 0;
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create( _sample_count, _var_count, _samples, _y, _alpha_count, _alpha, _Cp, _Cn,
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            _storage, _kernel, _get_row, _select_working_set, _calc_rho );
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::create( int _sample_count, int _var_count, const float** _samples, schar* _y,
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int _alpha_count, double* _alpha, double _Cp, double _Cn,
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CvMemStorage* _storage, CvSVMKernel* _kernel, GetRow _get_row,
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                SelectWorkingSet _select_working_set, CalcRho _calc_rho )
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, svm_type;
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVMSolver::create" );
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int rows_hdr_size;
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sample_count = _sample_count;
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_count = _var_count;
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    samples = _samples;
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y = _y;
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha_count = _alpha_count;
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha = _alpha;
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = _kernel;
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    C[0] = _Cn;
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    C[1] = _Cp;
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    eps = kernel->params->term_crit.epsilon;
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    max_iter = kernel->params->term_crit.max_iter;
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage = cvCreateChildMemStorage( _storage );
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    b = (double*)cvMemStorageAlloc( storage, alpha_count*sizeof(b[0]));
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha_status = (schar*)cvMemStorageAlloc( storage, alpha_count*sizeof(alpha_status[0]));
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    G = (double*)cvMemStorageAlloc( storage, alpha_count*sizeof(G[0]));
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < 2; i++ )
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        buf[i] = (Qfloat*)cvMemStorageAlloc( storage, sample_count*2*sizeof(buf[i][0]) );
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type = kernel->params->svm_type;
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    select_working_set_func = _select_working_set;
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !select_working_set_func )
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        select_working_set_func = svm_type == CvSVM::NU_SVC || svm_type == CvSVM::NU_SVR ?
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        &CvSVMSolver::select_working_set_nu_svm : &CvSVMSolver::select_working_set;
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    calc_rho_func = _calc_rho;
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !calc_rho_func )
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        calc_rho_func = svm_type == CvSVM::NU_SVC || svm_type == CvSVM::NU_SVR ?
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            &CvSVMSolver::calc_rho_nu_svm : &CvSVMSolver::calc_rho;
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    get_row_func = _get_row;
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !get_row_func )
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        get_row_func = params->svm_type == CvSVM::EPS_SVR ||
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       params->svm_type == CvSVM::NU_SVR ? &CvSVMSolver::get_row_svr :
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       params->svm_type == CvSVM::C_SVC ||
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       params->svm_type == CvSVM::NU_SVC ? &CvSVMSolver::get_row_svc :
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                       &CvSVMSolver::get_row_one_class;
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cache_line_size = sample_count*sizeof(Qfloat);
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // cache size = max(num_of_samples^2*sizeof(Qfloat)*0.25, 64Kb)
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // (assuming that for large training sets ~25% of Q matrix is used)
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cache_size = MAX( cache_line_size*sample_count/4, CV_SVM_MIN_CACHE_SIZE );
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // the size of Q matrix row headers
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows_hdr_size = sample_count*sizeof(rows[0]);
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( rows_hdr_size > storage->block_size )
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "Too small storage block size" );
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    lru_list.prev = lru_list.next = &lru_list;
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rows = (CvSVMKernelRow*)cvMemStorageAlloc( storage, rows_hdr_size );
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( rows, 0, rows_hdr_size );
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = true;
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat* CvSVMSolver::get_row_base( int i, bool* _existed )
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i1 = i < sample_count ? i : i - sample_count;
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMKernelRow* row = rows + i1;
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool existed = row->data != 0;
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Qfloat* data;
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( existed || cache_size <= 0 )
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSVMKernelRow* del_row = existed ? row : lru_list.prev;
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = del_row->data;
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( data != 0 );
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // delete row from the LRU list
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        del_row->data = 0;
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        del_row->prev->next = del_row->next;
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        del_row->next->prev = del_row->prev;
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        data = (Qfloat*)cvMemStorageAlloc( storage, cache_line_size );
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cache_size -= cache_line_size;
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // insert row into the LRU list
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    row->data = data;
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    row->prev = &lru_list;
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    row->next = lru_list.next;
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    row->prev->next = row->next->prev = row;
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !existed )
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel->calc( sample_count, var_count, samples, samples[i1], row->data );
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _existed )
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *_existed = existed;
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return row->data;
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat* CvSVMSolver::get_row_svc( int i, float* row, float*, bool existed )
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !existed )
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const schar* _y = y;
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int j, len = sample_count;
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( _y && i < sample_count );
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( _y[i] > 0 )
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < len; j++ )
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                row[j] = _y[j]*row[j];
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < len; j++ )
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                row[j] = -_y[j]*row[j];
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return row;
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat* CvSVMSolver::get_row_one_class( int, float* row, float*, bool )
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return row;
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat* CvSVMSolver::get_row_svr( int i, float* row, float* dst, bool )
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int j, len = sample_count;
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Qfloat* dst_pos = dst;
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Qfloat* dst_neg = dst + len;
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( i >= len )
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Qfloat* temp;
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP( dst_pos, dst_neg, temp );
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( j = 0; j < len; j++ )
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Qfloat t = row[j];
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst_pos[j] = t;
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst_neg[j] = -t;
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return dst;
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat* CvSVMSolver::get_row( int i, float* dst )
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool existed = false;
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* row = get_row_base( i, &existed );
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return (this->*get_row_func)( i, row, dst, existed );
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef is_upper_bound
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define is_upper_bound(i) (alpha_status[i] > 0)
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef is_lower_bound
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define is_lower_bound(i) (alpha_status[i] < 0)
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef is_free
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define is_free(i) (alpha_status[i] == 0)
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef get_C
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define get_C(i) (C[y[i]>0])
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef update_alpha_status
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define update_alpha_status(i) \
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha_status[i] = (schar)(alpha[i] >= get_C(i) ? 1 : alpha[i] <= 0 ? -1 : 0)
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef reconstruct_gradient
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define reconstruct_gradient() /* empty for now */
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::solve_generic( CvSVMSolutionInfo& si )
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int iter = 0;
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k;
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // 1. initialize gradient and alpha status
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < alpha_count; i++ )
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        update_alpha_status(i);
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        G[i] = b[i];
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(G[i]) > 1e200 )
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return false;
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < alpha_count; i++ )
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !is_lower_bound(i) )
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const Qfloat *Q_i = get_row( i, buf[0] );
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double alpha_i = alpha[i];
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < alpha_count; j++ )
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                G[j] += alpha_i*Q_i[j];
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // 2. optimization loop
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for(;;)
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const Qfloat *Q_i, *Q_j;
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double C_i, C_j;
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double old_alpha_i, old_alpha_j, alpha_i, alpha_j;
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double delta_alpha_i, delta_alpha_j;
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef _DEBUG
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < alpha_count; i++ )
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fabs(G[i]) > 1e+300 )
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return false;
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fabs(alpha[i]) > 1e16 )
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return false;
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( (this->*select_working_set_func)( i, j ) != 0 || iter++ >= max_iter )
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            break;
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Q_i = get_row( i, buf[0] );
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Q_j = get_row( j, buf[1] );
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_i = get_C(i);
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_j = get_C(j);
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha_i = old_alpha_i = alpha[i];
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha_j = old_alpha_j = alpha[j];
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y[i] != y[j] )
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double denom = Q_i[i]+Q_j[j]+2*Q_i[j];
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double delta = (-G[i]-G[j])/MAX(fabs(denom),FLT_EPSILON);
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double diff = alpha_i - alpha_j;
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            alpha_i += delta;
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            alpha_j += delta;
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( diff > 0 && alpha_j < 0 )
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = 0;
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = diff;
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( diff <= 0 && alpha_i < 0 )
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = 0;
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = -diff;
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( diff > C_i - C_j && alpha_i > C_i )
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = C_i;
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = C_i - diff;
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( diff <= C_i - C_j && alpha_j > C_j )
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = C_j;
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = C_j + diff;
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double denom = Q_i[i]+Q_j[j]-2*Q_i[j];
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double delta = (G[i]-G[j])/MAX(fabs(denom),FLT_EPSILON);
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            double sum = alpha_i + alpha_j;
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            alpha_i -= delta;
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            alpha_j += delta;
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( sum > C_i && alpha_i > C_i )
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = C_i;
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = sum - C_i;
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( sum <= C_i && alpha_j < 0)
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = 0;
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = sum;
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( sum > C_j && alpha_j > C_j )
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = C_j;
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = sum - C_j;
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( sum <= C_j && alpha_i < 0 )
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_i = 0;
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                alpha_j = sum;
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // update alpha
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] = alpha_i;
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[j] = alpha_j;
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        update_alpha_status(i);
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        update_alpha_status(j);
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // update G
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta_alpha_i = alpha_i - old_alpha_i;
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        delta_alpha_j = alpha_j - old_alpha_j;
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( k = 0; k < alpha_count; k++ )
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            G[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j;
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // calculate rho
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    (this->*calc_rho_func)( si.rho, si.r );
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // calculate objective value
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0, si.obj = 0; i < alpha_count; i++ )
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        si.obj += alpha[i] * (G[i] + b[i]);
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    si.obj *= 0.5;
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    si.upper_bound_p = C[1];
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    si.upper_bound_n = C[0];
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// return 1 if already optimal, return 0 otherwise
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::select_working_set( int& out_i, int& out_j )
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // return i,j which maximize -grad(f)^T d , under constraint
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // if alpha_i == C, d != +1
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // if alpha_i == 0, d != -1
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double Gmax1 = -DBL_MAX;        // max { -grad(f)_i * d | y_i*d = +1 }
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int Gmax1_idx = -1;
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double Gmax2 = -DBL_MAX;        // max { -grad(f)_i * d | y_i*d = -1 }
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int Gmax2_idx = -1;
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < alpha_count; i++ )
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double t;
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y[i] > 0 )    // y = +1
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_upper_bound(i) && (t = -G[i]) > Gmax1 )  // d = +1
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax1 = t;
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax1_idx = i;
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_lower_bound(i) && (t = G[i]) > Gmax2 )  // d = -1
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax2 = t;
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax2_idx = i;
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else        // y = -1
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_upper_bound(i) && (t = -G[i]) > Gmax2 )  // d = +1
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax2 = t;
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax2_idx = i;
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_lower_bound(i) && (t = G[i]) > Gmax1 )  // d = -1
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax1 = t;
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax1_idx = i;
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    out_i = Gmax1_idx;
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    out_j = Gmax2_idx;
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return Gmax1 + Gmax2 < eps;
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::calc_rho( double& rho, double& r )
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, nr_free = 0;
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double ub = DBL_MAX, lb = -DBL_MAX, sum_free = 0;
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < alpha_count; i++ )
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double yG = y[i]*G[i];
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( is_lower_bound(i) )
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y[i] > 0 )
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ub = MIN(ub,yG);
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lb = MAX(lb,yG);
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else if( is_upper_bound(i) )
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( y[i] < 0)
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ub = MIN(ub,yG);
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lb = MAX(lb,yG);
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ++nr_free;
8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_free += yG;
8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rho = nr_free > 0 ? sum_free/nr_free : (ub + lb)*0.5;
8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    r = 0;
8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool
8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::select_working_set_nu_svm( int& out_i, int& out_j )
8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // return i,j which maximize -grad(f)^T d , under constraint
8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // if alpha_i == C, d != +1
8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // if alpha_i == 0, d != -1
8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double Gmax1 = -DBL_MAX;    // max { -grad(f)_i * d | y_i = +1, d = +1 }
8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int Gmax1_idx = -1;
8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double Gmax2 = -DBL_MAX;    // max { -grad(f)_i * d | y_i = +1, d = -1 }
8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int Gmax2_idx = -1;
8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double Gmax3 = -DBL_MAX;    // max { -grad(f)_i * d | y_i = -1, d = +1 }
8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int Gmax3_idx = -1;
8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double Gmax4 = -DBL_MAX;    // max { -grad(f)_i * d | y_i = -1, d = -1 }
8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int Gmax4_idx = -1;
8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < alpha_count; i++ )
8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double t;
8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y[i] > 0 )    // y == +1
8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_upper_bound(i) && (t = -G[i]) > Gmax1 )  // d = +1
8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax1 = t;
8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax1_idx = i;
8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_lower_bound(i) && (t = G[i]) > Gmax2 )  // d = -1
8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax2 = t;
8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax2_idx = i;
8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else        // y == -1
8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_upper_bound(i) && (t = -G[i]) > Gmax3 )  // d = +1
8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax3 = t;
8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax3_idx = i;
8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !is_lower_bound(i) && (t = G[i]) > Gmax4 )  // d = -1
8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax4 = t;
8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                Gmax4_idx = i;
8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( MAX(Gmax1 + Gmax2, Gmax3 + Gmax4) < eps )
8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return 1;
8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( Gmax1 + Gmax2 > Gmax3 + Gmax4 )
8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        out_i = Gmax1_idx;
8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        out_j = Gmax2_idx;
8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        out_i = Gmax3_idx;
8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        out_j = Gmax4_idx;
8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 0;
8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid
9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVMSolver::calc_rho_nu_svm( double& rho, double& r )
9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int nr_free1 = 0, nr_free2 = 0;
9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double ub1 = DBL_MAX, ub2 = DBL_MAX;
9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double lb1 = -DBL_MAX, lb2 = -DBL_MAX;
9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double sum_free1 = 0, sum_free2 = 0;
9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double r1, r2;
9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < alpha_count; i++ )
9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double G_i = G[i];
9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y[i] > 0 )
9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_lower_bound(i) )
9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ub1 = MIN( ub1, G_i );
9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( is_upper_bound(i) )
9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lb1 = MAX( lb1, G_i );
9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ++nr_free1;
9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum_free1 += G_i;
9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( is_lower_bound(i) )
9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ub2 = MIN( ub2, G_i );
9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if( is_upper_bound(i) )
9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                lb2 = MAX( lb2, G_i );
9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ++nr_free2;
9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sum_free2 += G_i;
9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    r1 = nr_free1 > 0 ? sum_free1/nr_free1 : (ub1 + lb1)*0.5;
9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    r2 = nr_free2 > 0 ? sum_free2/nr_free2 : (ub2 + lb2)*0.5;
9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rho = (r1 - r2)*0.5;
9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    r = (r1 + r2)*0.5;
9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*
9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn///////////////////////// construct and solve various formulations ///////////////////////
9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/
9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::solve_c_svc( int _sample_count, int _var_count, const float** _samples, schar* _y,
9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               double _Cp, double _Cn, CvMemStorage* _storage,
9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               CvSVMKernel* _kernel, double* _alpha, CvSVMSolutionInfo& _si )
9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !create( _sample_count, _var_count, _samples, _y, _sample_count,
9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 _alpha, _Cp, _Cn, _storage, _kernel, &CvSVMSolver::get_row_svc,
9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 &CvSVMSolver::select_working_set, &CvSVMSolver::calc_rho ))
9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] = 0;
9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i] = -1;
9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !solve_generic( _si ))
9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] *= y[i];
9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::solve_nu_svc( int _sample_count, int _var_count, const float** _samples, schar* _y,
9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CvMemStorage* _storage, CvSVMKernel* _kernel,
9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                double* _alpha, CvSVMSolutionInfo& _si )
9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double sum_pos, sum_neg, inv_r;
9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !create( _sample_count, _var_count, _samples, _y, _sample_count,
9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 _alpha, 1., 1., _storage, _kernel, &CvSVMSolver::get_row_svc,
9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 &CvSVMSolver::select_working_set_nu_svm, &CvSVMSolver::calc_rho_nu_svm ))
9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum_pos = kernel->params->nu * sample_count * 0.5;
9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum_neg = kernel->params->nu * sample_count * 0.5;
9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( y[i] > 0 )
9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            alpha[i] = MIN(1.0, sum_pos);
10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_pos -= alpha[i];
10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            alpha[i] = MIN(1.0, sum_neg);
10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum_neg -= alpha[i];
10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i] = 0;
10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !solve_generic( _si ))
10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    inv_r = 1./_si.r;
10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] *= y[i]*inv_r;
10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _si.rho *= inv_r;
10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _si.obj *= (inv_r*inv_r);
10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _si.upper_bound_p = inv_r;
10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _si.upper_bound_n = inv_r;
10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::solve_one_class( int _sample_count, int _var_count, const float** _samples,
10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   CvMemStorage* _storage, CvSVMKernel* _kernel,
10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   double* _alpha, CvSVMSolutionInfo& _si )
10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, n;
10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double nu = _kernel->params->nu;
10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !create( _sample_count, _var_count, _samples, 0, _sample_count,
10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 _alpha, 1., 1., _storage, _kernel, &CvSVMSolver::get_row_one_class,
10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 &CvSVMSolver::select_working_set, &CvSVMSolver::calc_rho ))
10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y = (schar*)cvMemStorageAlloc( storage, sample_count*sizeof(y[0]) );
10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    n = cvRound( nu*sample_count );
10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i] = 1;
10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i] = 0;
10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] = i < n ? 1 : 0;
10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( n < sample_count )
10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[n] = nu * sample_count - n;
10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[n-1] = nu * sample_count - (n-1);
10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return solve_generic(_si);
10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::solve_eps_svr( int _sample_count, int _var_count, const float** _samples,
10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 const float* _y, CvMemStorage* _storage,
10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CvSVMKernel* _kernel, double* _alpha, CvSVMSolutionInfo& _si )
10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double p = _kernel->params->p, C = _kernel->params->C;
10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !create( _sample_count, _var_count, _samples, 0,
10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 _sample_count*2, 0, C, C, _storage, _kernel, &CvSVMSolver::get_row_svr,
10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 &CvSVMSolver::select_working_set, &CvSVMSolver::calc_rho ))
10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y = (schar*)cvMemStorageAlloc( storage, sample_count*2*sizeof(y[0]) );
10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha = (double*)cvMemStorageAlloc( storage, alpha_count*sizeof(alpha[0]) );
10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] = 0;
10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i] = p - _y[i];
10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i] = 1;
10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i+sample_count] = 0;
10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i+sample_count] = p + _y[i];
10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i+sample_count] = -1;
10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !solve_generic( _si ))
10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _alpha[i] = alpha[i] - alpha[i+sample_count];
10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVMSolver::solve_nu_svr( int _sample_count, int _var_count, const float** _samples,
10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                const float* _y, CvMemStorage* _storage,
10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                CvSVMKernel* _kernel, double* _alpha, CvSVMSolutionInfo& _si )
10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i;
11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double C = _kernel->params->C, sum;
11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !create( _sample_count, _var_count, _samples, 0,
11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 _sample_count*2, 0, 1., 1., _storage, _kernel, &CvSVMSolver::get_row_svr,
11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                 &CvSVMSolver::select_working_set_nu_svm, &CvSVMSolver::calc_rho_nu_svm ))
11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    y = (schar*)cvMemStorageAlloc( storage, sample_count*2*sizeof(y[0]) );
11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    alpha = (double*)cvMemStorageAlloc( storage, alpha_count*sizeof(alpha[0]) );
11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sum = C * _kernel->params->nu * sample_count * 0.5;
11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        alpha[i] = alpha[i + sample_count] = MIN(sum, C);
11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sum -= alpha[i];
11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i] = -_y[i];
11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i] = 1;
11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        b[i + sample_count] = _y[i];
11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        y[i + sample_count] = -1;
11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !solve_generic( _si ))
11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _alpha[i] = alpha[i] - alpha[i+sample_count];
11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return true;
11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//////////////////////////////////////////////////////////////////////////////////////////
11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVM::CvSVM()
11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    decision_func = 0;
11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_labels = 0;
11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_weights = 0;
11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage = 0;
11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_idx = 0;
11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = 0;
11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    solver = 0;
11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    default_model_name = "my_svm";
11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVM::~CvSVM()
11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::clear()
11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &decision_func );
11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &class_labels );
11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &class_weights );
11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage( &storage );
11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &var_idx );
11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete kernel;
11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete solver;
11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = 0;
11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    solver = 0;
11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_all = 0;
11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv = 0;
11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv_total = 0;
11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvSVM::CvSVM( const CvMat* _train_data, const CvMat* _responses,
11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _var_idx, const CvMat* _sample_idx, CvSVMParams _params )
11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    decision_func = 0;
11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_labels = 0;
11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_weights = 0;
11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    storage = 0;
11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_idx = 0;
11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = 0;
11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    solver = 0;
11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    default_model_name = "my_svm";
11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    train( _train_data, _responses, _var_idx, _sample_idx, _params );
11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint CvSVM::get_support_vector_count() const
11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return sv_total;
11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennconst float* CvSVM::get_support_vector(int i) const
11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return sv && (unsigned)i < (unsigned)sv_total ? sv[i] : 0;
11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVM::set_params( const CvSVMParams& _params )
12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::set_params" );
12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int kernel_type, svm_type;
12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params = _params;
12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel_type = params.kernel_type;
12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type = params.svm_type;
12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type != LINEAR && kernel_type != POLY &&
12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type != SIGMOID && kernel_type != RBF )
12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Unknown/unsupported kernel type" );
12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type == LINEAR )
12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.gamma = 1;
12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.gamma <= 0 )
12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "gamma parameter of the kernel must be positive" );
12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type != SIGMOID && kernel_type != POLY )
12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.coef0 = 0;
12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.coef0 < 0 )
12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "The kernel parameter <coef0> must be positive or zero" );
12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type != POLY )
12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.degree = 0;
12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.degree <= 0 )
12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "The kernel parameter <degree> must be positive" );
12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type != C_SVC && svm_type != NU_SVC &&
12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type != ONE_CLASS && svm_type != EPS_SVR &&
12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type != NU_SVR )
12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Unknown/unsupported SVM type" );
12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == ONE_CLASS || svm_type == NU_SVC )
12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.C = 0;
12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.C <= 0 )
12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "The parameter C must be positive" );
12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == C_SVC || svm_type == EPS_SVR )
12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.nu = 0;
12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.nu <= 0 || params.nu >= 1 )
12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "The parameter nu must be between 0 and 1" );
12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type != EPS_SVR )
12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.p = 0;
12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.p <= 0 )
12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsOutOfRange, "The parameter p must be positive" );
12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type != C_SVC )
12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.class_weights = 0;
12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.term_crit = cvCheckTermCriteria( params.term_crit, DBL_EPSILON, INT_MAX );
12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.term_crit.epsilon = MAX( params.term_crit.epsilon, DBL_EPSILON );
12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = true;
12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::create_kernel()
12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = new CvSVMKernel(&params,0);
12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::create_solver( )
12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    solver = new CvSVMSolver;
12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// switching function
12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVM::train1( int sample_count, int var_count, const float** samples,
12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const void* _responses, double Cp, double Cn,
12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CvMemStorage* _storage, double* alpha, double& rho )
12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "CvSVM::train1" );
12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMSolutionInfo si;
12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int svm_type = params.svm_type;
12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    si.rho = 0;
12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = svm_type == C_SVC ? solver->solve_c_svc( sample_count, var_count, samples, (schar*)_responses,
12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                  Cp, Cn, _storage, kernel, alpha, si ) :
12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         svm_type == NU_SVC ? solver->solve_nu_svc( sample_count, var_count, samples, (schar*)_responses,
13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                    _storage, kernel, alpha, si ) :
13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         svm_type == ONE_CLASS ? solver->solve_one_class( sample_count, var_count, samples,
13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                          _storage, kernel, alpha, si ) :
13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         svm_type == EPS_SVR ? solver->solve_eps_svr( sample_count, var_count, samples, (float*)_responses,
13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                      _storage, kernel, alpha, si ) :
13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         svm_type == NU_SVR ? solver->solve_nu_svr( sample_count, var_count, samples, (float*)_responses,
13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                    _storage, kernel, alpha, si ) : false;
13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    rho = si.rho;
13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVM::do_train( int svm_type, int sample_count, int var_count, const float** samples,
13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const CvMat* responses, CvMemStorage* temp_storage, double* alpha )
13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::do_train" );
13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMDecisionFunc* df = 0;
13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int sample_size = var_count*sizeof(samples[0][0]);
13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, j, k;
13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == ONE_CLASS || svm_type == EPS_SVR || svm_type == NU_SVR )
13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int sv_count = 0;
13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( decision_func = df =
13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (CvSVMDecisionFunc*)cvAlloc( sizeof(df[0]) ));
13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        df->rho = 0;
13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !train1( sample_count, var_count, samples, svm_type == ONE_CLASS ? 0 :
13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            responses->data.i, 0, 0, temp_storage, alpha, df->rho ))
13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < sample_count; i++ )
13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sv_count += fabs(alpha[i]) > 0;
13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sv_total = df->sv_count = sv_count;
13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( df->alpha = (double*)cvMemStorageAlloc( storage, sv_count*sizeof(df->alpha[0])) );
13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( sv = (float**)cvMemStorageAlloc( storage, sv_count*sizeof(sv[0])));
13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = k = 0; i < sample_count; i++ )
13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fabs(alpha[i]) > 0 )
13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( sv[k] = (float*)cvMemStorageAlloc( storage, sample_size ));
13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( sv[k], samples[i], sample_size );
13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                df->alpha[k++] = alpha[i];
13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int class_count = class_labels->cols;
13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* sv_tab = 0;
13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const float** temp_samples = 0;
13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* class_ranges = 0;
13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        schar* temp_y = 0;
13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        assert( svm_type == CvSVM::C_SVC || svm_type == CvSVM::NU_SVC );
13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( svm_type == CvSVM::C_SVC && params.class_weights )
13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvMat* cw = params.class_weights;
13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !CV_IS_MAT(cw) || cw->cols != 1 && cw->rows != 1 ||
13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cw->rows + cw->cols - 1 != class_count ||
13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_MAT_TYPE(cw->type) != CV_32FC1 && CV_MAT_TYPE(cw->type) != CV_64FC1 )
13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "params.class_weights must be 1d floating-point vector "
13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    "containing as many elements as the number of classes" );
13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( class_weights = cvCreateMat( cw->rows, cw->cols, CV_64F ));
13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvConvert( cw, class_weights ));
13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvScale( class_weights, class_weights, params.C ));
13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( decision_func = df = (CvSVMDecisionFunc*)cvAlloc(
13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (class_count*(class_count-1)/2)*sizeof(df[0])));
13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( sv_tab = (int*)cvMemStorageAlloc( temp_storage, sample_count*sizeof(sv_tab[0]) ));
13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( sv_tab, 0, sample_count*sizeof(sv_tab[0]) );
13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( class_ranges = (int*)cvMemStorageAlloc( temp_storage,
13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            (class_count + 1)*sizeof(class_ranges[0])));
13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( temp_samples = (const float**)cvMemStorageAlloc( temp_storage,
13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            sample_count*sizeof(temp_samples[0])));
13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( temp_y = (schar*)cvMemStorageAlloc( temp_storage, sample_count));
13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        class_ranges[class_count] = 0;
13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSortSamplesByClasses( samples, responses, class_ranges, 0 );
13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //check that while cross-validation there were the samples from all the classes
13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( class_ranges[class_count] <= 0 )
13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsBadArg, "While cross-validation one or more of the classes have "
13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            "been fell out of the sample. Try to enlarge <CvSVMParams::k_fold>" );
13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( svm_type == NU_SVC )
14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // check if nu is feasible
14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for(i = 0; i < class_count; i++ )
14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int ci = class_ranges[i+1] - class_ranges[i];
14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( j = i+1; j< class_count; j++ )
14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    int cj = class_ranges[j+1] - class_ranges[j];
14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( params.nu*(ci + cj)*0.5 > MIN( ci, cj ) )
14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        // !!!TODO!!! add some diagnostic
14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        EXIT; // exit immediately; will release the model and return NULL pointer
14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // train n*(n-1)/2 classifiers
14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < class_count; i++ )
14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = i+1; j < class_count; j++, df++ )
14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int si = class_ranges[i], ci = class_ranges[i+1] - si;
14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int sj = class_ranges[j], cj = class_ranges[j+1] - sj;
14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double Cp = params.C, Cn = Cp;
14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int k1 = 0, sv_count = 0;
14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < ci; k++ )
14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    temp_samples[k] = samples[si + k];
14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    temp_y[k] = 1;
14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < cj; k++ )
14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    temp_samples[ci + k] = samples[sj + k];
14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    temp_y[ci + k] = -1;
14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( class_weights )
14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    Cp = class_weights->data.db[i];
14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    Cn = class_weights->data.db[j];
14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( !train1( ci + cj, var_count, temp_samples, temp_y,
14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                             Cp, Cn, temp_storage, alpha, df->rho ))
14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    EXIT;
14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < ci + cj; k++ )
14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sv_count += fabs(alpha[k]) > 0;
14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                df->sv_count = sv_count;
14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( df->alpha = (double*)cvMemStorageAlloc( temp_storage,
14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                sv_count*sizeof(df->alpha[0])));
14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( df->sv_index = (int*)cvMemStorageAlloc( temp_storage,
14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                sv_count*sizeof(df->sv_index[0])));
14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < ci; k++ )
14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( fabs(alpha[k]) > 0 )
14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sv_tab[si + k] = 1;
14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        df->sv_index[k1] = si + k;
14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        df->alpha[k1++] = alpha[k];
14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < cj; k++ )
14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( fabs(alpha[ci + k]) > 0 )
14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sv_tab[sj + k] = 1;
14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        df->sv_index[k1] = sj + k;
14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        df->alpha[k1++] = alpha[ci + k];
14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // allocate support vectors and initialize sv_tab
14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0, k = 0; i < sample_count; i++ )
14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( sv_tab[i] )
14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sv_tab[i] = ++k;
14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sv_total = k;
14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( sv = (float**)cvMemStorageAlloc( storage, sv_total*sizeof(sv[0])));
14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0, k = 0; i < sample_count; i++ )
14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( sv_tab[i] )
14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL( sv[k] = (float*)cvMemStorageAlloc( storage, sample_size ));
14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                memcpy( sv[k], samples[i], sample_size );
14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                k++;
14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        df = (CvSVMDecisionFunc*)decision_func;
15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // set sv pointers
15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < class_count; i++ )
15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = i+1; j < class_count; j++, df++ )
15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < df->sv_count; k++ )
15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    df->sv_index[k] = sv_tab[df->sv_index[k]]-1;
15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    assert( (unsigned)df->sv_index[k] < (unsigned)sv_total );
15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = true;
15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVM::train( const CvMat* _train_data, const CvMat* _responses,
15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _var_idx, const CvMat* _sample_idx, CvSVMParams _params )
15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* responses = 0;
15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* temp_storage = 0;
15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float** samples = 0;
15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::train" );
15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int svm_type, sample_count, var_count, sample_size;
15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int block_size = 1 << 16;
15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double* alpha;
15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( set_params( _params ));
15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type = _params.svm_type;
15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* Prepare training data and related parameters */
15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvPrepareTrainData( "CvSVM::train", _train_data, CV_ROW_SAMPLE,
15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 svm_type != CvSVM::ONE_CLASS ? _responses : 0,
15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 svm_type == CvSVM::C_SVC ||
15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 svm_type == CvSVM::NU_SVC ? CV_VAR_CATEGORICAL :
15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CV_VAR_ORDERED, _var_idx, _sample_idx,
15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 false, &samples, &sample_count, &var_count, &var_all,
15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 &responses, &class_labels, &var_idx ));
15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sample_size = var_count*sizeof(samples[0][0]);
15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // make the storage block size large enough to fit all
15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // the temporary vectors and output support vectors.
15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sample_count*(int)sizeof(CvSVMKernelRow));
15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sample_count*2*(int)sizeof(double) + 1024 );
15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sample_size*2 + 1024 );
15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( storage = cvCreateMemStorage(block_size));
15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( temp_storage = cvCreateChildMemStorage(storage));
15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( alpha = (double*)cvMemStorageAlloc(temp_storage, sample_count*sizeof(double)));
15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create_kernel();
15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create_solver();
15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !do_train( svm_type, sample_count, var_count, samples, responses, temp_storage, alpha ))
15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
15736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ok = true; // model has been trained succesfully
15756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
15776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete solver;
15796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    solver = 0;
15806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage( &temp_storage );
15816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &responses );
15826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &samples );
15836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 || !ok )
15856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        clear();
15866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
15886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
15896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
15906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool CvSVM::train_auto( const CvMat* _train_data, const CvMat* _responses,
15916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvMat* _var_idx, const CvMat* _sample_idx, CvSVMParams _params, int k_fold,
15926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvParamGrid C_grid, CvParamGrid gamma_grid, CvParamGrid p_grid,
15936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvParamGrid nu_grid, CvParamGrid coef_grid, CvParamGrid degree_grid )
15946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
15956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool ok = false;
15966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* responses = 0;
15976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* responses_local = 0;
15986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMemStorage* temp_storage = 0;
15996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float** samples = 0;
16006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const float** samples_local = 0;
16016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::train_auto" );
16036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
16046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int svm_type, sample_count, var_count, sample_size;
16066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int block_size = 1 << 16;
16076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double* alpha;
16086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, k;
16096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvRNG rng = cvRNG(-1);
16106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // all steps are logarithmic and must be > 1
16126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double degree_step = 10, g_step = 10, coef_step = 10, C_step = 10, nu_step = 10, p_step = 10;
16136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double gamma = 0, C = 0, degree = 0, coef = 0, p = 0, nu = 0;
16146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double best_degree = 0, best_gamma = 0, best_coef = 0, best_C = 0, best_nu = 0, best_p = 0;
16156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float min_error = FLT_MAX, error;
16166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( _params.svm_type == CvSVM::ONE_CLASS )
16186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(!train( _train_data, _responses, _var_idx, _sample_idx, _params ))
16206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
16216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return true;
16226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
16256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( k_fold < 2 )
16276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "Parameter <k_fold> must be > 1" );
16286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(set_params( _params ));
16306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type = _params.svm_type;
16316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // All the parameters except, possibly, <coef0> are positive.
16336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // <coef0> is nonnegative
16346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( C_grid.step <= 1 )
16356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_grid.min_val = C_grid.max_val = params.C;
16376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_grid.step = 10;
16386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL(C_grid.check());
16416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( gamma_grid.step <= 1 )
16436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        gamma_grid.min_val = gamma_grid.max_val = params.gamma;
16456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        gamma_grid.step = 10;
16466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL(gamma_grid.check());
16496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( p_grid.step <= 1 )
16516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p_grid.min_val = p_grid.max_val = params.p;
16536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p_grid.step = 10;
16546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL(p_grid.check());
16576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( nu_grid.step <= 1 )
16596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nu_grid.min_val = nu_grid.max_val = params.nu;
16616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nu_grid.step = 10;
16626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL(nu_grid.check());
16656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( coef_grid.step <= 1 )
16676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coef_grid.min_val = coef_grid.max_val = params.coef0;
16696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coef_grid.step = 10;
16706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL(coef_grid.check());
16736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( degree_grid.step <= 1 )
16756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
16766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        degree_grid.min_val = degree_grid.max_val = params.degree;
16776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        degree_grid.step = 10;
16786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
16796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
16806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL(degree_grid.check());
16816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // these parameters are not used:
16836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( params.kernel_type != CvSVM::POLY )
16846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        degree_grid.min_val = degree_grid.max_val = params.degree;
16856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( params.kernel_type == CvSVM::LINEAR )
16866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        gamma_grid.min_val = gamma_grid.max_val = params.gamma;
16876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( params.kernel_type != CvSVM::POLY && params.kernel_type != CvSVM::SIGMOID )
16886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coef_grid.min_val = coef_grid.max_val = params.coef0;
16896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::NU_SVC || svm_type == CvSVM::ONE_CLASS )
16906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_grid.min_val = C_grid.max_val = params.C;
16916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::C_SVC || svm_type == CvSVM::EPS_SVR )
16926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nu_grid.min_val = nu_grid.max_val = params.nu;
16936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type != CvSVM::EPS_SVR )
16946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p_grid.min_val = p_grid.max_val = params.p;
16956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ASSERT( g_step > 1 && degree_step > 1 && coef_step > 1);
16976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_ASSERT( p_step > 1 && C_step > 1 && nu_step > 1 );
16986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
16996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    /* Prepare training data and related parameters */
17006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(cvPrepareTrainData( "CvSVM::train_auto", _train_data, CV_ROW_SAMPLE,
17016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 svm_type != CvSVM::ONE_CLASS ? _responses : 0,
17026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 svm_type == CvSVM::C_SVC ||
17036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 svm_type == CvSVM::NU_SVC ? CV_VAR_CATEGORICAL :
17046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 CV_VAR_ORDERED, _var_idx, _sample_idx,
17056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 false, &samples, &sample_count, &var_count, &var_all,
17066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 &responses, &class_labels, &var_idx ));
17076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sample_size = var_count*sizeof(samples[0][0]);
17096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // make the storage block size large enough to fit all
17116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // the temporary vectors and output support vectors.
17126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sample_count*(int)sizeof(CvSVMKernelRow));
17136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sample_count*2*(int)sizeof(double) + 1024 );
17146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sample_size*2 + 1024 );
17156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(storage = cvCreateMemStorage(block_size));
17176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(temp_storage = cvCreateChildMemStorage(storage));
17186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(alpha = (double*)cvMemStorageAlloc(temp_storage, sample_count*sizeof(double)));
17196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create_kernel();
17216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create_solver();
17226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int testset_size = sample_count/k_fold;
17256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int trainset_size = sample_count - testset_size;
17266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int last_testset_size = sample_count - testset_size*(k_fold-1);
17276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const int last_trainset_size = sample_count - last_testset_size;
17286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const bool is_regression = (svm_type == EPS_SVR) || (svm_type == NU_SVR);
17296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size_t resp_elem_size = CV_ELEM_SIZE(responses->type);
17316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size_t size = 2*last_trainset_size*sizeof(samples[0]);
17326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    samples_local = (const float**) cvAlloc( size );
17346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( samples_local, 0, size );
17356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    responses_local = cvCreateMat( 1, trainset_size, CV_MAT_TYPE(responses->type) );
17376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvZero( responses_local );
17386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // randomly permute samples and responses
17406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sample_count; i++ )
17416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i1 = cvRandInt( &rng ) % sample_count;
17436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i2 = cvRandInt( &rng ) % sample_count;
17446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const float* temp;
17456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        float t;
17466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int y;
17476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_SWAP( samples[i1], samples[i2], temp );
17496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( is_regression )
17506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_SWAP( responses->data.fl[i1], responses->data.fl[i2], t );
17516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
17526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_SWAP( responses->data.i[i1], responses->data.i[i2], y );
17536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
17546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    C = C_grid.min_val;
17566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    do
17576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
17586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      params.C = C;
17596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      gamma = gamma_grid.min_val;
17606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      do
17616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      {
17626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.gamma = gamma;
17636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p = p_grid.min_val;
17646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        do
17656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
17666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          params.p = p;
17676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          nu = nu_grid.min_val;
17686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          do
17696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          {
17706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            params.nu = nu;
17716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            coef = coef_grid.min_val;
17726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            do
17736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
17746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              params.coef0 = coef;
17756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              degree = degree_grid.min_val;
17766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              do
17776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              {
17786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                params.degree = degree;
17796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                float** test_samples_ptr = (float**)samples;
17816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                uchar* true_resp = responses->data.ptr;
17826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int test_size = testset_size;
17836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int train_size = trainset_size;
17846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                error = 0;
17866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < k_fold; k++ )
17876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
17886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( samples_local, samples, sizeof(samples[0])*test_size*k );
17896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( samples_local + test_size*k, test_samples_ptr + test_size,
17906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sizeof(samples[0])*(sample_count - testset_size*(k+1)) );
17916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( responses_local->data.ptr, responses->data.ptr, resp_elem_size*test_size*k );
17936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    memcpy( responses_local->data.ptr + resp_elem_size*test_size*k,
17946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        true_resp + resp_elem_size*test_size,
17956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        sizeof(samples[0])*(sample_count - testset_size*(k+1)) );
17966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
17976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( k == k_fold - 1 )
17986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
17996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        test_size = last_testset_size;
18006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        train_size = last_trainset_size;
18016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        responses_local->cols = last_trainset_size;
18026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
18036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Train SVM on <train_size> samples
18056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if( !do_train( svm_type, train_size, var_count,
18066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        (const float**)samples_local, responses_local, temp_storage, alpha ) )
18076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        EXIT;
18086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Compute test set error on <test_size> samples
18106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    CvMat s = cvMat( 1, var_count, CV_32FC1 );
18116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for( i = 0; i < test_size; i++, true_resp += resp_elem_size, test_samples_ptr++ )
18126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
18136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        float resp;
18146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        s.data.fl = *test_samples_ptr;
18156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        resp = predict( &s );
18166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        error += is_regression ? powf( resp - *(float*)true_resp, 2 )
18176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            : ((int)resp != *(int*)true_resp);
18186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
18196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( min_error > error )
18216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
18226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    min_error   = error;
18236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_degree = degree;
18246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_gamma  = gamma;
18256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_coef   = coef;
18266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_C      = C;
18276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_nu     = nu;
18286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_p      = p;
18296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
18306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                degree *= degree_grid.step;
18316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              }
18326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              while( degree < degree_grid.max_val );
18336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              coef *= coef_grid.step;
18346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
18356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            while( coef < coef_grid.max_val );
18366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            nu *= nu_grid.step;
18376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          }
18386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          while( nu < nu_grid.max_val );
18396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          p *= p_grid.step;
18406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
18416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while( p < p_grid.max_val );
18426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        gamma *= gamma_grid.step;
18436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
18446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      while( gamma < gamma_grid.max_val );
18456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      C *= C_grid.step;
18466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    while( C < C_grid.max_val );
18486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
18496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    min_error /= (float) sample_count;
18516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.C      = best_C;
18536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.nu     = best_nu;
18546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.p      = best_p;
18556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.gamma  = best_gamma;
18566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.degree = best_degree;
18576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    params.coef0  = best_coef;
18586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(ok = do_train( svm_type, sample_count, var_count, samples, responses, temp_storage, alpha ));
18606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
18626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete solver;
18646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    solver = 0;
18656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMemStorage( &temp_storage );
18666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &responses );
18676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat( &responses_local );
18686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &samples );
18696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvFree( &samples_local );
18706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 || !ok )
18726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        clear();
18736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ok;
18756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
18766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat CvSVM::predict( const CvMat* sample ) const
18786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
18796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool local_alloc = 0;
18806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float result = 0;
18816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float* row_sample = 0;
18826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Qfloat* buffer = 0;
18836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::predict" );
18856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
18876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int class_count;
18896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int var_count, buf_sz;
18906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !kernel )
18926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "The SVM should be trained first" );
18936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_count = class_labels ? class_labels->cols :
18956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  params.svm_type == ONE_CLASS ? 1 : 0;
18966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
18976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvPreparePredictData( sample, var_all, var_idx,
18986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   class_count, 0, &row_sample ));
18996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_count = get_var_count();
19016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buf_sz = sv_total*sizeof(buffer[0]) + (class_count+1)*sizeof(int);
19036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( buf_sz <= CV_MAX_LOCAL_SIZE )
19046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
19056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( buffer = (Qfloat*)cvStackAlloc( buf_sz ));
19066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        local_alloc = 1;
19076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
19096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( buffer = (Qfloat*)cvAlloc( buf_sz ));
19106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( params.svm_type == EPS_SVR ||
19126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.svm_type == NU_SVR ||
19136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        params.svm_type == ONE_CLASS )
19146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
19156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSVMDecisionFunc* df = (CvSVMDecisionFunc*)decision_func;
19166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, sv_count = df->sv_count;
19176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        double sum = -df->rho;
19186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel->calc( sv_count, var_count, (const float**)sv, row_sample, buffer );
19206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < sv_count; i++ )
19216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sum += buffer[i]*df->alpha[i];
19226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        result = params.svm_type == ONE_CLASS ? (float)(sum > 0) : (float)sum;
19246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( params.svm_type == C_SVC ||
19266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn             params.svm_type == NU_SVC )
19276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
19286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSVMDecisionFunc* df = (CvSVMDecisionFunc*)decision_func;
19296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int* vote = (int*)(buffer + sv_total);
19306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i, j, k;
19316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memset( vote, 0, class_count*sizeof(vote[0]));
19336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel->calc( sv_total, var_count, (const float**)sv, row_sample, buffer );
19346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 0; i < class_count; i++ )
19366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = i+1; j < class_count; j++, df++ )
19386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
19396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                double sum = -df->rho;
19406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int sv_count = df->sv_count;
19416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                for( k = 0; k < sv_count; k++ )
19426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    sum += df->alpha[k]*buffer[df->sv_index[k]];
19436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                vote[sum > 0 ? i : j]++;
19456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
19466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = 1, k = 0; i < class_count; i++ )
19496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
19506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( vote[i] > vote[k] )
19516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                k = i;
19526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
19536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        result = (float)(class_labels->data.i[k]);
19556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
19566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
19576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "INTERNAL ERROR: Unknown SVM type, "
19586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                "the SVM structure is probably corrupted" );
19596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
19616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( sample && (!CV_IS_MAT(sample) || sample->data.fl != row_sample) )
19636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &row_sample );
19646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !local_alloc )
19666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &buffer );
19676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return result;
19696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
19706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::write_params( CvFileStorage* fs )
19736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
19746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //CV_FUNCNAME( "CvSVM::write_params" );
19756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
19776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int svm_type = params.svm_type;
19796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int kernel_type = params.kernel_type;
19806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* svm_type_str =
19826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::C_SVC ? "C_SVC" :
19836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::NU_SVC ? "NU_SVC" :
19846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::ONE_CLASS ? "ONE_CLASS" :
19856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::EPS_SVR ? "EPS_SVR" :
19866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::NU_SVR ? "NU_SVR" : 0;
19876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char* kernel_type_str =
19886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type == CvSVM::LINEAR ? "LINEAR" :
19896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type == CvSVM::POLY ? "POLY" :
19906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type == CvSVM::RBF ? "RBF" :
19916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type == CvSVM::SIGMOID ? "SIGMOID" : 0;
19926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type_str )
19946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteString( fs, "svm_type", svm_type_str );
19956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
19966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "svm_type", svm_type );
19976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
19986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // save kernel
19996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "kernel", CV_NODE_MAP + CV_NODE_FLOW );
20006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type_str )
20026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteString( fs, "type", kernel_type_str );
20036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
20046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "type", kernel_type );
20056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type == CvSVM::POLY || !kernel_type_str )
20076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "degree", params.degree );
20086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type != CvSVM::LINEAR || !kernel_type_str )
20106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "gamma", params.gamma );
20116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel_type == CvSVM::POLY || kernel_type == CvSVM::SIGMOID || !kernel_type_str )
20136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "coef0", params.coef0 );
20146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct(fs);
20166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::C_SVC || svm_type == CvSVM::EPS_SVR ||
20186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::NU_SVR || !svm_type_str )
20196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "C", params.C );
20206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::NU_SVC || svm_type == CvSVM::ONE_CLASS ||
20226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type == CvSVM::NU_SVR || !svm_type_str )
20236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "nu", params.nu );
20246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::EPS_SVR || !svm_type_str )
20266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "p", params.p );
20276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "term_criteria", CV_NODE_MAP + CV_NODE_FLOW );
20296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( params.term_crit.type & CV_TERMCRIT_EPS )
20306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "epsilon", params.term_crit.epsilon );
20316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( params.term_crit.type & CV_TERMCRIT_ITER )
20326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "iterations", params.term_crit.max_iter );
20336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
20346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
20366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
20376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::write( CvFileStorage* fs, const char* name )
20406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
20416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::write" );
20426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
20446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, var_count = get_var_count(), df_count, class_count;
20466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSVMDecisionFunc* df = decision_func;
20476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_ML_SVM );
20496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    write_params( fs );
20516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "var_all", var_all );
20536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "var_count", var_count );
20546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_count = class_labels ? class_labels->cols :
20566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  params.svm_type == CvSVM::ONE_CLASS ? 1 : 0;
20576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( class_count )
20596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "class_count", class_count );
20616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( class_labels )
20636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWrite( fs, "class_labels", class_labels );
20646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( class_weights )
20666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWrite( fs, "class_weights", class_weights );
20676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( var_idx )
20706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWrite( fs, "var_idx", var_idx );
20716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // write the joint collection of support vectors
20736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvWriteInt( fs, "sv_total", sv_total );
20746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "support_vectors", CV_NODE_SEQ );
20756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sv_total; i++ )
20766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartWriteStruct( fs, 0, CV_NODE_SEQ + CV_NODE_FLOW );
20786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, sv[i], var_count, "f" );
20796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
20806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
20816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
20836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // write decision functions
20856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    df_count = class_count > 1 ? class_count*(class_count-1)/2 : 1;
20866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    df = decision_func;
20876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
20886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartWriteStruct( fs, "decision_functions", CV_NODE_SEQ );
20896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < df_count; i++ )
20906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
20916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int sv_count = df[i].sv_count;
20926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartWriteStruct( fs, 0, CV_NODE_MAP );
20936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteInt( fs, "sv_count", sv_count );
20946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteReal( fs, "rho", df[i].rho );
20956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvStartWriteStruct( fs, "alpha", CV_NODE_SEQ+CV_NODE_FLOW );
20966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvWriteRawData( fs, df[i].alpha, df[i].sv_count, "d" );
20976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
20986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( class_count > 1 )
20996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
21006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvStartWriteStruct( fs, "index", CV_NODE_SEQ+CV_NODE_FLOW );
21016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvWriteRawData( fs, df[i].sv_index, df[i].sv_count, "i" );
21026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            cvEndWriteStruct( fs );
21036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
21046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
21056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ASSERT( sv_count == sv_total );
21066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvEndWriteStruct( fs );
21076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
21096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvEndWriteStruct( fs );
21106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
21126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::read_params( CvFileStorage* fs, CvFileNode* svm_node )
21166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::read_params" );
21186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
21206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int svm_type, kernel_type;
21226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMParams _params;
21236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* tmp_node = cvGetFileNodeByName( fs, svm_node, "svm_type" );
21256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode* kernel_node;
21266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !tmp_node )
21276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "svm_type tag is not found" );
21286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_TYPE(tmp_node->tag) == CV_NODE_INT )
21306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type = cvReadInt( tmp_node, -1 );
21316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
21326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* svm_type_str = cvReadString( tmp_node, "" );
21346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_type =
21356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( svm_type_str, "C_SVC" ) == 0 ? CvSVM::C_SVC :
21366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( svm_type_str, "NU_SVC" ) == 0 ? CvSVM::NU_SVC :
21376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( svm_type_str, "ONE_CLASS" ) == 0 ? CvSVM::ONE_CLASS :
21386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( svm_type_str, "EPS_SVR" ) == 0 ? CvSVM::EPS_SVR :
21396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( svm_type_str, "NU_SVR" ) == 0 ? CvSVM::NU_SVR : -1;
21406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( svm_type < 0 )
21426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "Missing of invalid SVM type" );
21436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel_node = cvGetFileNodeByName( fs, svm_node, "kernel" );
21466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !kernel_node )
21476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "SVM kernel tag is not found" );
21486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_node = cvGetFileNodeByName( fs, kernel_node, "type" );
21506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !tmp_node )
21516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "SVM kernel type tag is not found" );
21526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_NODE_TYPE(tmp_node->tag) == CV_NODE_INT )
21546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type = cvReadInt( tmp_node, -1 );
21556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
21566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const char* kernel_type_str = cvReadString( tmp_node, "" );
21586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        kernel_type =
21596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( kernel_type_str, "LINEAR" ) == 0 ? CvSVM::LINEAR :
21606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( kernel_type_str, "POLY" ) == 0 ? CvSVM::POLY :
21616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( kernel_type_str, "RBF" ) == 0 ? CvSVM::RBF :
21626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            strcmp( kernel_type_str, "SIGMOID" ) == 0 ? CvSVM::SIGMOID : -1;
21636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( kernel_type < 0 )
21656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "Missing of invalid SVM kernel type" );
21666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.svm_type = svm_type;
21696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.kernel_type = kernel_type;
21706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.degree = cvReadRealByName( fs, kernel_node, "degree", 0 );
21716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.gamma = cvReadRealByName( fs, kernel_node, "gamma", 0 );
21726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.coef0 = cvReadRealByName( fs, kernel_node, "coef0", 0 );
21736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.C = cvReadRealByName( fs, svm_node, "C", 0 );
21756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.nu = cvReadRealByName( fs, svm_node, "nu", 0 );
21766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.p = cvReadRealByName( fs, svm_node, "p", 0 );
21776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    _params.class_weights = 0;
21786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    tmp_node = cvGetFileNodeByName( fs, svm_node, "term_criteria" );
21806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( tmp_node )
21816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
21826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _params.term_crit.epsilon = cvReadRealByName( fs, tmp_node, "epsilon", -1. );
21836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _params.term_crit.max_iter = cvReadIntByName( fs, tmp_node, "iterations", -1 );
21846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _params.term_crit.type = (_params.term_crit.epsilon >= 0 ? CV_TERMCRIT_EPS : 0) +
21856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               (_params.term_crit.max_iter >= 0 ? CV_TERMCRIT_ITER : 0);
21866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
21876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
21886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        _params.term_crit = cvTermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 1000, FLT_EPSILON );
21896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    set_params( _params );
21916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
21936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
21946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
21966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid CvSVM::read( CvFileStorage* fs, CvFileNode* svm_node )
21976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
21986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const double not_found_dbl = DBL_MAX;
21996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "CvSVM::read" );
22016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
22036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, var_count, df_count, class_count;
22056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int block_size = 1 << 16, sv_size;
22066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvFileNode *sv_node, *df_node;
22076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMDecisionFunc* df;
22086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSeqReader reader;
22096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !svm_node )
22116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "The requested element is not found" );
22126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    clear();
22146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // read SVM parameters
22166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    read_params( fs, svm_node );
22176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // and top-level data
22196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv_total = cvReadIntByName( fs, svm_node, "sv_total", -1 );
22206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_all = cvReadIntByName( fs, svm_node, "var_all", -1 );
22216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_count = cvReadIntByName( fs, svm_node, "var_count", var_all );
22226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_count = cvReadIntByName( fs, svm_node, "class_count", 0 );
22236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( sv_total <= 0 || var_all <= 0 || var_count <= 0 || var_count > var_all || class_count < 0 )
22256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "SVM model data is invalid, check sv_count, var_* and class_count tags" );
22266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( class_labels = (CvMat*)cvReadByName( fs, svm_node, "class_labels" ));
22286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( class_weights = (CvMat*)cvReadByName( fs, svm_node, "class_weights" ));
22296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( var_idx = (CvMat*)cvReadByName( fs, svm_node, "comp_idx" ));
22306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( class_count > 1 && (!class_labels ||
22326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_IS_MAT(class_labels) || class_labels->cols != class_count))
22336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "Array of class labels is missing or invalid" );
22346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( var_count < var_all && (!var_idx || !CV_IS_MAT(var_idx) || var_idx->cols != var_count) )
22366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "var_idx array is missing or invalid" );
22376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // read support vectors
22396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv_node = cvGetFileNodeByName( fs, svm_node, "support_vectors" );
22406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !sv_node || !CV_NODE_IS_SEQ(sv_node->tag))
22416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "Missing or invalid sequence of support vectors" );
22426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sv_total*(int)sizeof(CvSVMKernelRow));
22446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, sv_total*2*(int)sizeof(double));
22456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    block_size = MAX( block_size, var_all*(int)sizeof(double));
22466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( storage = cvCreateMemStorage( block_size ));
22476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( sv = (float**)cvMemStorageAlloc( storage,
22486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                sv_total*sizeof(sv[0]) ));
22496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( cvStartReadSeq( sv_node->data.seq, &reader, 0 ));
22516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv_size = var_count*sizeof(sv[0][0]);
22526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sv_total; i++ )
22546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* sv_elem = (CvFileNode*)reader.ptr;
22566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ASSERT( var_count == 1 || (CV_NODE_IS_SEQ(sv_elem->tag) &&
22576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   sv_elem->data.seq->total == var_count) );
22586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( sv[i] = (float*)cvMemStorageAlloc( storage, sv_size ));
22606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvReadRawData( fs, sv_elem, sv[i], "f" ));
22616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( sv_node->data.seq->elem_size, reader );
22626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
22636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // read decision functions
22656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    df_count = class_count > 1 ? class_count*(class_count-1)/2 : 1;
22666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    df_node = cvGetFileNodeByName( fs, svm_node, "decision_functions" );
22676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !df_node || !CV_NODE_IS_SEQ(df_node->tag) ||
22686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        df_node->data.seq->total != df_count )
22696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsParseError, "decision_functions is missing or is not a collection "
22706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  "or has a wrong number of elements" );
22716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( df = decision_func = (CvSVMDecisionFunc*)cvAlloc( df_count*sizeof(df[0]) ));
22736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvStartReadSeq( df_node->data.seq, &reader, 0 );
22746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < df_count; i++ )
22766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
22776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* df_elem = (CvFileNode*)reader.ptr;
22786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvFileNode* alpha_node = cvGetFileNodeByName( fs, df_elem, "alpha" );
22796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int sv_count = cvReadIntByName( fs, df_elem, "sv_count", -1 );
22816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( sv_count <= 0 )
22826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "sv_count is missing or non-positive" );
22836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        df[i].sv_count = sv_count;
22846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        df[i].rho = cvReadRealByName( fs, df_elem, "rho", not_found_dbl );
22866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( fabs(df[i].rho - not_found_dbl) < DBL_EPSILON )
22876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "rho is missing" );
22886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !alpha_node )
22906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ERROR( CV_StsParseError, "alpha is missing in the decision function" );
22916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( df[i].alpha = (double*)cvMemStorageAlloc( storage,
22936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        sv_count*sizeof(df[i].alpha[0])));
22946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ASSERT( sv_count == 1 || CV_NODE_IS_SEQ(alpha_node->tag) &&
22956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   alpha_node->data.seq->total == sv_count );
22966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( cvReadRawData( fs, alpha_node, df[i].alpha, "d" ));
22976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
22986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( class_count > 1 )
22996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
23006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvFileNode* index_node = cvGetFileNodeByName( fs, df_elem, "index" );
23016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( !index_node )
23026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsParseError, "index is missing in the decision function" );
23036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( df[i].sv_index = (int*)cvMemStorageAlloc( storage,
23046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                            sv_count*sizeof(df[i].sv_index[0])));
23056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_ASSERT( sv_count == 1 || CV_NODE_IS_SEQ(index_node->tag) &&
23066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                   index_node->data.seq->total == sv_count );
23076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( cvReadRawData( fs, index_node, df[i].sv_index, "i" ));
23086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
23096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
23106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            df[i].sv_index = 0;
23116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_NEXT_SEQ_ELEM( df_node->data.seq->elem_size, reader );
23136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    create_kernel();
23166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
23186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
23196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if 0
23216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void*
23236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCloneSVM( const void* _src )
23246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
23256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMModel* dst = 0;
23266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "icvCloneSVM" );
23286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
23306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const CvSVMModel* src = (const CvSVMModel*)_src;
23326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int var_count, class_count;
23336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i, sv_total, df_count;
23346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int sv_size;
23356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_IS_SVM(src) )
23376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( !src ? CV_StsNullPtr : CV_StsBadArg, "Input pointer is NULL or invalid" );
23386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // 0. create initial CvSVMModel structure
23406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dst = icvCreateSVM() );
23416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst->params = src->params;
23426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst->params.weight_labels = 0;
23436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst->params.weights = 0;
23446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    dst->var_all = src->var_all;
23466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src->class_labels )
23476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst->class_labels = cvCloneMat( src->class_labels );
23486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src->class_weights )
23496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst->class_weights = cvCloneMat( src->class_weights );
23506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( src->comp_idx )
23516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        dst->comp_idx = cvCloneMat( src->comp_idx );
23526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    var_count = src->comp_idx ? src->comp_idx->cols : src->var_all;
23546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_count = src->class_labels ? src->class_labels->cols :
23556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  src->params.svm_type == CvSVM::ONE_CLASS ? 1 : 0;
23566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv_total = dst->sv_total = src->sv_total;
23576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dst->storage = cvCreateMemStorage( src->storage->block_size ));
23586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dst->sv = (float**)cvMemStorageAlloc( dst->storage,
23596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    sv_total*sizeof(dst->sv[0]) ));
23606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    sv_size = var_count*sizeof(dst->sv[0][0]);
23626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < sv_total; i++ )
23646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( dst->sv[i] = (float*)cvMemStorageAlloc( dst->storage, sv_size ));
23666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( dst->sv[i], src->sv[i], sv_size );
23676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    df_count = class_count > 1 ? class_count*(class_count-1)/2 : 1;
23706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( dst->decision_func = cvAlloc( df_count*sizeof(CvSVMDecisionFunc) ));
23726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( i = 0; i < df_count; i++ )
23746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
23756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const CvSVMDecisionFunc *sdf =
23766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (const CvSVMDecisionFunc*)src->decision_func+i;
23776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvSVMDecisionFunc *ddf =
23786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            (CvSVMDecisionFunc*)dst->decision_func+i;
23796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int sv_count = sdf->sv_count;
23806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ddf->sv_count = sv_count;
23816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ddf->rho = sdf->rho;
23826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( ddf->alpha = (double*)cvMemStorageAlloc( dst->storage,
23836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        sv_count*sizeof(ddf->alpha[0])));
23846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        memcpy( ddf->alpha, sdf->alpha, sv_count*sizeof(ddf->alpha[0]));
23856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( class_count > 1 )
23876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
23886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_CALL( ddf->sv_index = (int*)cvMemStorageAlloc( dst->storage,
23896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                sv_count*sizeof(ddf->sv_index[0])));
23906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            memcpy( ddf->sv_index, sdf->sv_index, sv_count*sizeof(ddf->sv_index[0]));
23916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
23926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
23936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ddf->sv_index = 0;
23946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
23956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
23976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
23986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( cvGetErrStatus() < 0 && dst )
23996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvReleaseSVM( &dst );
24006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return dst;
24026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int icvRegisterSVMType()
24056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvTypeInfo info;
24076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    memset( &info, 0, sizeof(info) );
24086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.flags = 0;
24106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.header_size = sizeof( info );
24116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.is_instance = icvIsSVM;
24126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.release = (CvReleaseFunc)icvReleaseSVM;
24136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.read = icvReadSVM;
24146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.write = icvWriteSVM;
24156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.clone = icvCloneSVM;
24166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    info.type_name = CV_TYPE_NAME_ML_SVM;
24176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvRegisterType( &info );
24186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 1;
24206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
24216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int svm = icvRegisterSVMType();
24246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* The function trains SVM model with optimal parameters, obtained by using cross-validation.
24266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennThe parameters to be estimated should be indicated by setting theirs values to FLT_MAX.
24276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennThe optimal parameters are saved in <model_params> */
24286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvStatModel*
24296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvTrainSVM_CrossValidation( const CvMat* train_data, int tflag,
24306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvMat* responses,
24316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CvStatModelParams* model_params,
24326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvStatModelParams* cross_valid_params,
24336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvMat* comp_idx,
24346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvMat* sample_idx,
24356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvParamGrid* degree_grid,
24366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvParamGrid* gamma_grid,
24376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvParamGrid* coef_grid,
24386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvParamGrid* C_grid,
24396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvParamGrid* nu_grid,
24406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const CvParamGrid* p_grid )
24416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
24426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvStatModel* svm = 0;
24436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME("cvTainSVMCrossValidation");
24456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
24466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double degree_step = 7,
24486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	       g_step      = 15,
24496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		   coef_step   = 14,
24506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		   C_step      = 20,
24516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		   nu_step     = 5,
24526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn		   p_step      = 7; // all steps must be > 1
24536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double degree_begin = 0.01, degree_end = 2;
24546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double g_begin      = 1e-5, g_end      = 0.5;
24556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double coef_begin   = 0.1,  coef_end   = 300;
24566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double C_begin      = 0.1,  C_end      = 6000;
24576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double nu_begin     = 0.01,  nu_end    = 0.4;
24586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double p_begin      = 0.01, p_end      = 100;
24596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double rate = 0, gamma = 0, C = 0, degree = 0, coef = 0, p = 0, nu = 0;
24616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	double best_rate    = 0;
24636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double best_degree  = degree_begin;
24646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double best_gamma   = g_begin;
24656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double best_coef    = coef_begin;
24666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	double best_C       = C_begin;
24676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn	double best_nu      = nu_begin;
24686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double best_p       = p_begin;
24696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvSVMModelParams svm_params, *psvm_params;
24716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvCrossValidationParams* cv_params = (CvCrossValidationParams*)cross_valid_params;
24726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int svm_type, kernel;
24736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int is_regression;
24746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !model_params )
24766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
24776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !cv_params )
24786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsBadArg, "" );
24796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params = *(CvSVMModelParams*)model_params;
24816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params = (CvSVMModelParams*)model_params;
24826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_type = svm_params.svm_type;
24836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    kernel = svm_params.kernel_type;
24846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params.degree = svm_params.degree > 0 ? svm_params.degree : 1;
24866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params.gamma = svm_params.gamma > 0 ? svm_params.gamma : 1;
24876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params.coef0 = svm_params.coef0 > 0 ? svm_params.coef0 : 1e-6;
24886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params.C = svm_params.C > 0 ? svm_params.C : 1;
24896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params.nu = svm_params.nu > 0 ? svm_params.nu : 1;
24906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    svm_params.p = svm_params.p > 0 ? svm_params.p : 1;
24916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
24926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( degree_grid )
24936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
24946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !(degree_grid->max_val == 0 && degree_grid->min_val == 0 &&
24956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              degree_grid->step == 0) )
24966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
24976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( degree_grid->min_val > degree_grid->max_val )
24986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,
24996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "low bound of grid should be less then the upper one");
25006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( degree_grid->step <= 1 )
25016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "grid step should be greater 1" );
25026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            degree_begin = degree_grid->min_val;
25036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            degree_end   = degree_grid->max_val;
25046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            degree_step  = degree_grid->step;
25056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        degree_begin = degree_end = svm_params.degree;
25096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( gamma_grid )
25116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !(gamma_grid->max_val == 0 && gamma_grid->min_val == 0 &&
25136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              gamma_grid->step == 0) )
25146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( gamma_grid->min_val > gamma_grid->max_val )
25166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,
25176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "low bound of grid should be less then the upper one");
25186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( gamma_grid->step <= 1 )
25196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "grid step should be greater 1" );
25206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            g_begin = gamma_grid->min_val;
25216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            g_end   = gamma_grid->max_val;
25226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            g_step  = gamma_grid->step;
25236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        g_begin = g_end = svm_params.gamma;
25276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( coef_grid )
25296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !(coef_grid->max_val == 0 && coef_grid->min_val == 0 &&
25316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              coef_grid->step == 0) )
25326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( coef_grid->min_val > coef_grid->max_val )
25346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,
25356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "low bound of grid should be less then the upper one");
25366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( coef_grid->step <= 1 )
25376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "grid step should be greater 1" );
25386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            coef_begin = coef_grid->min_val;
25396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            coef_end   = coef_grid->max_val;
25406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            coef_step  = coef_grid->step;
25416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coef_begin = coef_end = svm_params.coef0;
25456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( C_grid )
25476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !(C_grid->max_val == 0 && C_grid->min_val == 0 && C_grid->step == 0))
25496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( C_grid->min_val > C_grid->max_val )
25516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,
25526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "low bound of grid should be less then the upper one");
25536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( C_grid->step <= 1 )
25546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "grid step should be greater 1" );
25556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            C_begin = C_grid->min_val;
25566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            C_end   = C_grid->max_val;
25576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            C_step  = C_grid->step;
25586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_begin = C_end = svm_params.C;
25626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( nu_grid )
25646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if(!(nu_grid->max_val == 0 && nu_grid->min_val == 0 && nu_grid->step==0))
25666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( nu_grid->min_val > nu_grid->max_val )
25686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,
25696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "low bound of grid should be less then the upper one");
25706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( nu_grid->step <= 1 )
25716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "grid step should be greater 1" );
25726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            nu_begin = nu_grid->min_val;
25736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            nu_end   = nu_grid->max_val;
25746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            nu_step  = nu_grid->step;
25756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nu_begin = nu_end = svm_params.nu;
25796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( p_grid )
25816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
25826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( !(p_grid->max_val == 0 && p_grid->min_val == 0 && p_grid->step == 0))
25836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
25846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( p_grid->min_val > p_grid->max_val )
25856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg,
25866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                "low bound of grid should be less then the upper one");
25876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( p_grid->step <= 1 )
25886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_ERROR( CV_StsBadArg, "grid step should be greater 1" );
25896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            p_begin = p_grid->min_val;
25906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            p_end   = p_grid->max_val;
25916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            p_step  = p_grid->step;
25926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
25936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
25946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
25956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p_begin = p_end = svm_params.p;
25966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
25976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // these parameters are not used:
25986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel != CvSVM::POLY )
25996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        degree_begin = degree_end = svm_params.degree;
26006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   if( kernel == CvSVM::LINEAR )
26026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        g_begin = g_end = svm_params.gamma;
26036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( kernel != CvSVM::POLY && kernel != CvSVM::SIGMOID )
26056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        coef_begin = coef_end = svm_params.coef0;
26066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::NU_SVC || svm_type == CvSVM::ONE_CLASS )
26086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        C_begin = C_end = svm_params.C;
26096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type == CvSVM::C_SVC || svm_type == CvSVM::EPS_SVR )
26116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        nu_begin = nu_end = svm_params.nu;
26126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( svm_type != CvSVM::EPS_SVR )
26146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        p_begin = p_end = svm_params.p;
26156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    is_regression = cv_params->is_regression;
26176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    best_rate = is_regression ? FLT_MAX : 0;
26186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( g_step > 1 && degree_step > 1 && coef_step > 1);
26206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert( p_step > 1 && C_step > 1 && nu_step > 1 );
26216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    for( degree = degree_begin; degree <= degree_end; degree *= degree_step )
26236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
26246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      svm_params.degree = degree;
26256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      //printf("degree = %.3f\n", degree );
26266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for( gamma= g_begin; gamma <= g_end; gamma *= g_step )
26276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      {
26286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        svm_params.gamma = gamma;
26296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //printf("   gamma = %.3f\n", gamma );
26306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( coef = coef_begin; coef <= coef_end; coef *= coef_step )
26316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
26326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          svm_params.coef0 = coef;
26336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          //printf("      coef = %.3f\n", coef );
26346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          for( C = C_begin; C <= C_end; C *= C_step )
26356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          {
26366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            svm_params.C = C;
26376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            //printf("         C = %.3f\n", C );
26386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( nu = nu_begin; nu <= nu_end; nu *= nu_step )
26396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
26406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              svm_params.nu = nu;
26416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              //printf("            nu = %.3f\n", nu );
26426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              for( p = p_begin; p <= p_end; p *= p_step )
26436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              {
26446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                int well;
26456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                svm_params.p = p;
26466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                //printf("               p = %.3f\n", p );
26476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                CV_CALL(rate = cvCrossValidation( train_data, tflag, responses, &cvTrainSVM,
26496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    cross_valid_params, (CvStatModelParams*)&svm_params, comp_idx, sample_idx ));
26506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                well =  rate > best_rate && !is_regression || rate < best_rate && is_regression;
26526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if( well || (rate == best_rate && C < best_C) )
26536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
26546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_rate   = rate;
26556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_degree = degree;
26566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_gamma  = gamma;
26576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_coef   = coef;
26586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_C      = C;
26596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_nu     = nu;
26606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    best_p      = p;
26616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
26626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                //printf("                  rate = %.2f\n", rate );
26636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn              }
26646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
26656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn          }
26666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
26676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
26686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
26696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //printf("The best:\nrate = %.2f%% degree = %f gamma = %f coef = %f c = %f nu = %f p = %f\n",
26706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      //  best_rate, best_degree, best_gamma, best_coef, best_C, best_nu, best_p );
26716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params->C      = best_C;
26736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params->nu     = best_nu;
26746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params->p      = best_p;
26756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params->gamma  = best_gamma;
26766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params->degree = best_degree;
26776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    psvm_params->coef0  = best_coef;
26786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL(svm = cvTrainSVM( train_data, tflag, responses, model_params, comp_idx, sample_idx ));
26806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
26826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return svm;
26846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
26856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
26876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
26886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */
26896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2690