function [w, gamma, obj, time, iters] = asvm(A,D,nu,tol,maxIter,perturb, ...
					     converge, normalize, prompt);
% ASVM Active Set Support Vector Machine methodology
%   ASVM solves a support vector machine problem using an active set
%   methodology. Minimally, it takes the following arguments:
%
%   w = asvm(A,D)
%
%   where A is the data matrix, D is a diagonal matrix of 1s and -1s
%   indicating which class the points are in, and w is the vector of
%   coefficients for the separating hyperplane.
%
%   All the following additional arguments are optional:
%
%   [w, gamma, objective, time, iters] = ...
%     asvm(A,D,nu,tol,maxIter,perturb,converge,normalize,prompt)
%
%   On the right hand side, A and D are required. If the rest are not
%   specified, the following defaults will be used:
%     nu = 1/size(A,1), tol = 1e-5, maxIter = 100, perturb = 0,
%       converge = 1, normalize = 0, prompt = 1
%
%   perturb indicates that all the data should be perturbed by a random
%   amount between 0 and the value given.
%
%   converge should be set to 0 if the optional convergence checking
%   should be ignored. This may lead to the algorithm getting 'stuck.'
%
%   normalize should be set to 1 if the data should be normalized before 
%   training.
%
%   prompt should be set to 0 if ASVM should not prompt the user to stop
%   if the algorithm seems stuck.
%
%   The value -1 can be used for any of the entries (except A and D) to
%   specify that default values should be used.
%
%   For more information, type 'help asvminfo'.
%
%   Copyright (C) 2000 David R. Musicant and Olvi L. Mangasarian.
%   Version 1.0 Beta 1
%   This software is free for academic use only.
%   For commercial use, contact musicant@cs.wisc.edu.

  m = size(A,1);
  e = ones(size(A,1),1);
  
  % If D is a vector, convert it to a diagonal matrix.
  [k,n] = size(D);
  if k==1 | n==1
    D=diag(D);
  end;

  % Check all components of D and verify that they are +-1
  checkall = diag(D)==1 | diag(D)==-1;
  if any(checkall==0)
    error('Error in D: classes must be all 1 or -1.');
  end;
  
  rand('seed',22);
  if exist('perturb')
    A = A + rand(size(A))*perturb;
  end;
  H = D*[A -e];
  if ~exist('nu') | nu==-1
    nu = 1/m;
  end;
  if ~exist('tol') | tol==-1
    tol = 1e-5;
  end;
  if ~exist('maxIter') | maxIter==-1
    maxIter = 100;
  end;
  if ~exist('converge') | converge==-1
    converge = 1;
  end;
  if ~exist('normalize') | normalize==-1
    normalize = 0;
  end;
  if ~exist('prompt') | prompt==-1
    prompt = 1;
  end;
  [w, gamma, obj, time, iters] = ...
      asvmmex(H,nu,tol,maxIter,converge,normalize,prompt);
  if all(w==0) & gamma==0
    disp(sprintf('Degenerate solution obtained. Perturbing and rerunning.'));
    perturb = 0.001;
    A = A + rand(size(A))*perturb;
    H = D*[A -e];
    [w, gamma, obj, time, iters] = asvmmex(H,nu,tol,maxIter,converge,...
					   normalize,prompt);
  end;
  
  return;
