content: /*
   *    This program is free software; you can redistribute it and/or modify
   *    it under the terms of the GNU General Public License as published by
   *    the Free Software Foundation; either version 2 of the License, or
   *    (at your option) any later version.
   *
   *    This program is distributed in the hope that it will be useful,
   *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *    GNU General Public License for more details.
   *
   *    You should have received a copy of the GNU General Public License
   *    along with this program; if not, write to the Free Software
   *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
  /*
   *    NormalizedPolyKernel.java
   *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
   *
   */
  
  package weka.classifiers.functions.supportVector;
  
  import weka.core.Instance;
  import weka.core.Instances;
  import weka.core.RevisionUtils;
  
  /**
   <!-- globalinfo-start -->
   * The normalized polynomial kernel.<br/>
   * K(x,y) = &lt;x,y&gt;/sqrt(&lt;x,x&gt;&lt;y,y&gt;) where &lt;x,y&gt; = PolyKernel(x,y)
   * <p/>
   <!-- globalinfo-end -->
   * 
   <!-- options-start -->
   * Valid options are: <p/>
   * 
   * <pre> -D
   *  Enables debugging output (if available) to be printed.
   *  (default: off)</pre>
   * 
   * <pre> -no-checks
   *  Turns off all checks - use with caution!
   *  (default: checks on)</pre>
   * 
   * <pre> -C &lt;num&gt;
   *  The size of the cache (a prime number), 0 for full cache and 
   *  -1 to turn it off.
   *  (default: 250007)</pre>
   * 
   * <pre> -E &lt;num&gt;
   *  The Exponent to use.
   *  (default: 1.0)</pre>
   * 
   * <pre> -L
   *  Use lower-order terms.
   *  (default: no)</pre>
   * 
   <!-- options-end -->
   *
   * @author Eibe Frank (eibe@cs.waikato.ac.nz)
   * @version $Revision: 1.8 $
   */
  public class NormalizedPolyKernel 
    extends PolyKernel {
  
    /** for serialization */
    static final long serialVersionUID = 1248574185532130851L;
  
    /**
     * default constructor - does nothing
     */
    public NormalizedPolyKernel() {
      super();
  
      setExponent(2.0);
    }
    
    /**
     * Creates a new <code>NormalizedPolyKernel</code> instance.
     *
     * @param dataset	the training dataset used.
     * @param cacheSize	the size of the cache (a prime number)
     * @param exponent	the exponent to use
     * @param lowerOrder	whether to use lower-order terms
     * @throws Exception	if something goes wrong
     */
    public NormalizedPolyKernel(Instances dataset, int cacheSize, 
        double exponent, boolean lowerOrder) throws Exception {
  	
      super(dataset, cacheSize, exponent, lowerOrder);
    }
    
    /**
     * Returns a string describing the kernel
     * 
     * @return a description suitable for displaying in the
     *         explorer/experimenter gui
     */
    public String globalInfo() {
      return 
          "The normalized polynomial kernel.\n"
        + "K(x,y) = <x,y>/sqrt(<x,x><y,y>) where <x,y> = PolyKernel(x,y)";
    }
     
    /**
     * Computes the result of the kernel function for two instances.
     * If id1 == -1, eval use inst1 instead of an instance in the dataset.
     * Redefines the eval function of PolyKernel.
     *
     * @param id1 the index of the first instance in the dataset
     * @param id2 the index of the second instance in the dataset
     * @param inst1 the instance corresponding to id1 (used if id1 == -1)
     * @return the result of the kernel function
     * @throws Exception if something goes wrong
     */
    public double eval(int id1, int id2, Instance inst1) 
      throws Exception {
  
      double div = Math.sqrt(super.eval(id1, id1, inst1) * ((m_keys != null)
                             ? super.eval(id2, id2, m_data.instance(id2))
                             : super.eval(-1, -1, m_data.instance(id2))));
  
      if(div != 0){      
        return super.eval(id1, id2, inst1) / div;
      } else {
        return 0;
      }
    }    
    
    /**
     * Sets the exponent value (must be different from 1.0).
     * 
     * @param value	the exponent value
     */
    public void setExponent(double value) {
      if (value != 1.0)
        super.setExponent(value);
      else
        System.out.println("A linear kernel, i.e., Exponent=1, is not possible!");
    }
    
    /**
     * returns a string representation for the Kernel
     * 
     * @return 		a string representaiton of the kernel
     */
    public String toString() {
      String	result;
      
      if (getUseLowerOrder())
        result = "Normalized Poly Kernel with lower order: K(x,y) = (<x,y>+1)^" + getExponent() + "/" + 
        	       "((<x,x>+1)^" + getExponent() + "*" + "(<y,y>+1)^" + getExponent() + ")^(1/2)";
      else
        result = "Normalized Poly Kernel: K(x,y) = <x,y>^" + getExponent() + "/" + "(<x,x>^" + 
                 getExponent() + "*" + "<y,y>^" + getExponent() + ")^(1/2)";
      
      return result;
    }
    
    /**
     * Returns the revision string.
     * 
     * @return		the revision
     */
    public String getRevision() {
      return RevisionUtils.extract("$Revision: 1.8 $");
    }
  }
  
  