/**
 * Copyright (c) 2015, Jozef Stefan Institute, Quintelligence d.o.o. and contributors
 * All rights reserved.
 *
 * This source code is licensed under the FreeBSD license found in the
 * LICENSE file in the root directory of this source tree.
 */
/**
 * Analytics module.
 * @module analytics
 * @example
 * // import modules
 * var qm = require('qminer');
 * var analytics = qm.analytics;
 * // load dataset, create model, evaluate model
 */
/**
    * Calculates the non-negative matrix factorization, see: {@link https://en.wikipedia.org/wiki/Non-negative_matrix_factorization}.
    * @param {(module:la.Matrix | module:la.SparseMatrix)} mat - The non-negative matrix.
    * @param {number} k - The reduced rank, e.g. number of columns in matrix U and number of rows in matrix V. Must be between 0 and `min(mat.rows, mat.cols)`.
    * @param {Object} [json] - Algorithm options.
    * @param {number} [json.iter = 100] - The number of iterations used for the algorithm.
    * @param {number} [json.tol = 1e-3] - The tolerance.
    * @param {boolean} [json.verbose = false] - If false, the console output is supressed.
    * @returns {Object} The json object `nmfRes` containing the non-negative matrices U and V:
    * <br> `nmfRes.U`- The {@link module:la.Matrix} representation of the matrix U,
    * <br> `nmfRes.V`- The {@link module:la.Matrix} representation of the matrix V.
    * @example <caption>Asynchronous function</caption>
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a matrix
    * var mat = new la.Matrix({ rows: 10, cols: 5, random: true });
    * // compute the non-negative matrix factorization
    * analytics.nmfAsync(mat, 3, { iter: 100, tol: 1e-4 }, function (err, result) {
    *    if (err) { console.log(err); }
    *    // calculation successful
    *    var U = result.U;
    *    var V = result.V;
    * });
    * @example <caption>Synchronous function</caption>
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a matrix
    * var mat = new la.Matrix({ rows: 10, cols: 5, random: true });
    * // compute the non-negative matrix factorization
    * var result = analytics.nmf(mat, 3, { iter: 100, tol: 1e-4 });
    * var U = result.U;
    * var V = result.V;
    */
 exports.prototype.nmf = function (mat, k, json) { return { "U": Object.create(require('qminer').la.Matrix.prototype), "V": Object.create(require('qminer').la.Matrix.prototype) }; }
/**
* @typedef {Object} SVMParam
* SVM constructor parameters. Used for the construction of {@link module:analytics.SVC} and {@link module:analytics.SVR}.
* @property  {string} [algorithm='SGD'] - The algorithm procedure. Possible options are `'SGD'` and `'LIBSVM'`. `'PR_LOQO'`is not supported anymore.
* @property  {number} [c=1.0] - Cost parameter. Increasing the parameter forces the model to fit the training data more accurately (setting it too large may lead to overfitting) .
* @property  {number} [j=1.0] - Unbalance parameter. Increasing it gives more weight to the positive examples (getting a better fit on the positive training examples gets a higher priority). Setting j=n is like adding n-1 copies of the positive training examples to the data set.
* @property  {number} [eps=1e-3] - Epsilon insensitive loss parameter. Larger values result in fewer support vectors (smaller model complexity)
* @property  {number} [batchSize=1000] - Number of examples used in the subgradient estimation. Higher number of samples slows down the algorithm, but makes the local steps more accurate.
* @property  {number} [maxIterations=10000] - Maximum number of iterations.
* @property  {number} [maxTime=1] - Maximum runtime in seconds.
* @property  {number} [minDiff=1e-6] - Stopping criterion tolerance.
* @property  {string} [type='C_SVC'] - The subalgorithm procedure in LIBSVM. Possible options are `'C_SVC'`, `'NU_SVC'` and `'ONE_CLASS'` for classification and `'EPSILON_SVR'`, `'NU_SVR'` and `'ONE_CLASS'` for regression.
* @property  {string} [kernel='LINEAR'] - Kernel type in LIBSVM. Possible options are `'LINEAR'`, `'POLY'`, 'RBF'`, 'SIGMOID'`  and `'PRECOMPUTED'`.
* @property  {number} [gamma=1.0] - Gamma parameter in LIBSVM. Set gamma in kernel function.
* @property  {number} [p=1e-1] - P parameter in LIBSVM. Set the epsilon in loss function of epsilon-SVR.
* @property  {number} [degree=1] - Degree parameter in LIBSVM. Set degree in kernel function.
* @property  {number} [nu=1e-2] - Nu parameter in LIBSVM. Set the parameter nu of nu-SVC, one-class SVM, and nu-SVR.
* @property  {number} [coef0=1.0] - Coef0 parameter in LIBSVM. Set coef0 in kernel function.
* @property  {number} [cacheSize=100] - Set cache memory size in MB (default 100) in LIBSVM.
* @property  {boolean} [verbose=false] - Toggle verbose output in the console.
*/
/**
* SVC
* @classdesc Support Vector Machine Classifier. Implements a soft margin linear support vector classifier using the PEGASOS algorithm,
* see: {@link http://ttic.uchicago.edu/~nati/Publications/PegasosMPB.pdf Pegasos: Primal Estimated sub-GrAdient SOlver for SVM}.
* @class
* @param {module:analytics~SVMParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link  module:analytics~SVMParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import modules
* var la = require('qminer').la;
* var analytics = require('qminer').analytics;
* // CLASSIFICATION WITH SVC
* // set up fake train and test data
* // four training examples with number of features = 2
* var featureMatrix = new la.Matrix({ rows: 2, cols: 4, random: true });
* // classification targets for four examples
* var targets = new la.Vector([-1, -1, 1, 1]);
* // set up the classification model
* var SVC = new analytics.SVC({ verbose: false });
* // train classifier
* SVC.fit(featureMatrix, targets);
* // set up a fake test vector
* var test = new la.Vector([1.1, -0.5]);
* // predict the target value
* var prediction = SVC.predict(test);
*/
 exports.SVC = function(arg) { return Object.create(require('qminer').analytics.SVC.prototype); };
/**
    * Gets the SVC parameters.
    * @returns {module:analytics~SVMParam} Parameters of the classifier model.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new SVC model with json
    * var SVC = new analytics.SVC({ c: 5, j: 10, batchSize: 2000, maxIterations: 12000, maxTime: 2, minDiff: 1e-10, verbose: true });
    * // get the parameters of the SVC model
    * // returns { algorithm: 'SGD' c: 5, j: 10, eps: 0.1, batchSize: 2000, maxIterations: 12000, maxTime: 2, minDiff: 1e-10, verbose: true }
    * var json = SVC.getParams();
    */
 exports.SVC.prototype.getParams = function() { return { algorithm: '', c: 0, j: 0, eps: 0.1, batchSize: 0, maxIterations: 0, maxTime: 0, minDiff: 0, verbose: true } };
/**
    * Sets the SVC parameters.
    * @param {module:analytics~SVMParam} param - Classifier training parameters.
    * @returns {module:analytics.SVC} Self. Updated the training parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a default SVC model
    * var SVC = new analytics.SVC();
    * // change the parameters of the SVC with the json { j: 5, maxIterations: 12000, minDIff: 1e-10 }
    * SVC.setParams({ j: 5, maxIterations: 12000, minDiff: 1e-10 }); // returns self
    */
 exports.SVC.prototype.setParams = function(param) { return Object.create(require('qminer').analytics.SVC.prototype); };
/**
    * Gets the vector of coefficients of the linear model. Type {@link module:la.Vector}.
    * @example
    * // import the analytics and la modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVC object
    * var SVC = new analytics.SVC();
    * // create the matrix containing the input features and the input vector for each matrix.
    * var matrix = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
    * var vec = new la.Vector([1, 1, -1, -1]);
    * // fit the model
    * SVC.fit(matrix, vec);
    * // get the weights
    * var weights = SVC.weights; // returns the coefficients of the normal vector of the hyperplane gained from the model: [1, 1]
    */
 exports.SVC.prototype.weights = Object.create(require('qminer').la.Vector.prototype);
/**
    * Saves model to output file stream.
    * @param {module:fs.FOut} fout - Output stream.
    * @returns {module:fs.FOut} The output stream `fout`.
    * @example
    * // import the analytics and la modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * var fs = require('qminer').fs;
    * // create a new SVC object
    * var SVC = new analytics.SVC();
    * // create the matrix containing the input features and the input vector for each matrix column.
    * var matrix = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
    * var vec = new la.Vector([1, 0, -1, -2]);
    * // fit the model
    * SVC.fit(matrix, vec);
    * // create output stream
    * var fout = fs.openWrite('svc_example.bin');
    * // save SVC object (model and parameters) to output stream and close it
    * SVC.save(fout);
    * fout.close();
    * // create input stream
    * var fin = fs.openRead('svc_example.bin');
    * // create a SVC object that loads the model and parameters from input stream
    * var SVC2 = new analytics.SVC(fin);
    */
 exports.SVC.prototype.save = function(fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
    * Sends vector through the model and returns the distance to the decision boundery.
    * @param {module:la.Vector | module:la.SparseVector | module:la.Matrix | module:la.SparseMatrix} X - Input feature vector or matrix with feature vectors as columns.
    * @returns {number | module:la.Vector} Distance:
    * <br>1. Real number, if `X` is {@link module:la.Vector} or {@link module:la.SparseVector}.
    * <br>2. {@link module:la.Vector}, if `X` is {@link module:la.Matrix} or {@link module:la.SparseMatrix}.
    * <br>Sign of the number corresponds to the class and the magnitude corresponds to the distance from the margin (certainty).
    * @example
    * // import the analytics and la modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVC object
    * var SVC = new analytics.SVC();
    * // create the matrix containing the input features and the input vector for each matrix
    * var matrix = new la.Matrix([[1, 0], [0, -1]]);
    * var vec = new la.Vector([1, -1]);
    * // fit the model
    * SVC.fit(matrix, vec);
    * // create the vector you want to get the distance from the model
    * var vec2 = new la.Vector([2, 3]);
    * // use the decisionFunction to get the distance of vec2 from the model
    * var distance = SVC.decisionFunction(vec2); // returns something close to 5
    */
 exports.SVC.prototype.decisionFunction = function(X) { return (X instanceof require('qminer').la.Vector | X instanceof require('qminer').la.SparseVector) ? 0 : Object.create(require('qminer').la.Vector.prototype); }
/**
    * Sends vector through the model and returns the prediction as a real number.
    * @param {module:la.Vector | module:la.SparseVector | module:la.Matrix | module:la.SparseMatrix} X - Input feature vector or matrix with feature vectors as columns.
    * @returns {number | module:la.Vector} Prediction:
    * <br>1. Real number, if `X` is {@link module:la.Vector} or {@link module:la.SparseVector}.
    * <br>2. {@link module:la.Vector}, if `X` is {@link module:la.Matrix} or {@link module:la.SparseMatrix}.
    * <br>1 for positive class and -1 for negative.
    * @example
    * // import the analytics and la modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVC object
    * var SVC = new analytics.SVC();
    * // create the matrix containing the input features and the input vector for each matrix
    * var matrix = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
    * var vec = new la.Vector([1, 1, -1, -1]);
    * // fit the model
    * SVC.fit(matrix, vec);
    * // create a vector you want to predict
    * var vec2 = new la.Vector([3, 5]);
    * // predict the vector
    * var prediction = SVC.predict(vec2); // returns 1
    */
 exports.SVC.prototype.predict = function(X) { return (X instanceof require('qminer').la.Vector | X instanceof require('qminer').la.SparseVector) ? 0 : Object.create(require('qminer').la.Vector.prototype); }
/**
    * Fits a SVM classification model, given column examples in a matrix and vector of targets.
    * @param {module:la.Matrix | module:la.SparseMatrix} X - Input feature matrix where columns correspond to feature vectors.
    * @param {module:la.Vector} y - Input vector of targets, one for each column of X.
    * @returns {module:analytics.SVC} Self. The model has been created.
    * @example
    * // import the analytics and la modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVC object
    * var SVC = new analytics.SVC();
    * // create the matrix containing the input features and the input vector for each matrix.
    * var matrix = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
    * var vec = new la.Vector([1, 1, -1, -1]);
    * // fit the model
    * SVC.fit(matrix, vec); // creates a model, where the hyperplane has the normal semi-equal to [1, 1]
    */
 exports.SVC.prototype.fit = function(X, y) { return Object.create(require('qminer').analytics.SVC.prototype); }
/**
* SVR
* @classdesc Support Vector Machine Regression. Implements a soft margin linear support vector regression using the PEGASOS algorithm with epsilon insensitive loss, see: {@link http://ttic.uchicago.edu/~nati/Publications/PegasosMPB.pdf Pegasos: Primal Estimated sub-GrAdient SOlver for SVM}.
* @class
* @param {module:analytics~SVMParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link  module:analytics~SVMParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import module
* var analytics = require('qminer').analytics;
* var la = require('qminer').la;
* // REGRESSION WITH SVR
* // Set up fake train and test data.
* // Four training examples with, number of features = 2
* var featureMatrix = new la.Matrix({ rows: 2, cols: 4, random: true });
* // Regression targets for four examples
* var targets = new la.Vector([1.1, -2, 3, 4.2]);
* // Set up the regression model
* var SVR = new analytics.SVR({ verbose: false });
* // Train regression
* SVR.fit(featureMatrix, targets);
* // Set up a fake test vector
* var test = new la.Vector([1.1, -0.8]);
* // Predict the target value
* var prediction = SVR.predict(test);
*/
 exports.SVR = function(arg) { return Object.create(require('qminer').analytics.SVR.prototype); };
/**
    * Gets the SVR parameters.
    * @returns {module:analytics~SVMParam} Parameters of the regression model.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new SVR object
    * var SVR = new analytics.SVR({ c: 10, eps: 1e-10, maxTime: 12000, verbose: true });
    * // get the parameters of SVR
    * var params = SVR.getParams();
    */
 exports.SVR.prototype.getParams = function() { return { algorithm: '', c: 0, j: 0, eps: 0, batchSize: 0, maxIterations: 0, maxTime: 0, minDiff: 0, verbose: true } };
/**
    * Sets the SVR parameters.
    * @param {module:analytics~SVMParam} param - Regression training parameters.
    * @returns {module:analytics.SVR} Self. Updated the training parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new SVR object
    * var SVR = new analytics.SVR();
    * // set the parameters of the SVR object
    * SVR.setParams({ c: 10, maxTime: 12000 });
    */
 exports.SVR.prototype.setParams = function(param) { return Object.create(require('qminer').analytics.SVR.prototype); };
/**
    * The vector of coefficients of the linear model. Type {@link module:la.Vector}.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVR object
    * var SVR = new analytics.SVR({ c: 10 });
    * // create a matrix and vector for the model
    * var matrix = new la.Matrix([[1, -1], [1, 1]]);
    * var vector = new la.Vector([1, 1]);
    * // create the model by fitting the values
    * SVR.fit(matrix, vector);
    * // get the coeficients of the linear model
    * var coef = SVR.weights;
    */
 exports.SVR.prototype.weights = Object.create(require('qminer').la.Vector.prototype);
/**
    * Saves model to output file stream.
    * @param {module:fs.FOut} fout - Output stream.
    * @returns {module:fs.FOut} The output stream `fout`.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * var fs = require('qminer').fs;
    * // create a new SVR object
    * var SVR = new analytics.SVR({ c: 10 });
    * // create a matrix and vector for the model
    * var matrix = new la.Matrix([[1, -1], [1, 1]]);
    * var vector = new la.Vector([1, 1]);
    * // create the model by fitting the values
    * SVR.fit(matrix, vector);
    * // save the model in a binary file
    * var fout = fs.openWrite('svr_example.bin');
    * SVR.save(fout);
    * fout.close();
    * // construct a SVR model by loading from the binary file
    * var fin = fs.openRead('svr_example.bin');
    * var SVR2 = new analytics.SVR(fin);
    */
 exports.SVR.prototype.save = function(fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
     * Sends vector through the model and returns the scalar product as a real number.
     * @param {module:la.Vector | module:la.SparseVector | module:la.Matrix | module:la.SparseMatrix} X - Input feature vector or matrix with feature vectors as columns.
     * @returns {number | module:la.Vector} Distance:
     * <br>1. Real number if `X` is {@link module:la.Vector} or {@link module:la.SparseVector}.
     * <br>2. {@link module:la.Vector}, if `X` is {@link module:la.Matrix} or {@link module:la.SparseMatrix}.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new SVR object
     * var SVR = new analytics.SVR({ c: 10 });
     * // create a matrix and vector for the model
     * var matrix = new la.Matrix([[1, -1], [1, 1]]);
     * var vector = new la.Vector([1, 1]);
     * // create the model by fitting the values
     * SVR.fit(matrix, vector);
     * // get the distance between the model and the given vector
     * var vec2 = new la.Vector([-5, 1]);
     * var distance = SVR.decisionFunction(vec2);
     */
 exports.SVR.prototype.decisionFunction = function(X) { return (X instanceof require('qminer').la.Vector | X instanceof require('qminer').la.SparseVector) ? 0 : Object.create(require('qminer').la.Vector.prototype); }
/**
    * Sends vector through the model and returns the prediction as a real number.
    * @param {module:la.Vector | module:la.SparseVector | module:la.Matrix | module:la.SparseMatrix} X - Input feature vector or matrix with feature vectors as columns.
    * @returns {number | module:la.Vector} Prediction:
    * <br>1. Real number, if `X` is {@link module:la.Vector} or {@link module:la.SparseVector}.
    * <br>2. {@link module:la.Vector}, if `X` is {@link module:la.Matrix} or {@link module:la.SparseMatrix}.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVR object
    * var SVR = new analytics.SVR({ c: 10 });
    * // create a matrix and vector for the model
    * var matrix = new la.Matrix([[1, -1], [1, 1]]);
    * var vector = new la.Vector([1, 1]);
    * // create the model by fitting the values
    * SVR.fit(matrix, vector);
    * // predict the value of the given vector
    * var vec2 = new la.Vector([-5, 1]);
    * var prediction = SVR.predict(vec2);
    */
 exports.SVR.prototype.predict = function(X) { return (X instanceof require('qminer').la.Vector | X instanceof require('qminer').la.SparseVector) ? 0 : Object.create(require('qminer').la.Vector.prototype); }
/**
    * Fits a SVM regression model, given column examples in a matrix and vector of targets.
    * @param {module:la.Matrix | module:la.SparseMatrix} X - Input feature matrix where columns correspond to feature vectors.
    * @param {module:la.Vector} y - Input vector of targets, one for each column of X.
    * @returns {module:analytics.SVR} Self.  The model has been created.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new SVR object
    * var SVR = new analytics.SVR({ c: 10 });
    * // create a matrix and vector for the model
    * var matrix = new la.Matrix([[1, -1], [1, 1]]);
    * var vector = new la.Vector([1, 1]);
    * // create the model by fitting the values
    * SVR.fit(matrix, vector);
    */
 exports.SVR.prototype.fit = function(X, y) { return Object.create(require('qminer').analytics.SVR.prototype); }
/**
* @typedef {Object} ridgeRegParam
* An object used for the construction of {@link module:analytics.RidgeReg}.
* @property {number} [gamma=0.0] - The gamma value.
*/
/**
 * Ridge Regression
 * @class
 * @classdesc Ridge regression minimizes the value `||A' x - b||^2 + ||gamma x||^2`.
 * Uses {@link http://en.wikipedia.org/wiki/Tikhonov_regularization Tikhonov regularization}.
 * @param {module:analytics~ridgeRegParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
 * <br>1. Using the {@link  module:analytics~ridgeRegParam} object,
 * <br>2. using the file input stream {@link module:fs.FIn}.
 * @example
 * // import modules
 * analytics = require('qminer').analytics;
 * la = require('qminer').la;
 * // create a new model with gamma equal to 1.0
 * var regmod = new analytics.RidgeReg({ gamma: 1.0 });
 * // generate a random feature matrix
 * var A = la.randn(10, 100);
 * // generate a random model
 * var w = la.randn(10);
 * // generate noise
 * var n = la.randn(100).multiply(0.01);
 * // generate responses (model'*data + noise)
 * var b = A.transpose().multiply(w).plus(n);
 * // fit model
 * regmod.fit(A, b);
 * // compare the true with the trained model
 * // true model
 * w.print();
 * // trained model;
 * regmod.weights.print();
 * // cosine between the true and the estimated model should be close to 1 if the fit succeeded
 * var cos = regmod.weights.cosine(w);
 */
 exports.RidgeReg = function(arg) { return Object.create(require('qminer').analytics.RidgeReg.prototype) };
/**
    * Gets the parameters.
    * @returns {model:analytics~RidgeRegParam} The object containing the parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new Ridge Regression object
    * var regmod = new analytics.RidgeReg({ gamma: 5 });
    * // get the parameters
    * // returns a json object { gamma: 5 }
    * var param = regmod.getParams();
    */
 exports.RidgeReg.prototype.getParams = function () { return { gamma: 0.0 } }
/**
    * Set the parameters.
    * @param {number | model:analytics~RidgeRegParam} gamma - The new parameter for the model, given as a number or as an object.
    * @returns {module:analytics.RidgeReg} Self. The parameter is set to `gamma`.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new Ridge Regression object
    * var regmod = new analytics.RidgeReg({ gamma: 5 });
    * // set the parameters of the object
    * var param = regmod.setParams({ gamma: 10 });
    */
 exports.RidgeReg.prototype.setParams = function (gamma) { return Object.create(require('qminer').analytics.RidgeReg.prototype); }
/**
     * Fits a column matrix of feature vectors `X` onto the response variable `y`.
     * @param {module:la.Matrix} X - Column matrix which stores the feature vectors.
     * @param {module:la.Vector} y - Response variable.
     * @returns {module:analytics.RidgeReg} Self. The model is fitted by `X` and `y`.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new Ridge Regression object
     * var regmod = new analytics.RidgeReg();
     * // create the test matrix and vector
     * var X = new la.Matrix([[1, 2], [1, -1]]);
     * var y = new la.Vector([3, 3]);
     * // fit the model with X and y
     * // the weights of the model are 2, 1
     * regmod.fit(X, y);
     */
 exports.RidgeReg.prototype.fit = function(X, y) { return Object.create(require('qminer').analytics.RidgeReg.prototype); }
/**
     * Returns the expected response for the provided feature vector.
     * @param {module:la.Vector} x - Feature vector.
     * @returns {number} Predicted response.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new Ridge Regression object
     * var regmod = new analytics.RidgeReg();
     * // create the test matrix and vector
     * var X = new la.Matrix([[1, 2], [1, -1]]);
     * var y = new la.Vector([3, 3]);
     * // fit the model with X and y
     * regmod.fit(X, y);
     * // create a new vector for the prediction
     * var vec = new la.Vector([3, 4]);
     * // create the prediction
     * // returns the value 10
     * var prediction = regmod.decisionFunction(vec);
     */
 exports.RidgeReg.prototype.decisionFunction = function(X) { return 0.0; }
/**
     * Returns the expected response for the provided feature vector.
     * @param {module:la.Vector} x - Feature vector.
     * @returns {number} Predicted response.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new Ridge Regression object
     * var regmod = new analytics.RidgeReg();
     * // create the test matrix and vector
     * var X = new la.Matrix([[1, 2], [1, -1]]);
     * var y = new la.Vector([3, 3]);
     * // fit the model with X and y
     * regmod.fit(X, y);
     * // create a new vector for the prediction
     * var vec = new la.Vector([3, 4]);
     * // create the prediction
     * // returns the value 10
     * var prediction = regmod.predict(vec);
     */
 exports.RidgeReg.prototype.predict = function(X) { return 0.0; }
/**
     * Vector of coefficients for linear regression. Type {@link module:la.Vector}.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new Ridge Regression object
     * var regmod = new analytics.RidgeReg();
     * // create the test matrix and vector
     * var X = new la.Matrix([[1, 2], [1, -1]]);
     * var y = new la.Vector([3, 3]);
     * // fit the model with X and y
     * regmod.fit(X, y);
     * // get the weights
     * var weights = regmod.weights;
     */
 exports.RidgeReg.prototype.weights = Object.create(require('qminer').la.Vector.prototype);
/**
     * Saves the model into the output stream.
     * @param {module:fs.FOut} fout - Output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create a new Ridge Regression object
     * var regmod = new analytics.RidgeReg();
     * // create the test matrix and vector
     * var X = new la.Matrix([[1, 2], [1, -1]]);
     * var y = new la.Vector([3, 3]);
     * // fit the model with X and y
     * regmod.fit(X, y);
     * // create an output stream object and save the model
     * var fout = fs.openWrite('regmod_example.bin');
     * regmod.save(fout);
     * fout.close();
     * // create a new Ridge Regression model by loading the model
     * var fin = fs.openRead('regmod_example.bin');
     * var regmod2 = new analytics.RidgeReg(fin);
     */
 exports.RidgeReg.prototype.save = function(fout) { Object.create(require('qminer').fs.FOut.prototype); };
/**
 * Sigmoid function (`y = 1/[1 + exp[-A*x + B]]`) fitted on decision function to mimic.
 * @class
 * @param {module:fs.FIn} [arg] - Construction arguments.
 * @example
 * // import modules
 * la = require('qminer').la;
 * analytics = require('qminer').analytics;
 * // create a new model
 * var sigmoid = new analytics.Sigmoid();
 * // generate a random predictions
 * var x = new la.Vector([0.5, 2.3, -0.1, 0.5, -7.3, 1.2]);
 * // generate a random labels
 * var y = new la.Vector([1, 1, -1, 1, -1, -1]);
 * // fit model
 * sigmoid.fit(x, y);
 * // get predictions
 * var pred1 = sigmoid.predict(1.2);
 * var pred2 = sigmoid.predict(-1.2);
 */
 exports.Sigmoid = function(arg) { return Object.create(require('qminer').analytics.Sigmoid.prototype); };
/**
    * Get the parameters. <i>It doesn't do anything, it's only for consistency for constructing pipeline.</i>
    * @returns {Object} An empty object.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create the Sigmoid model
    * var s = new analytics.Sigmoid();
    * // get the parameters
    * // returns an empty object
    * var param = s.getParams();
    */
 exports.Sigmoid.prototype.getParams = function () { return {}; }
/**
    * Sets the parameters. <i>It doesn't do anything, it's only for consistency for constructing pipeline.</i>
    * @param {Object} arg - Json object.
    * @returns {module:analytics.Sigmoid} Self. Nothing changes.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create the Sigmoid model
    * var s = new analytics.Sigmoid();
    * // set the parameters
    * // doesn't change the model
    * s.setParams({});
    */
 exports.Sigmoid.prototype.setParams = function (arg) { return Object.create(require('qminer').analytics.Sigmoid.prototype); }
/**
    * Gets the model.
    * @returns {Object} The object `sigModel` containing the properties:
    * <br> `sigModel.A` - First value of the Sigmoid model,
    * <br> `sigModel.B` - Second value of the Sigmoid model.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create the Sigmoid model
    * var s = new analytics.Sigmoid();
    * // get the model parameters
    * // returns a Json object { A: 0, B: 0 }
    * var model = s.getModel();
    */
 exports.Sigmoid.prototype.getModel = function () {return { A: 0, B: 0 }; }
/**
     * Fits a column matrix of feature vectors `X` onto the response variable `y`.
     * @param {module:la.Vector} x - Predicted values (e.g. using {@link module:analytics.SVR}).
     * @param {module:la.Vector} y - Actual binary labels: 1 or -1.
     * @returns {module:analytics.Sigmoid} Self. The model has been created.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the Sigmoid model
     * var s = new analytics.Sigmoid();
     * // create the predicted values and the binary labels
     * var X = new la.Vector([-3, -2, -1, 1, 2, 3]);
     * var y = new la.Vector([-1, -1, -1, 1, 1, 1]);
     * // fit the model
     * // changes the internal A and B values of the model
     * s.fit(X, y);
     */
 exports.Sigmoid.prototype.fit = function(X, y) { return Object.create(require('qminer').analytics.Sigmoid.prototype); }
/**
     * Returns the expected response for the provided feature vector.
     * @param {number | module:la.Vector} x - Prediction score.
     * @returns {number | module:la.Vector}
     * <br> 1. If `x` is a number, returns a normalized prediction score,
     * <br> 2. if `x` is a {@link module:la.Vector}, returns a vector of normalized prediction scores.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the Sigmoid model
     * var s = new analytics.Sigmoid();
     * // create the predicted values and the binary labels
     * var X = new la.Vector([-3, -2, -1, 1, 2, 3]);
     * var y = new la.Vector([-1, -1, -1, 1, 1, 1]);
     * // fit the model
     * s.fit(X, y);
     * // predict the probability of the value 0 on this model
     * // returns 0.5
     * var prediction = s.decisionFunction(0.5);
     */
 exports.Sigmoid.prototype.decisionFunction = function(x) { return (x instanceof Object.create(require('qminer').la.Vector)) ? Object.create(require('qminer').la.Vector.prototype) : 0.0; }
/**
     * Returns the expected response for the provided feature vector.
     * @param {number | module:la.Vector} x - Prediction score.
     * @returns {number | module:la.Vector}
     * <br> 1. If `x` is a number, returns a normalized prediction score,
     * <br> 2. if `x` is a {@link module:la.Vector}, returns a vector of normalized prediction scores.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the Sigmoid model
     * var s = new analytics.Sigmoid();
     * // create the predicted values and the binary labels
     * var X = new la.Vector([-3, -2, -1, 1, 2, 3]);
     * var y = new la.Vector([-1, -1, -1, 1, 1, 1]);
     * // fit the model
     * s.fit(X, y);
     * // predict the probability of the value 0 on this model
     * // returns 0.5
     * var prediction = s.predict(0.5);
     */
 exports.Sigmoid.prototype.predict = function(x) { return (x instanceof Object.create(require('qminer').la.Vector)) ? Object.create(require('qminer').la.Vector.prototype) : 0.0; }
/**
     * Saves the model into the output stream.
     * @param {module:fs.FOut} fout - Output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create the Sigmoid model
     * var s = new analytics.Sigmoid();
     * // create the predicted values and the binary labels
     * var X = new la.Vector([-3, -2, -1, 1, 2, 3]);
     * var y = new la.Vector([-1, -1, -1, 1, 1, 1]);
     * // fit the model
     * s.fit(X, y);
     * // create an output stream object and save the model
     * var fout = fs.openWrite('sigmoid_example.bin');
     * s.save(fout);
     * fout.close();
     * // create a new Sigmoid model by loading the model
     * var fin = fs.openRead('sigmoid_example.bin');
     * var s2 = new analytics.Sigmoid(fin);
     */
 exports.Sigmoid.prototype.save = function(fout) { return Object.create(require('qminer').fs.FOut.prototype); };
/**
* @typedef {Object} detectorParam
* An object used for the construction of {@link module:analytics.NearestNeighborAD}.
* @param {number} [rate=0.05] - The expected fracton of emmited anomalies (0.05 -> 5% of cases will be classified as anomalies).
* @param {number} [windowSize=100] - Number of most recent instances kept in the model.
*/
/**
 * Nearest Neighbour Anomaly Detection
 * @classdesc Anomaly detector that checks if the test point is too far from the nearest known point.
 * @class
 * @param {module:analytics~detectorParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link  module:analytics~detectorParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
 * @example
 * // import modules
 * var analytics = require('qminer').analytics;
 * var la = require('qminer').la;
 * // create a new NearestNeighborAD object
 * var neighbor = new analytics.NearestNeighborAD({ rate: 0.1 });
 * // create a sparse matrix
 * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
 * // fit the model with the matrix
 * neighbor.fit(matrix);
 * // create a new sparse vector
 * var vector = new la.SparseVector([[0, 4], [1, 0]]);
 * // predict if the vector is an anomaly or not
 * var prediction = neighbor.predict(vector);
 */
 exports.NearestNeighborAD = function(arg) { return Object.create(require('qminer').analytics.NearestNeighborAD.prototype); };
/**
    * Sets parameters.
    * @param {module:analytics~detectorParam} params - The object containing the parameters.
    * @returns {module:analytics.NearestNeighborAD} Self. The parameters are updated with `params`.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD();
    * // set it's parameters to rate: 0.1
    * neighbor.setParams({ rate: 0.1 });
    */
 exports.NearestNeighborAD.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.NearestNeighborAD.prototype); }
/**
    * Gets parameters.
    * @returns {module:analytics~detectorParam} The object containing the parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD();
    * // get the parameters of the object
    * // returns a json object { rate: 0.05 }
    * var params = neighbor.getParams();
    */
 exports.NearestNeighborAD.prototype.getParams = function () { return { rate: 0.0, windowSize: 0.0 }; }
/**
     * Saves model to provided output stream.
     * @param {module:fs.FOut} fout - The output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create a new NearestNeighborAD object
     * var neighbor = new analytics.NearestNeighborAD();
     * // create a new sparse matrix
     * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
     * // fit the model with the matrix
     * neighbor.fit(matrix);
     * // create an output stream object and save the model
     * var fout = fs.openWrite('neighbor_example.bin');
     * neighbor.save(fout);
     * fout.close();
     * // create a new Nearest Neighbor Anomaly model by loading the model
     * var fin = fs.openRead('neighbor_example.bin');
     * var neighbor2 = new analytics.NearestNeighborAD(fin);
     */
 exports.NearestNeighborAD.prototype.save = function(fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
    * Returns the model.
    * @returns {Object} The object `neighbourModel` containing the properties:
    * <br> 1. `neighbourModel.rate` - The expected fraction of emmited anomalies.
    * <br> 2. `neighbourModel.thresh` - Maximal squared distance to the nearest neighbor that is not anomalous.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD({ rate: 0.1 });
    * // get the model of the object
    * // returns a json object { rate: 0.1, window: 0 }
    * var model = neighbor.getModel();
    */
 exports.NearestNeighborAD.prototype.getModel = function () { return { rate: 0.1, threshold: 0.0 }; }
/**
    * Adds a new point to the known points and recalculates the threshold.
    * @param {module:la.SparseVector} X - Test example.
    * @param {number} recId - Integer record ID, used in {@link module:analytics.NearestNeighborAD.prototype.explain}.
    * @returns {module:analytics.NearestNeighborAD} Self. The model is updated.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD();
    * // create a new sparse matrix
    * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
    * // fit the model with the matrix
    * neighbor.fit(matrix);
    * // create a new sparse vector
    * var vector = new la.SparseVector([[0, 2], [1, 5]]);
    * // update the model with the vector
    * neighbor.partialFit(vector);
    */
 exports.NearestNeighborAD.prototype.partialFit = function(X) { return Object.create(require('qminer').NearestNeighborAD.prototype); }
/**
    * Analyzes the nearest neighbor distances and calculates the detector threshold based on the rate parameter.
    * @param {module:la.SparseMatrix} A - Matrix whose columns correspond to known examples. Gets saved as it is part of the model.
    * @param {module:la.IntVector} [idVec] - An integer vector of IDs.
    * @returns {module:analytics.NearestNeighborAD} Self. The model is set by the matrix `A`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD();
    * // create a new sparse matrix
    * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
    * // fit the model with the matrix
    * neighbor.fit(matrix);
    */
 exports.NearestNeighborAD.prototype.fit = function(A, idVec) { return Object.create(require('qminer').NearestNeighborAD.prototype); }
/**
     * Compares the point to the known points and returns distance to the nearest one.
     * @param {module:la.Vector} x - Test vector.
     * @returns {number} Distance to the nearest point.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new NearestNeighborAD object
     * var neighbor = new analytics.NearestNeighborAD();
     * // create a new sparse matrix
     * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
     * // fit the model with the matrix
     * neighbor.fit(matrix);
     * // create a new sparse vector
     * var vector = new la.SparseVector([[0, 4], [1, 0]]);
     * // get the distance of the vector from the model
     * var prediction = neighbor.decisionFunction(vector); // returns 1
     */
 exports.NearestNeighborAD.prototype.decisionFunction = function(x) { return 0.0; }
/**
    * Compares the point to the known points and returns 1 if it's too far away (based on the precalculated threshold).
    * @param {module:la.SparseVector} x - Test vector.
    * @returns {number} Returns 1.0 if the vector `x` is an anomaly and 0.0 otherwise.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD();
    * // create a new sparse matrix
    * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
    * // fit the model with the matrix
    * neighbor.fit(matrix);
    * // create a new sparse vector
    * var vector = new la.SparseVector([[0, 4], [1, 0]]);
    * // check if the vector is an anomaly
    * var prediction = neighbor.predict(vector); // returns 1
    */
 exports.NearestNeighborAD.prototype.predict = function(x) { return 0.0; }
/**
    * @typedef {Object} NearestNeighborADExplain
    * An object used for interpreting the predictions of {@link module:analytics.NearestNeighborAD#explain}.
    * @property {number} nearestID - The ID of the nearest neighbor.
    * @property {number} distance - The distance to the nearest neighbor.
    * @property {Array.<module:analytics~NearestNeighborADFeatureContribution>} features - An array with feature contributions.
    * @property {number} oldestID - The ID of the oldest record in the internal buffer (the record that was added first).
    * @property {number} newestID - The ID of the newest record in the internal buffer (the record that was added last).
    */
/**
    * @typedef {Object} NearestNeighborADFeatureContribution
    * An object explaining the prediction of {@link module:analytics.NearestNeighborAD#explain} in terms of a single feature.
    * Contained in the object {@link module:analytics~NearestNeighborADExplain}.
    * @property {number} id - The ID of the feature.
    * @property {number} val - The value of the feature for the vector we are explaining.
    * @property {number} nearVal - The the value of the feature for the nearest neighbor.
    * @property {number} contribution - Fraction of the total distance `(v(i) - n(i))^2 / ||v - n||^2`.
    */
/**
    * Returns an object that encodes the ID of the nearest neighbor and the features that contributed to the distance.
    * @param {module:la.SparseVector} x - Test vector.
    * @returns {module:analytics~NearestNeighborADExplain} The explanation object.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD({ rate:0.05, windowSize:3 });
    * // create a new sparse matrix
    * var matrix = new la.SparseMatrix([[[0, 1], [1, 2]], [[0, -2], [1, 3]], [[0, 0], [1, 1]]]);
    * // fit the model with the matrix and provide a vector record IDs
    * neighbor.fit(matrix, new la.IntVector([3541, 1112, 4244]));
    * // create a new sparse vector
    * var vector = new la.SparseVector([[0, 4], [1, 0]]);
    * // check if the vector is an anomaly
    * var explanation = neighbor.explain(vector); // returns an explanation
    */
 exports.NearestNeighborAD.prototype.explain = function(x) { return {}; }
/**
    * Returns true when the model has enough data to initialize. Type `boolean`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new NearestNeighborAD object
    * var neighbor = new analytics.NearestNeighborAD({ rate:0.05, windowSize:3 });
    * // check if the model has enough data
    * neighbor.init;
    */
 exports.NearestNeighborAD.prototype.init = false;
/**
* @typedef {Object} recLinRegParam
* An object used for the construction of {@link module:analytics.RecLinReg}.
* @param {number} dim - The dimension of the model.
* @param {number} [regFact=1.0] - The regularization factor.
* @param {number} [forgetFact=1.0] - The forgetting factor.
*/
/**
* Recursive Linear Regression
* @classdesc Holds the Recursive Linear Regression model.
* @class
* @param {module:analytics~recLinRegParam | module:fs.FIn} arg - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link  module:analytics~detectorParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import analytics module
* var analytics = require('qminer').analytics;
* // create the recursive linear regression model holder
* var linreg = new analytics.RecLinReg({ dim: 10, regFact: 1.0, forgetFact: 1.0 });
*/
 exports.RecLinReg = function(arg) { return Object.create(require('qminer').analytics.RecLinReg.prototype); }
/**
    * Updates the internal model.
    * @param {module:la.Vector} vec - The input vector.
    * @param {number} num - The target number for the vector.
    * @returns {module:analytics.RecLinReg} Self. The internal model is updated.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create the Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 3.0 });
    * // create a new dense vector
    * var vec = new la.Vector([1, 2, 3]);
    * // fit the model with the vector
    * linreg.partialFit(vec, 6);
    */
 exports.RecLinReg.prototype.partialFit = function (vec, num) { return Object.create(require('qminer').analytics.RecLinReg.prototype); }
/**
    * Creates/updates the internal model.
    * @param {module:la.Matrix} mat - The input matrix.
    * @param {module:la.Vector} vec - The target numbers, where the i-th number in vector is the target number for the i-th column of the `mat`.
    * @returns {module:analytics.RecLinReg} Self. The internal model is updated.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create the Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 2.0 });
    * // create a new dense matrix and target vector
    * var mat = new la.Matrix([[1, 2, 3], [3, 4, 5]]);
    * var vec = new la.Vector([3, 5, -1]);
    * // fit the model with the matrix
    * linreg.fit(mat, vec);
    */
 exports.RecLinReg.prototype.fit = function (mat, vec) { return Object.create(require('qminer').analytics.RecLinReg.prototype); }
/**
    * Puts the vector through the model and returns the prediction as a real number.
    * @param {module:la.Vector} vec - The prediction vector.
    * @returns {number} The prediction.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create the Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 2.0, recFact: 1e-10 });
    * // create a new dense matrix and target vector
    * var mat = new la.Matrix([[1, 2], [1, -1]]);
    * var vec = new la.Vector([3, 3]);
    * // fit the model with the matrix
    * linreg.fit(mat, vec);
    * // create the vector to be predicted
    * var pred = new la.Vector([1, 1]);
    * // predict the value of the vector
    * var prediction = linreg.predict(pred); // returns something close to 3.0
    */
 exports.RecLinReg.prototype.predict = function (vec) { return 0.0 }
/**
    * Sets the parameters of the model.
    * @param {module:analytics~recLinRegParam} params - The new parameters of the model.
    * @returns {module:analytics.RecLinReg} Self. The parameters are updated. Any previous model is set to default.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 10 });
    * // set the parameters of the model
    * linreg.setParams({ dim: 3, recFact: 1e2, forgetFact: 0.5 });
    */
 exports.RecLinReg.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.RecLinReg.prototype); }
/**
    * Returns the parameters.
    * @returns {module:analytics~recLinRegParam} The parameters of the model.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 10 });
    * // get the parameters of the model
    * var params = linreg.getParams(); // returns { dim: 10, recFact: 1.0, forgetFact: 1.0 }
    */
 exports.RecLinReg.prototype.getParams = function () { return { dim: 0, regFact: 1.0, forgetFact: 1.0 }; }
/**
    * Gives the weights of the model. Type {@link module:la.Vector}.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 2 });
    * // create a new dense matrix and target vector
    * var mat = new la.Matrix([[1, 2], [1, -1]]);
    * var vec = new la.Vector([3, 3]);
    * // fit the model with the matrix
    * linreg.fit(mat, vec);
    * // get the weights of the model
    * var weights = linreg.weights;
    */
 exports.RecLinReg.prototype.weights = Object.create(require('qminer').la.Vector.prototype);
/**
    * Gets the dimensionality of the model. Type `number`.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 10 });
    * // get the dimensionality of the model
    * var dim = linreg.dim;
    */
 exports.RecLinReg.prototype.dim = 0;
/**
    * Save model to provided output stream.
    * @param {module:fs.FOut} fout - The output stream.
    * @returns {module:fs.FOut} The output stream `fout`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * var fs = require('qminer').fs;
    * // create the Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 2.0, recFact: 1e-10 });
    * // create a new dense matrix and target vector
    * var mat = new la.Matrix([[1, 2], [1, -1]]);
    * var vec = new la.Vector([3, 3]);
    * // fit the model with the matrix
    * linreg.fit(mat, vec);
    * // create an output stream object and save the model
    * var fout = fs.openWrite('linreg_example.bin');
    * linreg.save(fout);
    * fout.close();
    * // create a new Nearest Neighbor Anomaly model by loading the model
    * var fin = fs.openRead('linreg_example.bin');
    * var linreg2 = new analytics.RecLinReg(fin);
    */
 exports.RecLinReg.prototype.save = function(fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} logisticRegParam
* An object used for the construction of {@link module:analytics.LogReg}.
* @property {number} [lambda=1] - The regularization parameter.
* @property {boolean} [intercept=false] - Indicates whether to automatically include the intercept.
*/
/**
 * Logistic regression model.
 * @class
 * @classdesc  Uses Newtons method to compute the weights. <b>Before use: QMiner must be built with the OpenBLAS library.</b>
 * @param { module:analytics~logisticRegParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link  module:analytics~logisticRegParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
 * @example
 * // import analytics module
 * var analytics = require('qminer').analytics;
 * // create the Logistic Regression model
 * var logreg = new analytics.LogReg({ lambda: 2 });
 * // create the input matrix and vector for fitting the model
 * var mat = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
 * var vec = new la.Vector([1, 0, -1, -2]);
 * // if OpenBLAS is used, fit the model
 * if (require('qminer').flags.blas) {
 *     logreg.fit(mat, vec);
 *     // create the vector for the prediction
 *     var test = new la.Vector([1, 1]);
 *     // get the prediction
 *     var prediction = logreg.predict(test);
 * }
 */
 exports.LogReg = function (arg) { return Object.create(require('qminer').analytics.LogReg.prototype); }
/**
    * Gets the parameters.
    * @returns {module:analytics~logisticRegParam} The parameters of the model.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create the Logistic Regression model
    * var logreg = new analytics.LogReg({ lambda: 10 });
    * // get the parameters of the model
    * var param = logreg.getParams(); // returns { lambda: 10, intercept: false }
    */
 exports.LogReg.prototype.getParams = function () { return { lambda: 1.0, intercept: false } };
/**
    * Set the parameters.
    * @param {module:analytics~logisticRegParam} param - The new parameters.
    * @returns {module:analytics.LogReg} Self. The parameters are updated.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a logistic regression model
    * var logreg = new analytics.LogReg({ lambda: 10 });
    * // set the parameters of the model
    * logreg.setParams({ lambda: 1 });
    */
 exports.LogReg.prototype.setParams = function (param) { return Object.create(require('qminer').analytics.LogReg.prototype); }
/**
     * Fits a column matrix of feature vectors `X` onto the response variable `y`.
     * @param {module:la.Matrix} X - the column matrix which stores the feature vectors.
     * @param {module:la.Vector} y - the response variable.
     * @param {number} [eps] - the epsilon used for convergence.
     * @returns {module:analytics.LogReg} Self. The model has been updated.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the logistic regression model
     * var logreg = new analytics.LogReg();
     * // create the input matrix and vector for fitting the model
     * var mat = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
     * var vec = new la.Vector([1, 0, -1, -2]);
     * // if OpenBLAS is used, fit the model
     * if (require('qminer').flags.blas) {
     *     logreg.fit(mat, vec);
     * }
     */
 exports.LogReg.prototype.fit = function (X, y, eps) { return Object.create(require('qminer').analytics.LogReg.prototype); }
/**
     * Returns the expected response for the provided feature vector.
     * @param {module:la.Vector} x - the feature vector.
     * @returns {number} the expected response.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the logistic regression model
     * var logreg = new analytics.LogReg();
     * // create the input matrix and vector for fitting the model
     * var mat = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
     * var vec = new la.Vector([1, 0, -1, -2]);
     * // if openblas is used, fit the model and predict the value
     * if (require('qminer').flags.blas) {
     *     // fit the model
     *     logreg.fit(mat, vec);
     *     // create the vector for the prediction
     *     var test = new la.Vector([1, 1]);
     *     // get the prediction
     *     var prediction = logreg.predict(test);
     * };
     */
 exports.LogReg.prototype.predict = function (x) { return 0.0; }
/**
     * Gives the weights of the model. Type {@link module:la.Vector}.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the logistic regression model
     * var logreg = new analytics.LogReg();
     * // get the weights of the model
     * var weights = logreg.weights;
     */
 exports.LogReg.prototype.weights = Object.create(require('qminer').la.vector.prototype);
/**
     * Saves the model into the output stream.
     * @param {module:fs.FOut} fout - the output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create the logistic regression model
     * var logreg = new analytics.LogReg();
     * // create the input matrix and vector for fitting the model
     * var mat = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
     * var vec = new la.Vector([1, 0, -1, -2]);
     * // if openblas is used, fit the model
     * if (require('qminer').flags.blas) {
     *     logreg.fit(mat, vec);
     * };
     * // create an output stream object and save the model
     * var fout = fs.openWrite('logreg_example.bin');
     * logreg.save(fout);
     * fout.close();
     * // create input stream
     * var fin = fs.openRead('logreg_example.bin');
     * // create a Logistic Regression object that loads the model and parameters from input stream
     * var logreg2 = new analytics.LogReg(fin);
     */
 exports.LogReg.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} hazardModelParam
* An object used for the construction of {@link module:analytics.PropHazards}.
* @property {number} [lambda = 0] - The regularization parameter.
*/
/**
 * Proportional Hazards Model
 * @class
 * @classdesc Proportional Hazards Model  with a constant hazard function. Uses Newtons method to compute the weights.
 * <b>Before use: QMiner must be built with the OpenBLAS library.</b>
 * @param {module:analytics~hazardModelParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link module:analytics~hazardModelParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
 * @example
 * // import analytics module
 * var analytics = require('qminer').analytics;
 * // create a Proportional Hazard model
 * var hazard = new analytics.PropHazards();
 */
 exports.PropHazards = function (arg) { return Object.create(require('qminer').analytics.PropHazards.prototype); }
/**
    * Gets the parameters of the model.
    * @returns {module:analytics~hazardModelParam} The parameters of the model.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a Proportional Hazard model
    * var hazard = new analytics.PropHazards({ lambda: 5 });
    * // get the parameters of the model
    * var param = hazard.getParams();
    */
 exports.PropHazards.prototype.getParams = function () { return { lambda: 0.0 }; }
/**
    * Sets the parameters of the model.
    * @param {module:analytics~hazardModelParam} params - The parameters given to the model.
    * @returns {module:analytics.PropHazards} Self. The model parameters have been updated.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a Proportional Hazard model
    * var hazard = new analytics.PropHazards({ lambda: 5 });
    * // set the parameters of the model
    * hazard.setParams({ lambda: 10 });
    */
 exports.PropHazards.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.PropHazards.prototype); }
/**
     * Fits a column matrix of feature vectors `X` onto the response variable `y`.
     * @param {module:la.Matrix} X - The column matrix which stores the feature vectors.
     * @param {module:la.Vector} y - The response variable.
     * @param {number} [eps] - The epsilon used for convergence.
     * @returns {module:analytics.PropHazards} Self. The model has been updated.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the Proportional Hazards model
     * var hazards = new analytics.PropHazards();
     * // create the input matrix and vector for fitting the model
     * var mat = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
     * var vec = new la.Vector([1, 0, -1, -2]);
     * // if openblas used, fit the model
     * if (require('qminer').flags.blas) {
     *     hazards.fit(mat, vec);
     * };
     */
 exports.PropHazards.prototype.fit = function(X, y, eps) { return Object.create(require('qminer').analytics.PropHazards.prototype); }
/**
     * Returns the expected response for the provided feature vector.
     * @param {module:la.Vector} x - The feature vector.
     * @returns {number} The expected response.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the Proportional Hazards model
     * var hazards = new analytics.PropHazards();
     * // create the input matrix and vector for fitting the model
     * var mat = new la.Matrix([[1, 1], [1, -1]]);
     * var vec = new la.Vector([3, 3]);
     * // if openblas used, fit the model and get the prediction
     * if (require('qminer').flags.blas) {
     *     // fit the model
     *     hazards.fit(mat, vec);
     *     // create a vector for the prediction
     *      var test = new la.Vector([1, 2]);
     *     // predict the value
     *     var prediction = hazards.predict(test);
     * };
     */
 exports.PropHazards.prototype.predict = function(x) { return 0.0; }
/**
     * The models weights. Type {@link module:la.Vector}.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create the Proportional Hazards model
     * var hazards = new analytics.PropHazards();
     * // get the weights
     * var weights = hazards.weights;
     */
 exports.PropHazards.prototype.weights = Object.create(require('qminer').la.Vector.prototype);
/**
     * Saves the model into the output stream.
     * @param {module:fs.FOut} fout - The output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create the Proportional Hazards model
     * var hazards = new analytics.PropHazards();
     * // create the input matrix and vector for fitting the model
     * var mat = new la.Matrix([[1, 0, -1, 0], [0, 1, 0, -1]]);
     * var vec = new la.Vector([1, 0, -1, -2]);
     * // if openblas used, fit the model
     * if (require('qminer').flags.blas) {
     *     hazards.fit(mat, vec);
     * };
     * // create an output stream and save the model
     * var fout = fs.openWrite('hazards_example.bin');
     * hazards.save(fout);
     * fout.close();
     * // create input stream
     * var fin = fs.openRead('hazards_example.bin');
     * // create a Proportional Hazards object that loads the model and parameters from input stream
     * var hazards2 = new analytics.PropHazards(fin);
     */
 exports.PropHazards.prototype.save = function(fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} nnetParam
* An object used for the construction of {@link module:analytics.NNet}.
* @property {Array.<number>} [layout = [1, 2, 1]] - The array representing the network schema.
* @property {number} [learnRate = 0.1] - The learning rate.
* @property {number} [momentum = 0.5] - The momentum of optimization.
* @property {string} [tFuncHidden = 'tanHyper'] - Type of activation function used on hidden nevrons. Possible options are `'tanHyper'`, `'sigmoid'`, `'fastTanh'`, `'softPlus'`, `'fastSigmoid'` and `'linear'`.
* @property {string} [tFuncOut = 'tanHyper'] - Type of activation function used on output nevrons. Possible options are `'tanHyper'`, `'sigmoid'`, `'fastTanh'`, `'softPlus'`, `'fastSigmoid'` and `'linear'`.
*/
/**
* Neural Network Model.
* @class
* @classdesc Holds online/offline neural network model.
* @param {module:analytics~nnetParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link module:analytics~nnetParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import module
* var analytics = require('qminer').analytics;
* // create a new Neural Networks model
* var nnet = new analytics.NNet({ layout: [3, 5, 2], learnRate: 0.2, momentum: 0.6 });
* // create the matrices for the fitting of the model
* var matIn = new la.Matrix([[1, 0], [0, 1], [1, 1]]);
* var matOut = new la.Matrix([[-1, 8], [-3, -3]]);
* // fit the model
* nnet.fit(matIn, matOut);
* // create the vector for the prediction
* var test = new la.Vector([1, 1, 2]);
* // predict the value of the vector
* var prediction = nnet.predict(test);
*/
 exports.NNet = function (arg) { return Object.create(require('qminer').analytics.NNet.prototype); }
/**
    * Get the parameters of the model.
    * @returns {module:analytics~nnetParam} The constructor parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a Neural Networks model
    * var nnet = new analytics.NNet();
    * // get the parameters
    * var params = nnet.getParams();
    */
 exports.NNet.prototype.getParams = function () { return { layout: Object.create(require('qminer').la.IntVector.prototype), learnRate: 0.0, momentum: 0.0, tFuncHidden: "", TFuncOut: "" }; }
/**
    * Sets the parameters of the model.
    * @params {module:analytics~nnetParam} params - The given parameters.
    * @returns {module:analytics.NNet} Self. The model parameters have been updated.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a Neural Networks model
    * var nnet = new analytics.NNet();
    * // set the parameters
    * nnet.setParams({ learnRate: 1, momentum: 10, layout: [1, 4, 3] });
    */
 exports.NNet.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.NNet.prototype); }
/**
    * Fits the model.
    * @param {module:la.Vector | module:la.Matrix} X - The input data.
    * @param {module:la.Vector | module:la.Matrix} Y - The output data.
    * <br> If `X` and `Y` are both {@link module:la.Vector}, then the fitting is in online mode.
    * <br> If `X` and `Y` are both {@link module:la.Matrix}, then the fitting is in batch mode.
    * @returns {module:analytics.NNet} Self. The model has been updated.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a Neural Networks model
    * var nnet = new analytics.NNet({ layout: [2, 3, 4] });
    * // create the matrices for the fitting of the model
    * var matIn = new la.Matrix([[1, 0], [0, 1]]);
    * var matOut = new la.Matrix([[1, 1], [1, 2], [-1, 8], [-3, -3]]);
    * // fit the model
    * nnet.fit(matIn, matOut);
    */
 exports.NNet.prototype.fit = function (input, output) { return Object.create(require('qminer').analytics.NNet.prototype); }
/**
    * Gets the prediction of the vector.
    * @param {module:la.Vector} vec - The prediction vector.
    * @returns {module:la.Vector} The prediction of vector `vec`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a Neural Networks model
    * var nnet = new analytics.NNet({ layout: [2, 3, 4] });
    * // create the matrices for the fitting of the model
    * var matIn = new la.Matrix([[1, 0], [0, 1]]);
    * var matOut = new la.Matrix([[1, 1], [1, 2], [-1, 8], [-3, -3]]);
    * // fit the model
    * nnet.fit(matIn, matOut);
    * // create the vector for the prediction
    * var test = new la.Vector([1, 1]);
    * // predict the value of the vector
    * var prediction = nnet.predict(test);
    */
 exports.NNet.prototype.predict = function (vec) { return Object.create(require('qminer').la.Vector.prototype); }
/**
    * Saves the model.
    * @param {module:fs.FOut} fout - The output stream.
    * @returns {module:fs.FOut} The output stream `fout`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * var fs = require('qminer').fs;
    * // create a Neural Networks model
    * var nnet = new analytics.NNet({ layout: [2, 3, 4] });
    * // create the matrices for the fitting of the model
    * var matIn = new la.Matrix([[1, 0], [0, 1]]);
    * var matOut = new la.Matrix([[1, 1], [1, 2], [-1, 8], [-3, -3]]);
    * // fit the model
    * nnet.fit(matIn, matOut);
    * // create an output stream object and save the model
    * var fout = fs.openWrite('nnet_example.bin');
    * nnet.save(fout);
    * fout.close();
    * // load the Neural Network model from the binary
    * var fin = fs.openRead('nnet_example.bin');
    * var nnet2 = new analytics.NNet(fin);
    */
 exports.NNet.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} tokenizerParam
* An object used for the construction of {@link module:analytics.Tokenizer}.
* @property {string} [type='unicode'] - The type of the tokenizer. The different types are:
*<br>1. 'simple' - Creates break on white spaces.
*<br>2. 'html' - Creates break on white spaces and ignores html tags.
*<br>3. 'unicode' - Creates break on white spaces and normalizes unicode letters, e.g. o?=o?= changes to cso?=z.
*/
/**
 * Tokenizer
 * @class
 * @classdesc Breaks text into tokens (i.e. words).
 * @param {module:analytics~tokenizerParam} [arg] - Construction arguments. If arg is not given it uses the `'unicode'` tokenizer type.
 * @example
 * // import analytics module
 * var analytics = require('qminer').analytics;
 * // construct Tokenizer object
 * var tokenizer = new analytics.Tokenizer({ type: "simple" });
 */
 exports.Tokenizer = function (arg) { return Object.create(require("qminer").analytics.Tokenizer.prototype); }
/**
    * Tokenizes given string.
    * @param {String} str - String given to tokenize.
    * @returns {Array.<String>} Array of tokens. The number of tokens is equal to number of words in input `str`.
    * Only keeps words, skips all punctuation.
    * Tokenizing contractions (i.e. don't) depends on which type you use. Example: type `'html'` breaks contractions into 2 tokens.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // construct model
    * var tokenizer = new analytics.Tokenizer();
    * // string you wish to tokenize
    * var string = "What a beautiful day!";
    * // tokenize string using getTokens
    * var tokens = tokenizer.getTokens(string);
    * // output:
    * tokens = ["What", "a", "beautiful", "day"];
    */
 exports.Tokenizer.prototype.getTokens = function (str) { return [""]; }
/**
    * Breaks string into sentences.
    * @param {String} str - String given to break into sentences.
    * @returns {Array.<String>} Array of sentences. The number of sentences is equal to number of sentences in input `str`.
    * How function breaks sentences depends on where you use a full-stop, exclamation mark, question mark or the new line command.
    * Careful: the space between the lines is not ignored.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // construct model
    * var tokenizer = new analytics.Tokenizer();
    * // string you wish to tokenize
    * var string = "C++? Alright. Let's do this!";
    * // tokenize text using getSentences
    * var tokens = tokenizer.getSentences(string);
    * // output:
    * tokens = ["C++", " Alright", " Let's do this"];
    */
 exports.Tokenizer.prototype.getSentences = function (str) { return [""]; }
/**
    * Breaks string into paragraphs.
    * @param {String} str - String given to break into paragraphs.
    * @returns {Array.<String>} Array of paragraphs. The number of paragraphs is equal to number of paragraphs in input `str`.
    * When function detects escape sequences `'\n'`, `'\r'` or `'\t'` it breaks text as new paragraph.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // construct model
    * var tokenizer = new analytics.Tokenizer();
    * // string you wish to tokenize
    * var string = "Yes!\t No?\n Maybe...";
    * // tokenize text using getParagraphs
    * var tokens = tokenizer.getParagraphs(string);
    * // output:
    * tokens = ["Yes", " No", " Maybe"];
    */
 exports.Tokenizer.prototype.getParagraphs = function (str) { return [""]; }
/**
* @typedef {Object} MDSParam
* An object used for the construction of {@link module:analytics.MDS}.
* @property {number} [maxSecs=500] - The maximum time period to compute Multidimensional Scaling of a matrix.
* @property {number} [maxStep=5000] - The maximum number of iterations.
* @property {number} [minDiff=1e-4] - The minimum difference criteria in MDS.
* @property {string} [distType="Euclid"] - The type of distance used. Available types: "Euclid", "Cos", "SqrtCos".
*/
/**
* Multidimensional Scaling
* @class
* @classdesc Scales a higher level vectors into a 2D vector space such that the distances between vectors are preserved as well as possible.
* @param {module:analytics~MDSParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link module:analytics~MDSParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import analytics module
* var analytics = require('qminer').analytics;
* // construct a MDS instance
* var mds = new analytics.MDS({ maxStep: 300, distType: 'Cos' });
* // create the multidimensional matrix
* var mat = new la.Matrix({ rows: 50, cols: 10, random: true });
* // get the 2d representation of mat
* var mat2d = mds.fitTransform(mat);
*/
 exports.MDS = function (arg) { return Object.create(require('qminer').analytics.MDS.prototype); }
/**
    * Get the parameters.
    * @returns {module:analytics~MDSParam} The constructor parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a MDS instance
    * var mds = new analytics.MDS();
    * // get the (default) parameters of the instance
    * // returns { maxStep: 5000, maxSecs: 300, minDiff: 1e-4, distType: "Euclid" }
    * var params = mds.getParams();
    */
 exports.MDS.prototype.getParams = function () { return { maxStep: 0, maxSecs: 0, minDiff: 0, distType: "" }; }
/**
    * Set the parameters.
    * @param {module:analytics~MDSParam} params - The constructor parameters.
    * @returns {module:analytics.MDS} Self. The model parameters have been updated.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a MDS instance
    * var mds = new analytics.MDS();
    * // get the (default) parameters of the instance
    * // returns { maxStep: 5000, maxSecs: 300, minDiff: 1e-4, distType: "Euclid" }
    * var params = mds.getParams();
    */
 exports.MDS.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.MDS.prototype); }
/**
    * Get the MDS of the given matrix.
    * @param {module:la.Matrix | module:la.SparseMatrix} mat - The multidimensional matrix.
    * @param {function} [callback] - The callback function receiving the error parameter (`err`) and the result parameter (`res`).
    * <i>Only for the asynchronous function.</i>
    * @returns {module:la.Matrix} The matrix of dimensions `mat.cols` x 2, where the i-th row of the matrix is the 2D representation
    * of the i-th column of `mat`.
    * @example <caption>Asynchronous function</caption>
    * // import the modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a MDS instance
    * var mds = new analytics.MDS();
    * // create the multidimensional matrix
    * var mat = new la.Matrix({ rows: 50, cols: 10, random: true });
    * // get the 2d representation of mat
    * mds.fitTransformAsync(mat, function (err, res) {
    *    if (err) throw err;
    *    // successful calculation
    *    var mat2d = res;
    * });
    * @example <caption>Synchronous function</caption>
    * // import the modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a MDS instance
    * var mds = new analytics.MDS();
    * // create the multidimensional matrix
    * var mat = new la.Matrix({ rows: 50, cols: 10, random: true });
    * // get the 2d representation of mat
    * var mat2d = mds.fitTransform(mat);
    */
 exports.MDS.prototype.fitTransform = function (mat, callback) { return Object.create(require('qminer').la.Matrix.prototype); }
/**
    * Save the MDS model.
    * @param {module:fs.FOut} fout - The output stream.
    * @returns {module:fs.FOut} The output stram `fout`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var fs = require('qminer').fs;
    * // create a MDS instance
    * var mds = new analytics.MDS({ iter: 200, MaxStep: 10 });
    * // create the file output stream
    * var fout = new fs.openWrite('MDS.bin');
    * // save the MDS instance
    * mds.save(fout);
    * fout.close();
    * // load the MDS instance
    * var fin = fs.openRead('MDS.bin');
    * var mds2 = new analytics.MDS(fin);
    */
 exports.MDS.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} KMeansParam
* An object used for the construction of {@link module:analytics.KMeans}.
* @property {number} [iter=10000] - The maximum number of iterations.
* @property {number} [k=2] - The number of centroids.
* @property {boolean} [allowEmpty=true] - Whether to allow empty clusters to be generated.
* @property {boolean} [calcDistQual=false] - Whether to calculate the quality measure based on distance, if false relMeanCentroidDist will return 'undefined'
* @property {string} [centroidType="Dense"] - The type of centroids. Possible options are `'Dense'` and `'Sparse'`.
* @property {string} [distanceType="Euclid"] - The distance type used at the calculations. Possible options are `'Euclid'` and `'Cos'`.
* @property {boolean} [verbose=false] - If `false`, the console output is supressed.
* @property {Array.<number>} [fitIdx] - The index array used for the construction of the initial centroids.
* @property {Object} [fitStart] - The KMeans model returned by {@link module:analytics.KMeans.prototype.getModel} used for centroid initialization.
* @property {(module:la.Matrix | module:la.SparseMatrix)} fitStart.C - The centroid matrix.
*/
/**
* KMeans Clustering
* @classdesc KMeans Clustering is an iterative, data-partitioning algorithm that assigns observations into K clusters.
* @class
* @param {module:analytics~KMeansParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link module:analytics~KMeansParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import analytics and la modules
* var analytics = require('qminer').analytics;
* var la = require('qminer').la;
* // create a KMeans object
* var KMeans = new analytics.KMeans();
* // create the matrix to be fitted
* var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
* // create the model
* KMeans.fit(X);
* // predict where the columns of the matrix will be assigned
* var Y = new la.Matrix([[1, 1, 0], [-2, 3, 1]]);
* var prediction = KMeans.predict(Y);
*/
 exports.KMeans = function (arg) { return Object.create(require('qminer').analytics.KMeans.prototype); }
/**
    * Returns the parameters.
    * @returns {module:analytics~KMeansParam} The construction parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new KMeans object
    * var KMeans = new analytics.KMeans({ iter: 1000, k: 5 });
    * // get the parameters
    * var json = KMeans.getParams();
    */
 exports.KMeans.prototype.getParams = function () { return { iter: 10000, k: 2, distanceType: "Euclid", centroidType: "Dense", verbose: false }; }
/**
     * Sets the parameters.
     * @param {module:analytics~KMeansParam} params - The construction parameters.
     * @returns {module:analytics.KMeans} Self. The model parameters have been updated.
     * @example
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans();
     * // change the parameters of the KMeans object
     * KMeans.setParams({ iter: 1000, k: 5 });
     */
 exports.KMeans.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.KMeans.prototype); }
/**
     * Calculates the centroids.
     * @param {module:la.Matrix | module:la.SparseMatrix} X - Matrix whose columns correspond to examples.
     * @returns {module:analytics.KMeans} Self. The model has been updated.
     * @example <caption> Asynchronous function </caption>
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fitAsync(X, function (err) {
     *     if (err) console.log(err);
     *     // successful calculation
     * });
     *
     * @example <caption> Synchronous function </caption>
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fit(X);
     */
 exports.KMeans.prototype.fit = function (X) { return Object.create(require('qminer').analytics.KMeans.prototype); }
/**
     * Returns an vector of cluster id assignments.
     * @param {module:la.Matrix | module:la.SparseMatrix} A - Matrix whose columns correspond to examples.
     * @returns {module:la.IntVector} Vector of cluster assignments.
     * @example
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fit(X);
     * // create the matrix of the prediction vectors
     * var pred = new la.Matrix([[2, -1, 1], [1, 0, -3]]);
     * // predict the values
     * var prediction = KMeans.predict(pred);
     */
 exports.KMeans.prototype.predict = function (A) { return Object.create(require('qminer').la.IntVector.prototype); }
/**
     * Transforms the points to vectors of distances to centroids.
     * @param {module:la.Matrix | module:la.SparseMatrix} A - Matrix whose columns correspond to examples.
     * @returns {module:la.Matrix} Matrix where each column represents the squared distances to the centroid vectors.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fit(X);
     * // create the matrix of the transform vectors
     * var matrix = new la.Matrix([[-2, 0], [0, -3]]);
     * // get the transform values of matrix
     * // returns the matrix
     * //  10    17
     * //   1    20
     * //  10     1
     * KMeans.transform(matrix);
     */
 exports.KMeans.prototype.transform = function (A) { return Object.create(require('qminer').la.Matrix.prototype); }
/**
     * Permutates the clusters, and with it {@link module:analytics.KMeans#centroids}, {@link module:analytics.KMeans#medoids} and {@link module:analytics.KMeans#idxv}.
     * @param {module:la.IntVector} mapping - The mapping, where `mapping[4] = 2` means "map cluster 4 into cluster 2".
     * @returns {module:analytics.KMeans} Self. The clusters has been permutated.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fit(X);
     * // create the mapping vector
     * var Mapping = new la.IntVector([1, 0, 2]);
     * // permutate the clusters.
     * KMeans.permuteCentroids(Mapping);
     */
 exports.KMeans.prototype.permuteCentroids = function (mapping) { return Object.create(require('qminer').analytics.KMeans.prototype); }
/**
     * Saves KMeans internal state into (binary) file.
     * @param {module:fs.FOut} fout - The output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fit(X);
     * // create the file output stream
     * var fout = new fs.openWrite('KMeans.bin');
     * // save the KMeans instance
     * KMeans.save(fout);
     * fout.close();
     * // load the KMeans instance
     * var fin = fs.openRead('KMeans.bin');
     * var KMeans2 = new analytics.KMeans(fin);
     */
 exports.KMeans.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
     * The centroids created with the fit method. Type {@link module:la.Matrix}.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * KMeans.fit(X);
     * // get the centroids
     * var centroids = KMeans.centroids;
     */
 exports.KMeans.prototype.centroids = Object.create(require('qminer').la.Matrix.prototype);
/**
    * The medoids created with the fit method. Type {@link module:la.IntVector}.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * // create a new KMeans object
    * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
    * // create a matrix to be fitted
    * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
    * // create the model with the matrix X
    * KMeans.fit(X);
    * // get the centroids
    * var medoids = KMeans.medoids;
    */
 exports.KMeans.prototype.medoids = Object.create(require('qminer').la.IntVector.prototype);
/**
    * The integer vector containing the cluster ids of the training set created with the fit method. Type {@link module:la.IntVector}.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * // create a new KMeans object
    * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
    * // create a matrix to be fitted
    * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
    * // create the model with the matrix X
    * KMeans.fit(X);
    * // get the idxv
    * var idxv = KMeans.idxv;
    */
 exports.KMeans.prototype.idxv = Object.create(require('qminer').la.IntVector.prototype);
/**
     * Returns the normalized weighted distance between the vectors and their centroids
     * using the following formula:
     *  d = \frac{sum_i p_i*sum_j d(x_j,c_i) / n_i}{sum_{k=1}^n d(x_k, mu) / n}
     *    = \frac{sum_{i,j} d(c_i,x_j)}{sum_k d(x_k, mu)}
     *
     * @returns {number} relMeanDist
     */
 exports.KMeans.prototype.relMeanCentroidDist = 0;
/**
* @typedef {Object} DpMeansParam
* An object used for the construction of {@link module:analytics.KMeans}.
* @property {number} [iter=10000] - The maximum number of iterations.
* @property {number} [lambda=1] - Maximum radius of the clusters
* @property {number} [minClusters=2] - Minimum number of clusters
* @property {number} [maxClusters=inf] - Maximum number of clusters
* @property {boolean} [allowEmpty=true] - Whether to allow empty clusters to be generated.
* @property {boolean} [calcDistQual=false] - Whether to calculate the quality measure based on distance, if false relMeanCentroidDist will return 'undefined'
* @property {string} [centroidType="Dense"] - The type of centroids. Possible options are `'Dense'` and `'Sparse'`.
* @property {string} [distanceType="Euclid"] - The distance type used at the calculations. Possible options are `'Euclid'` and `'Cos'`.
* @property {boolean} [verbose=false] - If `false`, the console output is supressed.
* @property {Array.<number>} [fitIdx] - The index array used for the construction of the initial centroids.
* @property {Object} [fitStart] - The KMeans model returned by {@link module:analytics.KMeans.prototype.getModel} used for centroid initialization.
* @property {(module:la.Matrix | module:la.SparseMatrix)} fitStart.C - The centroid matrix.
*/
/**
 * DpMeans Clustering
 * @classdesc DpMeans Clustering is an iterative, data-partitioning algorithm that assigns observations into clusters with the nearest centroid according to some metric.
 *              The number of clusters is not known in advance, but can be upper and lower bounded. Rather the parameter
 *              is the maximum radius of a cluster `lambda`.
 * @class
 * @param {module:analytics~DpMeansParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
 * <br>1. Using the {@link module:analytics~DpMeansParam} object,
 * <br>2. using the file input stream {@link module:fs.FIn}.
 * @example
 * // import analytics and la modules
 * var analytics = require('qminer').analytics;
 * var la = require('qminer').la;
 * // create a KMeans object
 * var dpmeans = new analytics.DpMeans();
 * // create the matrix to be fitted
 * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
 * // create the model
 * dpmeans.fit(X);
 * // predict where the columns of the matrix will be assigned
 * var Y = new la.Matrix([[1, 1, 0], [-2, 3, 1]]);
 * var prediction = dpmeans.predict(Y);
 */
 exports.DpMeans = function (arg) { return Object.create(require('qminer').analytics.DpMeans.prototype); }
/**
    * Returns the parameters.
    * @returns {module:analytics~KMeansParam} The construction parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new DpMeans object
    * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 5 });
    * // get the parameters
    * var json = DpMeans.getParams();
    * console.log(json.lambda);
    */
 exports.DpMeans.prototype.getParams = function () { return { iter: 10000, lambda: 2, distanceType: "Euclid", centroidType: "Dense", verbose: false }; }
/**
     * Sets the parameters.
     * @param {module:analytics~KMeansParam} params - The construction parameters.
     * @returns {module:analytics.DpMeans} Self. The model parameters have been updated.
     * @example
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans();
     * // change the parameters of the DpMeans object
     * DpMeans.setParams({ iter: 1000, lambda: 5 });
     */
 exports.DpMeans.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.DpMeans.prototype); }
/**
     * Calculates the centroids.
     * @param {module:la.Matrix | module:la.SparseMatrix} X - Matrix whose columns correspond to examples.
     * @returns {module:analytics.DpMeans} Self. The model has been updated.
     * @example <caption> Asynchronous function </caption>
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fitAsync(X, function (err) {
     *     if (err) console.log(err);
     *     // successful calculation
     * });
     *
     * @example <caption> Synchronous function </caption>
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fit(X);
     */
 exports.DpMeans.prototype.fit = function (X) { return Object.create(require('qminer').analytics.DpMeans.prototype); }
/**
     * Returns an vector of cluster id assignments.
     * @param {module:la.Matrix | module:la.SparseMatrix} A - Matrix whose columns correspond to examples.
     * @returns {module:la.IntVector} Vector of cluster assignments.
     * @example
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fit(X);
     * // create the matrix of the prediction vectors
     * var pred = new la.Matrix([[2, -1, 1], [1, 0, -3]]);
     * // predict the values
     * var prediction = DpMeans.predict(pred);
     */
 exports.DpMeans.prototype.predict = function (A) { return Object.create(require('qminer').la.IntVector.prototype); }
/**
     * Transforms the points to vectors of distances to centroids.
     * @param {module:la.Matrix | module:la.SparseMatrix} A - Matrix whose columns correspond to examples.
     * @returns {module:la.Matrix} Matrix where each column represents the squared distances to the centroid vectors.
     * @example
     * // import modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fit(X);
     * // create the matrix of the transform vectors
     * var matrix = new la.Matrix([[-2, 0], [0, -3]]);
     * // get the transform values of matrix
     * // returns the matrix
     * //  10    17
     * //   1    20
     * //  10     1
     * DpMeans.transform(matrix);
     */
 exports.DpMeans.prototype.transform = function (A) { return Object.create(require('qminer').la.Matrix.prototype); }
/**
     * Permutates the clusters, and with it {@link module:analytics.DpMeans#centroids}, {@link module:analytics.DpMeans#medoids} and {@link module:analytics.DpMeans#idxv}.
     * @param {module:la.IntVector} mapping - The mapping, where `mapping[4] = 2` means "map cluster 4 into cluster 2".
     * @returns {module:analytics.DpMeans} Self. The clusters have been permuted.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fit(X);
     * if (DpMeans.centroids.cols > 1) {
     *     // create the mapping vector: swap first two centroids
     *     var Mapping = new la.IntVector([1, 0, 2, 3, 4, 5].splice(0,DpMeans.centroids.cols));
     *     console.log(DpMeans.centroids.toString());
     *     // permutate the clusters.
     *     DpMeans.permuteCentroids(Mapping);
     *     console.log(DpMeans.centroids.toString());
     * }
     */
 exports.DpMeans.prototype.permuteCentroids = function (mapping) { return Object.create(require('qminer').analytics.DpMeans.prototype); }
/**
     * Saves DpMeans internal state into (binary) file.
     * @param {module:fs.FOut} fout - The output stream.
     * @returns {module:fs.FOut} The output stream `fout`.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * var fs = require('qminer').fs;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fit(X);
     * // create the file output stream
     * var fout = new fs.openWrite('DpMeans.bin');
     * // save the DpMeans instance
     * DpMeans.save(fout);
     * fout.close();
     * // load the DpMeans instance
     * var fin = fs.openRead('DpMeans.bin');
     * var KMeans2 = new analytics.DpMeans(fin);
     */
 exports.DpMeans.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
     * The centroids created with the fit method. Type {@link module:la.Matrix}.
     * @example
     * // import the modules
     * var analytics = require('qminer').analytics;
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X
     * DpMeans.fit(X);
     * // get the centroids
     * var centroids = DpMeans.centroids;
     * // print the first centroid
     * console.log(centroids.getCol(0));
     */
 exports.DpMeans.prototype.centroids = Object.create(require('qminer').la.Matrix.prototype);
/**
    * The medoids created with the fit method. Type {@link module:la.IntVector}.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * // create a new DpMeans object
    * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
    * // get the centroids
    * var medoids = DpMeans.medoids;
    */
 exports.DpMeans.prototype.medoids = Object.create(require('qminer').la.IntVector.prototype);
/**
    * The integer vector containing the cluster ids of the training set created with the fit method. Type {@link module:la.IntVector}.
    * @example
    * // import the modules
    * var analytics = require('qminer').analytics;
    * // create a new DpMeans object
    * var DpMeans = new analytics.DpMeans({ iter: 1000, lambda: 3 });
    * // get the idxv
    * var idxv = DpMeans.idxv;
    */
 exports.DpMeans.prototype.idxv = Object.create(require('qminer').la.IntVector.prototype);
/**
     * Returns the normalized weighted distance between the vectors and their centroids
     * using the following formula:
     *  d = \frac{sum_i p_i*sum_j d(x_j,c_i) / n_i}{sum_{k=1}^n d(x_k, mu) / n}
     *    = \frac{sum_{i,j} d(c_i,x_j)}{sum_k d(x_k, mu)}
     *
     * @returns {number} relMeanDist
     */
 exports.DpMeans.prototype.relMeanCentroidDist = 0;
/**
* @typedef {Object} TDigestParam
* An object used for the construction of {@link module:analytics.TDigest}.
* @property {number} [minCount=0] - The minimal number of examples before the model is initialized.
* @property {number} [clusters=100] - The number of 1-d clusters (large values lead to higher memory usage).
*/
/**
* TDigest quantile estimation on streams
* @classdesc TDigest is a methods that approximates the CDF function of streaming measurements.
*   Data structure useful for percentile and quantile estimation for online data streams.
*   It can be added to any anomaly detector to set the number of alarms triggered as a percentage of the total samples.
*   Adding new samples to the distribution is achieved through `partialFit` and querying the model (computing quantiles)
*   is implemented by `predict` function.
*   <br> This is based on the Data Lib Sketch Implementation: {@link https://github.com/vega/datalib-sketch/blob/master/src/t-digest.js t-digest.js}
*   <br> Paper: Ted Dunning, Otmar Ertl - {@link https://github.com/tdunning/t-digest/blob/master/docs/t-digest-paper/histo.pdf Computing Extremely Accurate Quantiles Using t-Digests}.
* @class
* @param {module:analytics~TDigestParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link module:analytics~TDigestParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import modules
* var qm = require('qminer');
* var fs = qm.fs;
* var analytics = qm.analytics;
* // create the default TDigest object
* var tdigest = new analytics.TDigest();
* // create the data used for calculating quantiles
* var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
* // fit the TDigest model
* for (var i = 0; i < inputs.length; i++) {
*     tdigest.partialFit(inputs[i]);
* }
* // make the prediction for the 0.1 quantile
* var prediction = tdigest.predict(0.1);
* // save the model
* tdigest.save(fs.openWrite('tdigest.bin')).close();
* // open the tdigest model under a new variable
* var tdigest2 = new analytics.TDigest(fs.openRead('tdigest.bin'));
*/
 exports.TDigest = function (arg) { return Object.create(require('qminer').analytics.TDigest.prototype); }
/**
    * Returns the parameters.
    * @returns {module:analytics~TDigestParam} The construction parameters.
    * @example
    * // import modules
    * var qm = require('qminer');
    * var analytics = qm.analytics;
    * // create the default TDigest object
    * var tdigest = new analytics.TDigest();
    * // get the parameters of the object
    * var params = tdigest.getParams();
    */
 exports.TDigest.prototype.getParams = function () { return { }; }
/**
    * Sets the parameters.
    * @param {module:analytics~TDigestParam} params - The construction parameters.
    * @returns {module:analytics.TDigest} Self. The model parameters have been updated.
    * @example
    * // import modules
    * var qm = require('qminer');
    * var analytics = qm.analytics;
    * // create the default TDigest object
    * var tdigest = new analytics.TDigest();
    * // set the parameters of the object
    * var params = tdigest.setParams({ minCount: 10, clusters: 50 });
    */
 exports.TDigest.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.TDigest.prototype); }
/**
    * Adds a new measurement to the model and updates the approximation of the data distribution.
    * @param {number} x - Input number.
    * @returns {module:analytics.TDigest} Self. The model has been updated.
    * @example
    * // import modules
    * var qm = require('qminer');
    * var analytics = qm.analytics;
    * // create the default TDigest object
    * var tdigest = new analytics.TDigest();
    * // create the data used for calculating quantiles
    * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
    * // fit the TDigest model with all input values
    * for (var i = 0; i < inputs.length; i++) {
    *     tdigest.partialFit(inputs[i]);
    * }
    */
 exports.TDigest.prototype.partialFit = function (X) { return Object.create(require('qminer').analytics.TDigest.prototype); }
/**
    * Returns a quantile given input number, that is the approximate fraction of samples smaller than the input (0.05 means that 5% of data is smaller than the input value).
    * @param {number} x - Input number.
    * @returns {number} Quantile (between 0 and 1).
    * @example
    * // import modules
    * var qm = require('qminer');
    * var analytics = qm.analytics;
    * // create the default TDigest object
    * var tdigest = new analytics.TDigest();
    * // create the data used for calculating quantiles
    * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
    * // fit the TDigest model
    * for (var i = 0; i < inputs.length; i++) {
    *     tdigest.partialFit(inputs[i]);
    * }
    * // make the prediction for the 0.1 quantile
    * var prediction = tdigest.predict(0.1);
    */
 exports.TDigest.prototype.predict = function (x) { return 0; }
/**
    * Saves TDigest internal state into (binary) file.
    * @param {module:fs.FOut} fout - The output stream.
    * @returns {module:fs.FOut} The output stream `fout`.
    * @example
    * // import modules
    * var qm = require('qminer');
    * var fs = require('qminer').fs;
    * var analytics = qm.analytics;
    * var fs = qm.fs;
    * // create the default TDigest object
    * var tdigest = new analytics.TDigest();
    * // create the data used for calculating quantiles
    * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
    * // fit the TDigest model
    * for (var i = 0; i < inputs.length; i++) {
    *     tdigest.partialFit(inputs[i]);
    * }
    * // save the model
    * tdigest.save(fs.openWrite('tdigest.bin')).close();
    * // open the tdigest model under a new variable
    * var tdigest2 = new analytics.TDigest(fs.openRead('tdigest.bin'));
    */
 exports.TDigest.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
    * Returns true when the model has enough data to initialize. Type `boolean`.
    * @example
    * // import modules
    * var qm = require('qminer');
    * var analytics = qm.analytics;
    * var fs = qm.fs;
    * // create the default TDigest object
    * var tdigest = new analytics.TDigest();
    * // check if the model has enough data to initialize
    * if (tdigest.init) { console.log("Ready to initialize"); }
    */
 exports.TDigest.prototype.init = false;
/**
     * Returns the current size of the algorithms summary in number of tuples.
     */
 exports.TDigest.size = 0;
/**
     * Returns the models current memory consumption.
     */
 exports.TDigest.memory = 0;
/**
* @typedef {Object} GkParam
* An object used for the construction of {@link module:analytics.Gk}.
* @property {number} [eps=0.01] - Determines the relative error of the algorithm.
* @property {boolean} [autoCompress=true] - Whether the summary should be compresses automatically or manually.
*/
/**
 * @classdesc Greenwald - Khanna algorithm for online quantile estimation. Given
 *   a comulative probability p, the algorithm returns the approximate value of
 *   the p-th quantile.
 *
 *   The algorithm works by keeping a summary of buckets, each summarizing a
 *   range of values. Through the run of the algorithm new buckets are created
 *   and periodically merged if possible.
 *
 *   It is was first explained in:
 *   "Space-Efficient Online Computation of Quantile Summaries"
 *   http://infolab.stanford.edu/~datar/courses/cs361a/papers/quantiles.pdf
 *
 *   The error is bounded by the rank of the output element (not by the absolute value).
 *   Specifically, the worst case error in rank is bounded by eps*n, where n is the
 *   number of elements in the summary.
 *
 * @class
 * @param {module:analytics~GkParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
 * <br>1. Using the {@link module:analytics~GkParam} object,
 * <br>2. using the file input stream {@link module:fs.FIn}.
 *
 * @example
 * // import modules
 * var qm = require('qminer');
 * var fs = require('qminer').fs;
 * var analytics = qm.analytics;
 *
 * // create the Gk object
 * var gk = new analytics.Gk({
 *     eps: 0.001,
 *     autoCompress: true
 * });
 *
 * // create the data used for calculating quantiles
 * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
 *
 * // fit the model
 * for (var i = 0; i < inputs.length; i++) {
 *     gk.partialFit(inputs[i]);
 * }
 *
 * // make the prediction for the 0.1 quantile
 * var prediction = gk.predict(0.1);
 * // save the model
 * gk.save(fs.openWrite('gk.bin')).close();
 * // open the gk model under a new variable
 * var gk2 = new analytics.Gk(fs.openRead('gk.bin'));
 */
 exports.Gk = function (arg) { return Object.create(require('qminer').analytics.Gk.prototype); }
/**
     * Returns the models' parameters as a JavaScript object (JSON). These parameters
     * are the same as are set through the constructor.
     *
     * @returns {module:analytics~GkParam} The construction parameters.
     *
     * var analytics = qm.analytics;
     * var gk = new analytics.Gk();
     * var params = gk.getParams();
     *
     * console.log(params.eps);
     * console.log(params.autoCompress);
     */
 exports.Gk.prototype.getParams = function () { return { }; }
/**
     * Adds a new value to the summary.
     *
     * @param {number} val - the value
     * @returns {module:analytics.Gk} reference to self
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.CountWindowGk();
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     */
 exports.Gk.compress = function (fout) { return Object.create(require('qminer').analytics.Gk.prototype); }
/**
     * Given an input cumulative probability, returns a quantile associated with that
     * probability (e.g. for input 0.5 it will return the median).
     *
     * @param {number|Array} pVals - the p-values which we a querying
     * @returns {number|Array} quantiles - depending whether the input was a single value or array the method returns a quantile or array of quantiles
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.Gk({
     *     eps: 0.1
     * });
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     * gk.partialFit(1.0);
     * gk.partialFit(3.0);
     * gk.partialFit(2.0);
     *
     * console.log(gk.predict(0.01));   // prints the first percentile
     * console.log(gk.predict(0.25));   // prints the first quartile
     * console.log(gk.predict(0.5));    // prints the median
     */
 exports.Gk.prototype.predict = function (x) { return 0; }
/**
     * Manually runs the compression procedure.
     *
     * @returns reference to self
     */
 exports.Gk.compress = function (fout) { return Object.create(require('qminer').analytics.Gk.prototype); }
/**
     * Saves the objects state into the output stream.
     *
     * @param {module:fs.FOut} fout - the output stream
     * @returns {module:fs.FOut} - the output stream
     */
 exports.Gk.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
     * Returns the current size of the algorithms summary in number of tuples.
     */
 exports.Gk.size = 0;
/**
     * Returns the models current memory consumption.
     */
 exports.Gk.memory = 0;
/**
* @typedef {Object} BiasedGkParam
* An object used for the construction of {@link module:analytics.BiasedGk}.
* @property {number} [targetProb=0.01] - The probability where the algorithm is most accurate. Its accuracy is determined as eps*max(p, targetProb) when targetProb < 0.5 and eps*max(1-p, 1-targetProb) when targetProb >= 0.5. Higher values of `targetProb` allow for a smaller memory footprint.
* @property {number} [eps=0.1] - Parameter which determines the accuracy.
* @property {string} [compression="periodic"] - Determines when the algorithm compresses its summary. Options are: "periodic", "aggressive" and "manual".
* @property {boolean} [useBands=true] - Whether the algorithm should use the 'band' subprocedure. Using this subprocedure should result in a smaller summary.
*/
/**
 * @classdesc The CKMS (GK adapted for biased quantiles) algorithm for online
 *   biased quantile estimation. Given a probability p the algorithm returns
 *   the approximate value of the p-th quantile. The algorithm is most accurate
 *   in one of the extremes (which extreme depends on the parameters).
 *
 *   The algorithm works by keeping a summary of buckets, each summarizing a
 *   range of values. Through the run of the algorithm new buckets are created
 *   and periodically merged if possible.
 *
 *   It was first explained in:
 *   "Effective Computation of Biased Quantiles over Data Streams"
 *   https://www.cs.rutgers.edu/~muthu/bquant.pdf
 *
 *   Only the biased version is implemented (the targeted version is flawed).
 *
 *   The error is bounded by the rank of the element (not the absolute value).
 *   Specifically, the worst case relative error is bounded by max(eps*p, eps*p0)
 *   where eps is an accuracy paramter, p0 is the `targetProb` and p is the
 *   p-value set as the parameter of function `predict`.
 *
 * @class
 * @param {module:analytics~BiasedGkParam | module:fs:FIn} [arg] - Constructor arguments. There are 2 ways of constructing:
 * <br>1. Using the {@link module:analytics~BiasedGkParam} object,
 * <br>2. using the file input stream {@link module:fs.FIn}.
 *
 * @example
 * // import modules
 * var qm = require('qminer');
 * var fs = require('qminer').fs;
 * var analytics = qm.analytics;
 *
 * // create the BiasedGk object
 * var gk = new analytics.BiasedGk({
 *     eps: 0.1,
 *     targetProb: 0.99,
 *     compression: 'periodic',
 *     useBands: true
 * });
 *
 * // create the data used for calculating quantiles
 * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
 *
 * // fit the model
 * for (var i = 0; i < inputs.length; i++) {
 *     gk.partialFit(inputs[i]);
 * }
 *
 * // make the prediction for the 0.1 quantile
 * var prediction = gk.predict(0.1);
 * // save the model
 * gk.save(fs.openWrite('gk.bin')).close();
 * // open the gk model under a new variable
 * var gk2 = new analytics.BiasedGk(fs.openRead('gk.bin'));
 *
 */
 exports.BiasedGk = function (arg) { return Object.create(require('qminer').analytics.BiasedGk.prototype); }
/**
     * Returns the models' parameters as a JavaScript object (JSON). These parameters
     * are the same as are set through the constructor.
     *
     * @returns {module:analytics~BiasedGkParam} The construction parameters.
     *
     * var analytics = qm.analytics;
     * var gk = new analytics.BiasedGk();
     * var params = gk.getParams();
     *
     * console.log(params.targetProb);
     * console.log(params.eps);
     * console.log(params.autoCompress);
     * console.log(params.useBands);
     */
 exports.BiasedGk.prototype.getParams = function () { return { }; }
/**
     * Adds a new value to the summary.
     *
     * @param {number} val - the value
     * @returns {module:analytics.Gk} reference to self
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.BiasedGk();
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     */
 exports.BiasedGk.compress = function (fout) { return Object.create(require('qminer').analytics.BiasedGk.prototype); }
/**
     * Given an input cumulative probability, returns a quantile associated with that
     * probability (e.g. for input 0.5 it will return the median).
     *
     * @param {number|Array} pVals - the p-values which we a querying
     * @returns {number|Array} quantiles - depending whether the input was a single value or array the method returns a quantile or array of quantiles
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.BiasedGk({
     *     eps: 0.1,
     *     targetProb: 0.01
     * });
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     * gk.partialFit(1.0);
     * gk.partialFit(3.0);
     * gk.partialFit(2.0);
     *
     * console.log(gk.predict(0.01));   // prints the first percentile
     * console.log(gk.predict(0.25));   // prints the first quartile
     * console.log(gk.predict(0.5));    // prints the median
     */
 exports.BiasedGk.prototype.predict = function (x) { return 0; }
/**
     * Manually runs the compression procedure.
     *
     * @returns reference to self
     */
 exports.BiasedGk.compress = function (fout) { return Object.create(require('qminer').analytics.BiasedGk.prototype); }
/**
     * Saves the objects state into the output stream.
     *
     * @param {module:fs.FOut} fout - the output stream
     * @returns {module:fs.FOut} - the output stream
     */
 exports.BiasedGk.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
     * Returns the current size of the algorithms summary in number of tuples.
     */
 exports.BiasedGk.size = 0;
/**
     * Returns the models current memory consumption.
     */
 exports.BiasedGk.memory = 0;
/**
* @typedef {Object} CountWindowGkParam
* An object used for the construction of {@link module:analytics.CountWindowGk}.
* @property {number} [windowSize=10000] - Number of values to store in the window.
* @property {number} [quantileEps=0.01] - Worst-case error of the quantile estimation procedure.
* @property {number} [countEps=0.005] - Worst-case error of the sliding window (exponential histogram) procedure.
*/
/**
 * @classdesc Greenwald - Khanna algorithm for quantile estimation on sliding windows. Given
 *   a cumulative probability p, the algorithm returns the approximate value of the
 *   p-th quantile of all the values in a sliding window.
 *
 *   The algorithm works by keeping a summary of buckets. Each bucket summarizes a
 *   range of values. Through the run of the algorithm, new buckets are created and
 *   old ones merged. To allow for the computation on a sliding window, each bucket
 *   uses an Exponential Histogram structure to remember how many values it summarizes.
 *
 *   It is summarized in:
 *   "Online Algorithm for Approximate Quantile Queries on Sliding Windows"
 *   http://dl.acm.org/citation.cfm?id=2954329
 *
 *   The error is not bounded by the absolute value of the output, but by the error
 *   in rank of the output element. For instance, if we have 100 elements and query
 *   the median, we could get the 48-th (p=0.48), 50-th (p=0.5), 51-th (p=0.51),
 *   etc. element.
 *
 *   The algorithms error is bounded by two factors. The first is the quantile
 *   estimation factor `quantileEps` occurs because of the summary structure and
 *   defines the maximum size of the buckets. The second type of error `countEps`
 *   occurs because of the Exponential Histograms inside the buckets.
 *
 *   The worst-case error is bounded by (quantileEps + 2*countEps + O(countEps^2)),
 *   although in practice the error is lower.
 *
 *   This version of the algorithm uses a count-based fixed size sliding window.
 *
 * @class
 * @param {module:analytics~FixedWindowGkParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
 * <br>1. Using the {@link module:analytics~FixedWindowGkParam} object,
 * <br>2. using the file input stream {@link module:fs.FIn}.
 *
 * @example
 * // import modules
 * var qm = require('qminer');
 * var fs = qm.fs;
 * var analytics = qm.analytics;
 *
 * // create the default TDigest object
 * var gk = new analytics.CountWindowGk({
 *     windowSize: 5,
 *     quantileEps: 0.001,
 *     countEps: 0.0005
 * });
 *
 * // create the data used for calculating quantiles
 * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
 *
 * // fit the TDigest model
 * for (var i = 0; i < inputs.length; i++) {
 *     gk.partialFit(inputs[i]);
 * }
 *
 * // make the prediction for the 0.1 quantile
 * var prediction = gk.predict(0.1);
 * // save the model
 * gk.save(fs.openWrite('gk.bin')).close();
 * // open the gk model under a new variable
 * var gk2 = new analytics.CountWindowGk(fs.openRead('gk.bin'));
 *
 */
 exports.CountWindowGk = function (arg) { return Object.create(require('qminer').analytics.CountWindowGk.prototype); }
/**
     * Returns the models' parameters as a JavaScript object (JSON). These parameters
     * are the same as are set through the constructor.
     *
     * @returns {module:analytics~FixedWindowGkParam} The construction parameters.
     *
     * var analytics = qm.analytics;
     * var gk = new qm.analytics.CountWindowGk({ windowSize: 100 }); // window 100 elements long
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     * gk.partialFit(1.0);
     * gk.partialFit(3.0);
     * gk.partialFit(2.0);
     * var params = gk.getParams();
     *
     * console.log(params.windowSize);
     * console.log(params.quantileEps);
     * console.log(params.countEps);
     */
 exports.CountWindowGk.prototype.getParams = function () { return { }; }
/**
     * Appends a new value to the sliding window. If an old value
     * falls outside the sliding window, it is forgotten.
     *
     * @param {number} val - the value
     * @returns {module:analytics.CountWindowGk} reference to self
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.CountWindowGk();
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     *
     */
 exports.CountWindowGk.partialFit = function (fout) { return Object.create(require('qminer').analytics.CountWindowGk.prototype); }
/**
     * Given an input cumulative probability, returns a quantile associated with that
     * probability (e.g. for input 0.5 it will return the median).
     *
     * @param {number} p - cumulative probability between 0 and 1 (both inclusive)
     * @returns {number} quantile associated with p
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.CountWindowGk({
     *     windowSize: 100    // window 100 elements long
     * });
     * gk.partialFit(1.0);
     * gk.partialFit(2.0);
     * gk.partialFit(1.0);
     * gk.partialFit(3.0);
     * gk.partialFit(2.0);
     *
     * console.log(gk.predict(0.01));   // prints the first percentile
     * console.log(gk.predict(0.25));   // prints the first quartile
     * console.log(gk.predict(0.5));    // prints the median
     */
 exports.CountWindowGk.prototype.predict = function (x) { return 0; }
/**
     * Saves the objects state into a binary file.
     *
     * @param {module:fs.FOut} fout - the output stream
     * @returns {module:fs.FOut} the output stream `fout`
     *
     * @example
     * var qm = require('qminer');
     * var fs = qm.fs;
     * var gk = new qm.analytics.CountWindowGk();
     *
     * // save the model
     * gk.save(fs.openWrite('gk.bin')).close();
     * // open the model under a new variable
     * var gk = new analytics.CountWindowGk(fs.openRead('gk.bin'));
     */
 exports.CountWindowGk.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} TimeWindowGkParam
* An object used for the construction of {@link module:analytics.TimeWindowGk}.
* @property {number} [window=1000*60*60] - Duration of the time window.
* @property {number} [quantileEps=0.01] - Worst-case error of the quantile estimation procedure.
* @property {number} [countEps=0.005] - Worst-case error of the sliding window (exponential histogram) procedure.
*/
/**
 * @classdesc Greenwald - Khanna algorithm for quantile estimation on sliding windows. Given
 *   a cumulative probability p, the algorithm returns the approximate value of the
 *   p-th quantile of all the values in a sliding window.
 *
 *   The algorithm works by keeping a summary of buckets. Each bucket summarizes a
 *   range of values. Through the run of the algorithm, new buckets are created and
 *   old ones merged. To allow for the computation on a sliding window, each bucket
 *   uses an Exponential Histogram structure to remember how many values it summarizes.
 *
 *   It is summarized in:
 *   "Online Algorithm for Approximate Quantile Queries on Sliding Windows"
 *   http://dl.acm.org/citation.cfm?id=2954329
 *
 *   The error is not bounded by the absolute value of the output, but by the error
 *   in rank of the output element. For instance, if we have 100 elements and query
 *   the median, we could get the 48-th (p=0.48), 50-th (p=0.5), 51-th (p=0.51),
 *   etc. element.
 *
 *   The algorithms error is bounded by two factors. The first is the quantile
 *   estimation factor `quantileEps` occurs because of the summary structure and
 *   defines the maximum size of the buckets. The second type of error `countEps`
 *   occurs because of the Exponential Histograms inside the buckets.
 *
 *   The worst-case error is bounded by (quantileEps + 2*countEps + O(countEps^2)),
 *   although in practice the error is lower.
 *
 *   This version of the algorithm uses a time-based fixed duration sliding window.
 *
 * @class
 * @param {module:analytics~TimeWindowGkParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
 * <br>1. Using the {@link module:analytics~TimeWindowGkParam} object,
 * <br>2. using the file input stream {@link module:fs.FIn}.
 *
 * @example
 * // import modules
 * var qm = require('qminer');
 * var fs = qm.fs;
 * var analytics = qm.analytics;
 *
 * // create the default object
 * var gk = new analytics.TimeWindowGk({
 *     window: 5,
 *     quantileEps: 0.001,
 *     countEps: 0.0005
 * });
 *
 * // create the data used for calculating quantiles
 * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
 * var times = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 *
 * // fit the model
 * for (var i = 0; i < inputs.length; i++) {
 *     gk.partialFit(times[i], inputs[i]);
 * }
 *
 * // make the prediction for the 0.1 quantile
 * var prediction = gk.predict(0.1);
 * // save the model
 * gk.save(fs.openWrite('gk.bin')).close();
 * // open the gk model under a new variable
 * var gk2 = new analytics.TimeWindowGk(fs.openRead('gk.bin'));
 */
 exports.TimeWindowGk = function (arg) { return Object.create(require('qminer').analytics.TimeWindowGk.prototype); }
/**
     * Returns the models' parameters as a JavaScript object (JSON). These parameters
     * are the same as are set through the constructor.
     *
     * @returns {module:analytics~TimeWindowGkParam} The construction parameters.
     *
     * var qm = require('qminer');
     * var fs = qm.fs;
     * var analytics = qm.analytics;
     *
     * // create the default object
     * var gk = new analytics.TimeWindowGk({
     *     window: 5,
     *     quantileEps: 0.001,
     *     countEps: 0.0005
     * });
     *
     * // create the data used for calculating quantiles
     * var inputs = [10, 1, 2, 8, 9, 5, 6, 4, 7, 3];
     * var times = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     *
     * // fit the model
     * for (var i = 0; i < inputs.length; i++) {
     *     gk.partialFit(times[i], inputs[i]);
     * }
     * var params = gk.getParams();
     *
     * console.log(params.window);
     * console.log(params.quantileEps);
     * console.log(params.countEps);
     */
 exports.TimeWindowGk.prototype.getParams = function () { return { }; }
/**
     * Adds a new observation to the window. The window is updated with the provided timestamp,
     * all records which fall outside the new window are forgotten.
     *
     * @param {number|Date} timestamp - time of the observation
     * @param {number} [value] - the observation
     * @returns {module:analytics.TimeWindowGk} reference to self
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.TimeWindowGk({
     *     window: 1000*60*60*24*2    // window is 2 days
     * });
     * gk.partialFit(new Date('2017-06-06'), 1.0);
     * gk.partialFit(new Date('2017-06-07').getTime(), 1.0);
     * gk.partialFit(new Date('2017-06-08'));  // only move the time window, the first value is forgotten
     */
 exports.TimeWindowGk.partialFit = function (fout) { return Object.create(require('qminer').analytics.TimeWindowGk.prototype); }
/**
     * Given an input cumulative probability, returns a quantile associated with that
     * probability (e.g. for input 0.5 it will return the median).
     *
     * @param {number} p - cumulative probability between 0 and 1 (both inclusive)
     * @returns {number} quantile associated with p
     *
     * @example
     * var qm = require('qminer');
     *
     * var gk = new qm.analytics.TimeWindowGk({
     *     window: 100    // window is 2 days
     * });
     * gk.partialFit(0, 1.0);
     * gk.partialFit(1, 1.0);
     * gk.partialFit(2, 1.0);
     * gk.partialFit(3, 1.0);
     * gk.partialFit(4, 1.0);
     *
     * console.log(gk.predict(0.01));   // prints the first percentile
     * console.log(gk.predict(0.25));   // prints the first quartile
     * console.log(gk.predict(0.5));    // prints the median
     */
 exports.TimeWindowGk.prototype.predict = function (x) { return 0; }
/**
     * Saves the objects state into a binary file.
     *
     * @param {module:fs.FOut} fout - the output stream
     * @returns {module:fs.FOut} the output stream `fout`
     *
     * @example
     * var qm = require('qminer');
     * var fs = qm.fs;
     * var gk = new qm.analytics.TimeWindowGk({
     *     window: 100    // window is 2 days
     * });
     * gk.partialFit(0, 1.0);
     * gk.partialFit(1, 1.0);
     * gk.partialFit(2, 1.0);
     * gk.partialFit(3, 1.0);
     * gk.partialFit(4, 1.0);
     * // save the model
     * gk.save(fs.openWrite('gk.bin')).close();
     * // open the model under a new variable
     * var gk = new analytics.TimeWindowGk(fs.openRead('gk.bin'));
     */
 exports.TimeWindowGk.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
/**
* @typedef {Object} RecSysParam
* An object used for the construction of {@link module:analytics.RecommenderSys}.
* @property {number} [iter=10000] - The maximum number of iterations.
* @property {number} [k=2] - The number of centroids.
* @property {number} [tol=1e-3] - The tolerance.
* @property {boolean} [verbose=false] - If false, the console output is supressed.
*/
/**
* Recommender System
* @classdesc The recommender system algorithm using Weighted Non-negative Matrix Factorization to predict the
* unknown values. If `A` is a matrix with unknown values it calculates the matrices `U` and `V` such that `U*V` approximates `A`.
* @class
* @param {module:analytics~RecSysParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
* <br>1. Using the {@link module:analytics~RecSysParam} object,
* <br>2. using the file input stream {@link module:fs.FIn}.
* @example
* // import analytics and la modules
* var analytics = require('qminer').analytics;
* var la = require('qminer').la;
* // create a Recommender System object
* var recSys = new analytics.RecommenderSys({ tol: 1e-3, iter: 10000, k: 2, verbose: false });
* // create the matrix to be fitted
* var X = new la.Matrix([[1, 2, 1], [1, 1, 3]]);
* // create the model
* recSys.fit(X);
*/
 exports.RecommenderSys = function (arg) { return Object.create(require('qminer').analytics.RecommenderSys.prototype); }
/**
    * Returns the parameters.
    * @returns {module:analytics~RecSysParam} The construction parameters.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new KMeans object
    * var recSys = new analytics.RecommenderSys({ iter: 1000, k: 5 });
    * // get the parameters
    * var json = recSys.getParams();
    */
 exports.RecommenderSys.prototype.getParams = function () { return { iter: 10000, k: 2, tol: 1e-3, verbose: false }; }
/**
    * Sets the parameters.
    * @param {module:analytics~RecSysParam} params - The construction parameters.
    * @returns {module:analytics.RecommenderSys} Self. The parameters has been updated.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new Recommender System object
    * var recSys = new analytics.RecommenderSys();
    * // change the parameters of the Recommender System object
    * recSys.setParams({ iter: 1000, k: 5 });
    */
 exports.RecommenderSys.prototype.setParams = function (params) { return Object.create(require('qminer').analytics.RecommenderSys.prototype); }
/**
     * Gets the model.
     * @returns {Object} An object `recSysModel` containing the properties:
     * <br>1. `recSysModel.U` - The matrix `U` from the weighted NMF. Type {@link module:la.Matrix}.
     * <br>2. `recSysModel.V` - The matrix `V` from the weighted NMF. Type {@link module:la.Matrix}.
     * @example
     * // import modules
     * //var analytics = require('qminer').analytics;
     * //var la = require('qminer').la;
     * // create a new Recommender System object
     * //var recSys = new analytics.RecommenderSys({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * //var X = new la.Matrix([[1, 5, 0], [1, 0, 3]]);
     * // create the model with the matrix X
     * //recSys.fit(X);
     * // get the model
     * //var model = recSys.getModel();
     */
 exports.RecommenderSys.prototype.getModel = function () { return { U: Object.create(require('qminer').la.Matrix.prototype), V: Object.create(require('qminer').la.Matrix.prototype) }; }
/**
    * Fits the input matrix to the recommender model.
    * @param {module:la.Matrix | module:la.SparseMatrix} A - Matrix with the ratings, where it A_ij element is the rating that the i-th person
    * gave to the j-th item. If A_ij = 0, the data doesn't exist.
    * @returns {module:analytics.RecommenderSys} Self. The model has been fitted.
    * @example <caption> Asynhronous function </caption>
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new Recommender System object
    * var recSys = new analytics.RecommenderSys({ iter: 1000, k: 2 });
    * // create a matrix to be fitted
    * var X = new la.Matrix([[1, 5, 0], [1, 0, 3]]);
    * // create the model with the matrix X
    * recSys.fitAsync(X, function (err) {
    *    if (err) { console.log(err); }
    *    // successful calculation
    * });
    * @example <caption> Synhronous function </caption>
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create a new Recommender System object
    * var recSys = new analytics.RecommenderSys({ iter: 1000, k: 2 });
    * // create a matrix to be fitted
    * var X = new la.Matrix([[1, 5, 0], [1, 0, 3]]);
    * // create the model with the matrix X
    * recSys.fit(X);
    */
 exports.RecommenderSys.prototype.fit = function (A) { return Object.create(require('qminer').analytics.RecommenderSys.prototype); }
/**
    * Saves RecommenderSys internal state into (binary) file.
    * @param {module:fs.FOut} fout - The output stream.
    * @returns {module:fs.FOut} The output stream `fout`.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var fs = require('qminer').fs;
    * // create a new Recommender System object
    * var recSys = new analytics.RecommenderSys();
    * // change the parameters of the Recommender System object
    * recSys.setParams({ iter: 1000, k: 5 });
    * // create the file output stream
    * var fout = new fs.openWrite('recsys.bin');
    * // save the RecommenderSys instance
    * recSys.save(fout);
    * fout.close();
    * // load the RecommenderSys instance
    * var fin = fs.openRead('recsys.bin');
    * var recSys2 = new analytics.RecommenderSys(fin);
    */
 exports.RecommenderSys.prototype.save = function (fout) { return Object.create(require('qminer').fs.FOut.prototype); }
 exports.GraphCascade = function (arg) { return Object.create(require('qminer').analytics.GraphCascade.prototype); }
/**
    * Sets the cascade time for a given node
    * @param {string} nodeId -
    * @param {number} timestamp -
    */
/**
    * Computes the posterior for timestamps of unobserved nodes
    * @param {number} timestamp - current time
    */
/**
    * Returns the posteriors
    * @returns {Object} - model
    */
/**
    * Returns the pruned directed acyclic graph
    * @returns {Object} - dag
    */
/**
    * Returns the topologically ordered node names
    * @returns {Object} - nodeArr
    */


    ///////////////////////////////////////////////////
    /////////////   DATA PREPROCESSING   //////////////
    ///////////////////////////////////////////////////

    /**
    * PreprocessingF
    * @namespace
    * @desc Preprocessing functions for preparing labels in formats accepted
    * by learning modules in {@link module:analytics}.
    */
    var preprocessing = preprocessing || {};
    // namespacing: http://addyosmani.com/blog/essential-js-namespacing/

    /**
    * Transforming arrays with labels to vector appropriate for binary classifiers.
    * @class
    * @classdesc
    * Transform given array of labels into binary vector with different
    * numeric value for elements when label matches specified label and
    * for other elements. By default, these values are +1 for matching
    * labels, and -1 for the rest.
    * @param {Array} y - Labels.
    * @param {string | number} positiveLabel - Positive label.
    * @param {number} [positiveId = 1] - Value when matching positive label.
    * @param {number} [negativeId = -1] - Value when not matching positive label.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create binarizer with 'b' as positive label
    * var binarizer = new analytics.preprocessing.Binarizer('b');
    */
    preprocessing.Binarizer = function (positiveLabel, positiveId, negativeId) {
        if (positiveLabel == undefined) { throw "Binarizer needs positive label"; }

        this.positiveLabel = positiveLabel;
        this.positiveId = (positiveId == undefined) ? 1 : positiveId;
        this.negativeId = (negativeId == undefined) ? -1 : negativeId;

        this.fit = function () {
            // do nothing
        }

        /**
        * Transform given array of labels to binary numeric vector.
        * @param {(Array<number> | Array<string> | module:la.Vector | module:la.StrVector)} y - Labels.
        * @return {modul:la.Vector} Binarized vector.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // create binarizer with 'b' as positive label
        * var binarizer = new analytics.preprocessing.Binarizer('b');
        * // get vector with binarized labels
        * var bins = binarizer.transform(['a','b','a','c']);
        */
        this.transform = function (y) {
            var target = new la.Vector();
            for (var i = 0; i < y.length; i++) {
                target.push(y[i] === this.positiveLabel ? this.positiveId : this.negativeId);
            }
            return target;
        }
    };

    /**
    * Applies the model's `decisionFunction` method (if exists) on each column of matrix `X`.
    * @param {Object} model - The model, that has the `decisionFunction` method.
    * @param {module:la.SparseMatrix} X - The matrix.
    * @returns {module:la.Vector} The dense vector where the i-th value is the value the `model.decisionFunction`
    * returned for the sparse vector `X[i]`.
    * @example
    * // TODO
    */
    preprocessing.applyModel = function (model, X) {
        if (model.decisionFunction == undefined) {
            throw "preprocessing.applyModel: model doesn't have a method called decisionFunction!";
        }
        var target = new la.Vector();
        for (var i = 0; i < X.cols; i++) {
            target.push(model.decisionFunction(X[i]));
        }
        return target;
    }

    // Exports preprocessing namespace
    exports.preprocessing = preprocessing;

    // SVM
    /**
    * Get the model.
    * @returns {Object} The `svmModel` object containing the property:
    * <br> 1. `svmModel.weights` - The weights of the model. Type {@link module:la.Vector}.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a SVC model
    * var SVC = new analytics.SVC();
    * // get the properties of the model
    * var model = SVC.getModel();
    */
    exports.SVC.prototype.getModel = function() { return { weights: this.weights, bias: this.bias }; }
    /**
    * Get the model.
    * @returns {Object} The `svmModel` object containing the property:
    * <br> 1. `svmModel.weights` - The weights of the model. Type {@link module:la.Vector}.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a SVR model
    * var SVR = new analytics.SVR();
    * // get the properties of the model
    * var model = SVR.getModel();
    */
    exports.SVR.prototype.getModel = function() { return { weights: this.weights, bias: this.bias }; }

    // Ridge Regression
    /**
    * Gets the model.
    * @returns {Object} The `ridgeRegModel` object containing the property:
    * <br> 1. `ridgeRegModel.weights` - The weights of the model. Type {@link module:la.Vector}.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create the Ridge Regression model
    * var regmod = new analytics.RidgeReg();
    * // get the model
    * var model = regmod.getModel();
    */
    exports.RidgeReg.prototype.getModel = function () { return { weights: this.weights }; }

    // Recursive Linear Regression
    /**
    * Gets the model.
    * @returns {Object} The `recLinRegModel` object containing the property:
    * <br> 1. `recLinRegModel.weights` - The weights of the model. Type {@link module:la.Vector}.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create the Recursive Linear Regression model
    * var linreg = new analytics.RecLinReg({ dim: 10 });
    * // get the model
    * var model = linreg.getModel(); // returns { weights: new require('qminer').la.Vector(); }
    */
    exports.RecLinReg.prototype.getModel = function () { return { weights: this.weights } }

    /**
    * @typedef {Object} oneVsAllParam
    * An object used for the construction of {@link module:analytics.OneVsAll}.
    * @property {function} [model] - Constructor for binary model to be
    * used internaly. Constructor should expect only one parameter.
    * @property {Object} [modelParam] - Parameter for `oneVsAllParam.model` constructor.
    * @property {number} [categories] - Number of categories.
    * @property {boolean} [verbose = false] - If false, the console output is supressed.
    */

    /**
    * @classdesc One vs All model for multiclass prediction. Builds binary model
    * for each category and predicts the one with the highest score. Binary model is
    * provided as part of the constructor.
    * @class
    * @param {module:analytics~oneVsAllParam} [arg] - Construction arguments.
    * @example
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // create a new OneVsAll object with the model analytics.SVC
    * var onevsall = new analytics.OneVsAll({ model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2 });
    */
    exports.OneVsAll = function (arg) {
        // remember parameters
        var model = arg.model;
        var modelParam = arg.modelParam;
        var cats = arg.cats;
        var verbose = arg.verbose == undefined ? false : arg.verbose;
        // trained models
        var models = [ ];

        /**
        * Gets the parameters.
        * @returns {module:analytics~oneVsAllParam} The constructor parameters.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // create a new OneVsAll object with the model analytics.SVC
        * var onevsall = new analytics.OneVsAll({ model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2 });
        * // get the parameters
        * // returns the JSon object
        * // { model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2, models: [] }
        * var params = onevsall.getParams();
        */
        this.getParams = function () {
            return { model: model, modelParam: modelParam, cats: cats, models: models }
        };

        /**
        * Sets the parameters.
        * @param {module:analytics~OneVsAllParam} params - The constructor parameters.
        * @returns {module:analytics.OneVsAll} Self. The parameters are changed.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // create a new OneVsAll object with the model analytics.SVC
        * var onevsall = new analytics.OneVsAll({ model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2 });
        * // set the parameters
        * var params = onevsall.setParams({ model: analytics.SVR, modelParam: { c: 12, maxTime: 10000}, cats: 3, verbose: true });
        */
        this.setParams = function (params) {
            model = params.model == undefined ? model : params.model;
            modelParam = params.modelParam == undefined ? modelParam : params.modelParam;
            cats = params.cats == undefined ? cats : params.cats;
            verbose = params.verbose == undefined ? verbose : params.verbose;
        }

        /**
         * Apply all models to the given vector and returns a vector of scores, one for each category.
         * Semantic of scores depend on the provided binary model.
         * @param {module:la.Vector | module:la.SparseVector | module:la.Matrix | module:la.SparseMatrix} X -
         * Feature vector or matrix with feature vectors as columns.
         * @returns {module:la.Vector | module:la.Matrix} The score and label of the input `X`:
         * <br>1. {@link module:la.Vector} of scores, if `X` is of type {@link module:la.Vector} or {@link module:la.SparseVector}.
         * <br>2. {@link module:la.Matrix} with columns corresponding to instances, and rows corresponding to labels, if `X` is of type {@link module:la.Matrix} or {@link module:la.SparseMatrix}.
         * @example
         * // import modules
         * var analytics = require('qminer').analytics;
         * var la = require('qminer').la;
         * // create a new OneVsAll object with the model analytics.SVC
         * var onevsall = new analytics.OneVsAll({ model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2 });
         * // create the data (matrix and vector) used to fit the model
         * var matrix = new la.Matrix([[1, 2, 1, 1], [2, 1, -3, -4]]);
         * var vector = new la.Vector([0, 0, 1, 1]);
         * // fit the model
         * onevsall.fit(matrix, vector);
         * // create the vector for the decisionFunction
         * var test = new la.Vector([1, 2]);
         * // give the vector to the decision function
         * var prediction = onevsall.decisionFunction(test); // returns the vector of scores
         */
        this.decisionFunction = function(X) {
            // check what is our input
            if (X instanceof la.Vector || X instanceof la.SparseVector) {
                // evaluate all models
                var scores = new la.Vector();
                for (var cat = 0; cat < cats; cat++) {
                    scores.push(models[cat].decisionFunction(X));
                }
                return scores;
            } else if (X instanceof la.Matrix || X instanceof la.SparseMatrix) {
                // create matrix where cols are instances and rows are scores for categories
                var scores = new la.Matrix({rows: cats, cols: X.cols});
                for (var i = 0; i < X.cols; i++) {
                    var x_i = X.getCol(i);
                    for (var cat = 0; cat < cats; cat++) {
                        scores.put(cat, i, models[cat].decisionFunction(x_i));
                    }
                }
                return scores;
            } else {
                throw "analytics.OneVsAll.decisionFunction: Input data of unsupported type!";
            }
        }

        /**
         * Apply all models to the given vector and returns category with the highest score.
         * @param {module:la.Vector | module:la.SparseVector | module:la.Matrix | module:la.SparseMatrix} X -
         * Feature vector or matrix with feature vectors as columns.
         * @returns {number | module:la.IntVector}
         * <br>1. number of the category with the higher score, if `X` is {@link module:la.Vector} or {@link module:la.SparseVector}.
         * <br>2. {@link module:la.IntVector} of categories with the higher score for each column of `X`, if `X` is {@link module:la.Matrix} or {@link module:la.SparseMatrix}.
         * @example
         * // import modules
         * var analytics = require('qminer').analytics;
         * var la = require('qminer').la;
         * // create a new OneVsAll object with the model analytics.SVC
         * var onevsall = new analytics.OneVsAll({ model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2 });
         * // create the data (matrix and vector) used to fit the model
         * var matrix = new la.Matrix([[1, 2, 1, 1], [2, 1, -3, -4]]);
         * var vector = new la.Vector([0, 0, 1, 1]);
         * // fit the model
         * onevsall.fit(matrix, vector);
         * // create the vector for the prediction
         * var test = new la.Vector([1, 2]);
         * // get the prediction of the vector
         * var prediction = onevsall.predict(test); // returns 0
         */
        this.predict = function(X) {
            // evaluate all models
            var scores = this.decisionFunction(X);
            // select maximal one
            if (scores instanceof la.Vector) {
                return scores.getMaxIdx();
            } else if (scores instanceof la.Matrix) {
                var predictions = new la.IntVector();
                for (var i = 0; i < scores.cols; i++) {
                    predictions.push(scores.getCol(i).getMaxIdx());
                }
                return predictions;
            } else {
                throw "analytics.OneVsAll.predict: decisionFunction returns unsupported type!";
            }
        }

        // X = feature matrix
        // y = target label from 0..cats
        /**
         * Apply all models to the given vector and returns category with the highest score.
         * @param {module:la.Matrix | module:la.SparseMatrix} X - training instance feature vectors.
         * @param {module:la.Vector} y - target category for each training instance. Categories must
         * be integer numbers between `0` and `oneVsAllParam.categories-1`.
         * @returns {module:analytics.OneVsAll} Self. The models have been fitted.
         * @example
         * // import modules
         * var analytics = require('qminer').analytics;
         * var la = require('qminer').la;
         * // create a new OneVsAll object with the model analytics.SVC
         * var onevsall = new analytics.OneVsAll({ model: analytics.SVC, modelParam: { c: 10, maxTime: 1000 }, cats: 2 });
         * // create the data (matrix and vector) used to fit the model
         * var matrix = new la.Matrix([[1, 2, 1, 1], [2, 1, -3, -4]]);
         * var vector = new la.Vector([0, 0, 1, 1]);
         * // fit the model
         * onevsall.fit(matrix, vector);
         */
        this.fit = function(X, y) {
            models = [ ];
            // make model for each category
            for (var cat = 0; cat < cats; cat++) {
                if (verbose) {
                    console.log("Fitting label", (cat + 1), "/", cats);
                };
                // prepare targert vector for current category
                var target = (y instanceof la.Matrix) ?
                    // we have a special bianary vector for each category, make it into -1/+1
                    (new exports.preprocessing.Binarizer(1)).transform(y.getRow(cat)) :
                    // we have a vector with label for each element, get out -1/+1 vector
                    (new exports.preprocessing.Binarizer(cat)).transform(y);
                // get the model
                var catModel = new model(modelParam);
                models.push(catModel.fit(X, target));
            }
            if (verbose) {
                console.log("Done!");
            };
            return this;
        }
    };

    /**
     * Threshold Model
     * @class
     * @classdesc The Threshold model. Uses the methods from the {@link module:analytics.metrics}.
     * @param {Object} [arg] - The constructor parameters.
     * @param {string} [arg.target] - Target type. Possible options are `"recall"` and `"precision"`.
     * @param {TODO} [arg.level] - TODO
     * @example
     * // TODO
     */
    exports.ThresholdModel = function(params) {
        // what do we optimize
        this.target = params.target;
        if (this.target === "recall" || this.target === "precision") {
            this.level = params.level;
        }
        // threshold model
        this.model = null;

        // apply all models to the given vector and return distance to the class boundary
        // x = dense vector with prediction score for each class
        // result = traslated predictions based on thresholds
        /**
         * Apply all models to the given vector and returns the distance to the class boundary.
         * @param {number | module:la.Vector} x - The prediction score for each class.
         * @returns {number | module:la.Vector}
         * <br>1. value of the translated prediction based on the threshold, if `x` is `number`,
         * <br>2. {@link module:la.Vector} of translated prediction based on the threshold, if `x` is {@link module:la.Vector}.
         * @example
         * // TODO
         */
        this.decisionFunction = function(x) {
            if (x instanceof Number) {
                // just transate based on the model's threshold
                return x - this.model;
            } else if (x instanceof la.Vector) {
                // each element is a new instance
                var scores = new la.Vector();
                for (var i = 0; i < x.length; i++) {
                    scores.push(x[i] - this.model);
                }
                return scores;
            } else {
                throw "analytics.ThresholdModel.decisionFunction: Input data of unsupported type!";
            }
        }

        // return the most likely category
        // x = dense vector with prediction score for each class
        // result = array of positive label ids
        /**
         * Returns the most likely category.
         * @param {number | module:la.Vector} x - The prediction score for each class.
         * @returns {number | module:la.Vector}
         * <br>1. value of the positive label IDs, if `x` is `number`,
         * <br>2. {@link module:la.Vector} of the positive label IDs, if `x` is {@link module:la.Vector}.
         * @example
         * // TODO
         */
        this.predict = function(x) {
            // evaluate all models
            var scores = this.decisionFunction(x)
            // check what we get
            if (scores instanceof la.Vector) {
                return res = new la.Vector();
                for (var i = 0; i < scores.length; i++) {
                    res.push(scores[i] > 0 ? 1 : -1);
                }
                return res;
            } else {
                return scores > 0 ? 1 : -1;
            }
        }

        // X = vector of predictions for each instance (output of decision_funcition)
        // y = target labels (1 or -1)
        /**
         * Fits the model.
         * @param {module:la.Vector} X - Prediction for each instance (output of descisionFunction).
         * @param {number} y - The target labels (1 or -1).
         * @example
         * // TODO
         */
        this.fit = function(X, y) {
            if (this.target === "f1") {
                // find threshold that maximizes F1 measure
                this.model = exports.metrics.bestF1Threshold(y, X);
            } else if (this.target === "recall") {
                // find threshold that results in desired recall
                this.model = exports.metrics.desiredRecallThreshold(y, X, this.level);
            } else if (this.target === "precision") {
                // find threshold that results in desired precision
                this.model = exports.metrics.desiredPrecisionThreshold(y, X, this.level);
            } else {
                throw "Unknown threshold model target: " + this.target;
            }
        }
    }


    /**
    * Metrics
    * @namespace
    * @desc Classification and regression metrics.
    * @example <caption>Batch classification example</caption>
    * // import metrics module
    * var analytics = require('qminer').analytics;
    *
    * // true and predicted lables
    * var true_lables = [0, 1, 0, 0, 1];
    * var pred_prob = [0.3, 0.5, 0.2, 0.5, 0.8];
    *
    * // compute ROC curve
    * var roc = analytics.metrics.rocCurve(true_lables, pred_prob);
    * @example <caption>Online classification example</caption>
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // true and predicted lables
    * var true_lables = [0, 1, 0, 0, 1];
    * var pred_prob = [0.3, 0.5, 0.2, 0.5, 0.8];
    *
    * // create predictionCurve instance
    * var predictionCurve = new analytics.metrics.PredictionCurve();
    *
    * // simulate data flow
    * for (var i in true_lables) {
    *    // push new value
    *    predictionCurve.push(true_lables[i], pred_prob[i]);
    *}
    *
    * var roc = predictionCurve.roc(); // get ROC
    * @example <caption>Batch regression example</caption>
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // true and predicted data
    * var true_vals = [1, 2, 3, 4, 5];
    * var pred_vals = [3, 4, 5, 6, 7];
    *
    * // use batch MAE method
    * analytics.metrics.meanAbsoluteError(true_vals, pred_vals);
    * @example <caption>Online regression example</caption>
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // true and predicted data
    * var true_vals = [1, 2, 3, 4, 5];
    * var pred_vals = [3, 4, 5, 6, 7];
    *
    * // create online MAE metric instance
    * var mae = new analytics.metrics.MeanAbsoluteError();
    *
    * // simulate data flow
    * for (var i in true_vals) {
    *   // push new value
    *   mae.push(true_vals[i], pred_vals[i]);
    * }
    * // get updated error
    * mae.getError();
    */
    var metrics = metrics || {};
    // namespacing: http://addyosmani.com/blog/essential-js-namespacing/

    ///////////////////////////////////////////////////
    ///////////// CLASSIFICATION METRICS //////////////
    ///////////////////////////////////////////////////

    /**
    * For evaluating provided categories from binary? classifiers.
    * @class
    * @classdesc Class implements several classification measures (precision, recall, F1, accuracy).
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lable(s).
    * @param {(Array<number> | module:la.Vector)} yPred - Predicted (estimated) lable(s).
    */
    metrics.ClassificationScore = function (yTrue, yPred) {
        /**
        * Returns `Object` containing different classification measures.
        * @returns {Object} scores - Object with different classification socres.
        * @returns {number} scores.count - Count.
        * @returns {number} scores.TP - Number of true positives.
        * @returns {number} scores.TN - Number of true negative.
        * @returns {number} scores.FP - Number of false positives.
        * @returns {number} scores.FN - Number of false positives.
        * @returns {number} scores.all - Number of all results.
        * @returns {number} scores.accuracy - Accuracy score. Formula: `(tp + tn) / (tp + fp + fn + tn)`.
        * @returns {number} scores.precision - Precision score. Formula: `tp / (tp + fp)`.
        * @returns {number} scores.recall - Recall score. Formula: `tp / (tp + fn)`.
        * @returns {number} scores.f1 - F1 score. Formula:  `2 * (precision * recall) / (precision + recall)`.
        */
        this.scores = {
            count: 0, predictionCount: 0,
            TP: 0, TN: 0, FP: 0, FN: 0,
            all: function () { return this.TP + this.FP + this.TN + this.FN; },
            precision: function () { return (this.FP == 0) ? 1 : this.TP / (this.TP + this.FP); },
            recall: function () { return (this.FN == 0) ? 1 : this.TP / (this.TP + this.FN); },
            f1: function () { return ((this.precision() + this.recall()) == 0) ? 0 :
                2 * this.precision() * this.recall() / (this.precision() + this.recall()); },
            accuracy: function () { return (this.TP + this.TN) / this.all(); }
        };

        /**
        * Adds prediction to the current statistics. Labels can be either integers.
        * or integer array (when there are zero or more then one lables).
        * @param {number} correct - Correct lable.
        * @param {number} predicted - Predicted lable.
        */
        this.push = function (correct, predicted) {
            var catCorrect = (correct > 0);
            var catPredicted = (predicted > 0);
            // update counts for correct categories
            if (catCorrect) { this.scores.count++; }
            // update counts for how many times category was predicted
            if (catPredicted) { this.scores.predictionCount++; }
            // update true/false positive/negative count
            if (catCorrect && catPredicted) {
                // both predicted and correct say true
                this.scores.TP++;
            } else if (catCorrect) {
                // this was only correct but not predicted
                this.scores.FN++;
            } else if (catPredicted) {
                // this was only predicted but not correct
                this.scores.FP++;
            } else {
                // both predicted and correct say false
                this.scores.TN++;
            }
        };

        // initialize if we are passed the data
        if (arguments.length >= 2) {
            for (var i = 0; i < yTrue.length; i++) {
                this.push(yTrue[i], yPred[i]);
            }
        }

        // check if input parameters are of correct type and binary
        for (var i = 0; i < arguments.length; i++) {
            // check type
            var argumentType = arguments[i].constructor.name;
            if (argumentType !== "Array" && argumentType !== "Vector") {
                throw new TypeError('input param must be of type "Array" or "Vector", but is ' + argumentType + ' instead');
            }
        }
    };

    /**
    * Accuracy score is the proportion of true results (both true positives and true negatives)
    * among the total number of cases examined.
    * Formula: `(tp + tn) / (tp + fp + fn + tn)`.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Predicted (estimated) lables.
    * @returns {number} Accuracy value.
    */
    metrics.accuracyScore = function (yTrue, yPred) {
        return new metrics.ClassificationScore(yTrue, yPred).scores.accuracy();
    };

    /**
    * Precision score is defined as the proportion of the true positives against all the
    * positive results (both true positives and false positives).
    * Formula: `tp / (tp + fp)`.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Predicted (estimated) lables.
    * @returns {number} Precission score.
    */
    metrics.precisionScore = function (yTrue, yPred) {
        return new metrics.ClassificationScore(yTrue, yPred).scores.precision();
    };

    /**
    * Recall score is intuitively the ability of the classifier to find all the positive samples.
    * Formula: `tp / (tp + fn)`.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Predicted (estimated) lables.
    * @returns {number} Recall score.
    */
    metrics.recallScore = function (yTrue, yPred) {
        return new metrics.ClassificationScore(yTrue, yPred).scores.recall();
    };

    /**
    * The F1 score can be interpreted as a weighted average of the precision and recall, where
    * an F1 score reaches its best value at 1 and worst score at 0. The relative contribution of
    * precision and recall to the F1 score are equal.
    * Formula: `2 * (precision * recall) / (precision + recall)`.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Predicted (estimated) lables.
    * @returns {number} F1 score.
    */
    metrics.f1Score = function (yTrue, yPred) {
        return new metrics.ClassificationScore(yTrue, yPred).scores.f1();
    };

    /**
    * Class implements several prediction curve measures (ROC, AOC, Precision-Recall, ...).
    * @class
    * @classdesc Used for computing ROC curve and other related measures such as AUC.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lable(s) of binary classification in range {-1, 1} or {0, 1}.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @example
    * // import metrics module
    * var metrics = require('qminer').analytics.metrics;
    *
    * // true and predicted lables
    * var true_lables = [0, 1, 0, 0, 1];
    * var pred_prob = [0.3, 0.5, 0.2, 0.5, 0.8];
    *
    * // create predictionCurve instance
    * var predictionCurve = new metrics.PredictionCurve();
    *
    * // simulate data flow
    * for (var i in true_lables) {
    *    // push new value
    *    predictionCurve.push(true_lables[i], pred_prob[i]);
    *}
    *
    * var roc = predictionCurve.roc(); // get ROC
    * var auc = predictionCurve.auc(); // get AUC
    * var pr = predictionCurve.precisionRecallCurve() // get precision-recall curve
    */
    metrics.PredictionCurve = function (yTrue, yPred) {
        /**
        * Count of all examples.
        * @name module:analytics~metrics.PredictionCurve#length
        * @type number
        */
        this.length = 0;
        /**
        * Count of all positive examples.
        * @name module:analytics~metrics.PredictionCurve#allPositives
        * @type number
        */
        this.allPositives = 0;
        /**
        * Count of all negative examples.
        * @name module:analytics~metrics.PredictionCurve#allNegatives
        * @type number
        */
        this.allNegatives = 0;
        // store of predictions and ground truths
        /**
        * Store of ground truths.
        * @name module:analytics~metrics.PredictionCurve#grounds
        * @type module:la.Vector
        */
        this.grounds = new la.Vector();
        /**
        * Store of predictions.
        * @name module:analytics~metrics.PredictionCurve#predictions
        * @type module:la.Vector
        */
        this.predictions = new la.Vector();

        /**
        * Add new measurement with ground score (1 or -1) and predicted value
        * or integer array (when there are zero or more then one lables).
        * @param {number} ground - Correct lable.
        * @param {number} predicted - Estimated probabilities.
        */
        this.push = function (ground, predict) {
            // remember the scores
            this.grounds.push(ground)
            this.predictions.push(predict);
            // update counts
            this.length++;
            if (ground > 0) {
                this.allPositives++;
            } else {
                this.allNegatives++;
            }
        };

        // initialize if we are given data
        if (arguments.length >= 2) {
            for (var i = 0; i < yTrue.length; i++) {
                this.push(yTrue[i], yPred[i]);
            }
        }

        // check if input parameters are of correct type and binary
        for (var i = 0; i < arguments.length; i++) {
            // check type
            var argumentType = arguments[i].constructor.name;
            if (argumentType !== "Array" && argumentType !== "Vector") {
                throw new TypeError('input param must be of type "Array" or "Vector", but is ' + argumentType + ' instead');
            }
        }

        /**
        * Get Receiver Operating Characteristic (ROC) parametrization sampled on `sample` points.
        * @param {number} [sample=10] - Desired number of samples in output.
        * @returns {module:la.Matrix} A matrix with increasing false and true positive rates.
        */
        this.roc = function (sample) {
            // default sample size is 10
            sample = sample || 10;
            // sort according to predictions
            var perm = this.predictions.sortPerm(false);
            // maintaining the results as we go along
            var TP = 0, FP = 0, ROC = [[0, 0]];

            // check input samples
            if (this.allNegatives == 0) throw new Error('No positive samples in yTrue, true positive value should be meaningless.');
            if (this.allNegatives == this.length) throw new Error('No negative samples in yTrue, false positive value should be meaningless.');

            // for figuring out when to dump a new ROC sample
            var unique = 1;
            for (var i = 1; i < perm.perm.length; i++) {
                if (Math.abs(perm.vec[i] - perm.vec[i - 1]) > 1e-8) {
                    unique++;
                }
            }

            var next = Math.floor(unique / sample);

            // go over the sorted results
            for (var i = 0; i < perm.perm.length; i++) {
                // get the ground
                var ground = this.grounds[perm.perm[i]];
                // update TP/FP counts according to the ground
                if (ground > 0) { TP++ } else { FP++; }

                // see if time to do next save
                if ((i < perm.perm.length - 1) && (Math.abs(perm.vec[i] - perm.vec[i + 1]) > 1e-8)) {
                    next = next - 1;
                }

                if (next < 0) {
                    // add new datapoint to the curve
                    ROC.push([FP / this.allNegatives, TP / this.allPositives]);
                    // setup next timer
                    next = Math.floor(unique / sample);
                }
            }
            // add the last point
            ROC.push([1, 1]);
            // return ROC
            return ROC;
        }

        /**
        * Get Area Under the Curve (AUC) of the current curve.
        * @param {number} [sample=10] - Desired number of samples in output.
        * @returns {number} Area under ROC curve.
        */
        this.auc = function (sample) {
            // default sample size is 10
            sample = sample || 10;
            // get the curve
            var curve = this.roc(sample);
            // compute the area
            var result = 0;
            for (var i = 1; i < curve.length; i++) {
                // get edge points
                var left = curve[i - 1];
                var right = curve[i];
                // first the rectangle bellow
                result = result + (right[0] - left[0]) * left[1];
                // an then the triangle above
                result = result + (right[0] - left[0]) * (right[1] - left[1]) / 2;
            }
            return result;
        }

        /**
        * evalPrecisionRecall.
        * @private
        * @param {callback} callback.
        */
        this.evalPrecisionRecall = function (callback) {
            // sort according to predictions
            var perm = this.predictions.sortPerm(false);
            // maintaining the results as we go along
            var TP = 0, FP = 0, TN = this.allNegatives, FN = this.allPositives;
            // go over the sorted results
            for (var i = 0; i < perm.perm.length; i++) {
                // get the ground
                var ground = this.grounds[perm.perm[i]];
                // update TP/FP counts according to the ground
                if (ground > 0) { TP++; FN--; } else { FP++; TN--; }
                // do the update
                if ((TP + FP) > 0 && (TP + FN) > 0 && TP > 0) {
                    // compute current precision and recall
                    var precision = TP / (TP + FP);
                    var recall = TP / (TP + FN);
                    // see if we need to update current bep
                    callback.update(ground, perm.vec[i], precision, recall);
                }
            }
            return callback.finish();
        }

        /**
        * Get precision recall curve sampled on `sample` points.
        * @param {number} [sample=10] - Desired number of samples in output.
        * @returns {module:la.Matrix} Precision-recall pairs.
        */
        this.precisionRecallCurve = function (sample) {
            return this.evalPrecisionRecall(new function (sample, length) {
                // default sample size is 10
                this.sample = sample || 10;
                // curve
                this.curve = [[0, 1]];
                // for figuring out when to dump a new ROC sample
                this.next = Math.floor(length / (this.sample));
                this.counter = this.next;
                // keep last value
                this.precision = 0; this.recall = 0;
                // handlers
                this.update = function (yTrue, yPred, precision, recall) {
                    this.counter = this.counter - 1;
                    if (this.counter <= 0) {
                        // add to the curve
                        this.curve.push([recall, precision]);
                        // setup next timer
                        this.counter = this.next;
                    }
                    // always remember last value
                    this.precision = precision; this.recall = recall;
                }
                this.finish = function () {
                    // add the last point
                    this.curve.push([this.recall, this.precision]);
                    return this.curve;
                }
            }(sample, this.length));
        };

        /**
        * Get break-even point, the value where precision and recall intersect.
        * @returns {number} Break-even point.
        */
        this.breakEvenPoint = function () {
            return this.evalPrecisionRecall(new function () {
                this.minDiff = 1.0; this.bep = -1.0;
                this.update = function (yTrue, yPred, precision, recall) {
                    var diff = Math.abs(precision - recall);
                    if (diff < this.minDiff) { this.minDiff = diff; bep = (precision + recall) / 2; }
                }
                this.finish = function () { return this.bep; }
            }());
        }

        /**
        * Gets threshold for prediction score, which results in the highest F1.
        * @returns {number} Threshold with highest F1 score.
        */
        this.bestF1 = function () {
            return this.evalPrecisionRecall(new function () {
                this.maxF1 = 0.0; this.threshold = 0.0;
                this.update = function (yTrue, yPred, precision, recall) {
                    var f1 = 2 * precision * recall / (precision + recall);
                    if (f1 > this.maxF1) {
                        this.maxF1 = f1;
                        this.threshold = yPred;
                    }
                }
                this.finish = function () { return this.threshold; }
            }());
        }

        /**
        * Gets threshold for prediction score, nearest to specified recall.
        * @param {number} desiredRecall - Desired recall score.
        * @returns {number} Recal Score Threshold. Threshold for recall score, nearest to specified `recall`.
        */
        this.desiredRecall = function (desiredRecall) {
            return this.evalPrecisionRecall(new function () {
                this.recallDiff = 1.0; this.threshold = 0.0;
                this.update = function (yTrue, yPred, precision, recall) {
                    var diff = Math.abs(desiredRecall - recall);
                    if (diff < this.recallDiff) {
                        this.recallDiff = diff;
                        this.threshold = yPred;
                    }
                }
                this.finish = function () { return this.threshold; }
            }());
        }

        /**
        * Gets threshold for prediction score, nearest to specified precision.
        * @param {number} desiredPrecision - Desired precision score.
        * @returns {number} Threshold for prediction score, nearest to specified `precision`.
        */
        this.desiredPrecision = function (desiredPrecision) {
            return this.evalPrecisionRecall(new function () {
                this.precisionDiff = 1.0; this.threshold = 0.0;
                this.update = function (yTrue, yPred, precision, recall) {
                    var diff = Math.abs(desiredPrecision - precision);
                    if (diff < this.precisionDiff) {
                        this.precisionDiff = diff;
                        this.threshold = yPred;
                    }
                }
                this.finish = function () { return this.threshold; }
            }());
        }
    };

    /**
    * Get ROC parametrization sampled on `sample` points.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @param {number} [sample=10] - Desired number of samples in output.
    * @returns {module:la.Matrix} A matrix with increasing false and true positive rates.
    * @example
    * // import metrics module
    * var metrics = require('qminer').analytics.metrics;
    *
    * // true and predicted lables
    * var true_lables = [0, 1, 0, 0, 1];
    * var pred_prob = [0.3, 0.5, 0.2, 0.5, 0.8];
    *
    * // compute ROC curve
    * var roc = metrics.rocCurve(true_lables, pred_prob); // output: [ [ 0, 0 ], [0, 0.5], [[ 0.34, 1 ],], [ 0.67, 0 ], [ 1, 1 ] ]
    */
    metrics.rocCurve = function (yTrue, yPred, sample) {
        return new metrics.PredictionCurve(yTrue, yPred).roc(sample);
    };

    /**
    * Get AUC of the current curve.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @param {number} [sample=10] - Desired number of samples in output.
    * @returns {number} Area under ROC curve.
    * @example
    * // import metrics module
    * var metrics = require('qminer').analytics.metrics;
    *
    * // true and predicted lables
    * var true_lables = [0, 1, 0, 0, 1];
    * var pred_prob = [0.3, 0.5, 0.2, 0.5, 0.8];
    *
    * // compute ROC curve
    * var auc = metrics.rocAucScore(true_lables, pred_prob); // output: 0.92
    */
    metrics.rocAucScore = function (yTrue, yPred, sample) {
        return new metrics.PredictionCurve(yTrue, yPred).auc(sample);
    };

    /**
    * Get precision recall curve sampled on `sample` points.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @param {number} [sample=10] - Desired number of samples in output.
    * @returns {module:la.Matrix} Precision-recall pairs.
    */
    metrics.precisionRecallCurve = function (yTrue, yPred, sample) {
        return new metrics.PredictionCurve(yTrue, yPred).precisionRecallCurve(sample);
    };

    /**
    * Get break-even point, the value where precision and recall intersect.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @returns {number} Break-even point score.
    */
    metrics.breakEventPointScore = function (yTrue, yPred) {
        return new metrics.PredictionCurve(yTrue, yPred).breakEvenPoint();
    };

    /**
    * Gets threshold for prediction score, which results in the highest F1.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @returns {number} Threshold with highest F1 score.
    */
    metrics.bestF1Threshold = function (yTrue, yPred) {
        return new metrics.PredictionCurve(yTrue, yPred).bestF1();
    };

    /**
    * Gets threshold for recall score, nearest to specified recall.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @param {number} desiredRecall - Desired recall score.
    * @returns {number} Threshold for recall score, nearest to specified `recall`.
    */
    metrics.desiredRecallThreshold = function (yTrue, yPred, desiredRecall) {
        return new metrics.PredictionCurve(yTrue, yPred).desiredRecall(desiredRecall);
    };

    /**
    * Gets threshold for prediction score, nearest to specified precision.
    * @param {(Array<number> | module:la.Vector)} yTrue - Ground truth (correct) lables.
    * @param {(Array<number> | module:la.Vector)} yPred - Estimated probabilities.
    * @param {number} desiredPrecision - Desired precision score.
    * @returns {number} Threshold for prediction score, nearest to specified `precision`.
    */
    metrics.desiredPrecisionThreshold = function (yTrue, yPred, desiredPrecision) {
        return new metrics.PredictionCurve(yTrue, yPred).desiredPrecision(desiredPrecision);
    };

    ///////////////////////////////////////////////////
    //////////// ONLINE REGRESSION METRICS ////////////
    ///////////////////////////////////////////////////

    // Online regression metrics used for evaluating online models

    // Main object for online metrics model
    /**
    * createOnlineMetric
    * @ignore
    * @class
    *
    * This provides methods used for event handling. It's not meant to
    * be used directly.
    *
    */
    function createOnlineMetric(callback) {
        var error = -1;
        this.metric = new callback(); // We can hide this later (just delete this)

        // check if input types are of correct type
        function checkPushParams() {
            for (var i = 0, j = arguments.length; i < j; i++) {
                var argumentType = arguments[i].constructor.name;
                if (argumentType !== "Number") {
                    throw new TypeError('input param ' + i + ' must be of type "Number", but is ' + argumentType + ' instead');
                }
            }
        }

        /**
        * Updates metric with ground truth target value `yTrue` and estimated target value `yPred`.
        * @ignore
        * @param {number} yTrue - Ground truth (correct) target value.
        * @param {number} yPred - Estimated target value.
        */
        this.push = function (yTrue, yPred, ref_num) {
            // set default values of optional input parameters
            var yPred = yPred == null ? 0 : yPred;
            var ref_num = ref_num == null ? 0 : ref_num;
            // check if input types are of correct type
            checkPushParams(yTrue, yPred, ref_num);
            // calculate the error with provided function from the callback function
            error = this.metric.update(yTrue, yPred);
        }

        /**
        * Returns error value.
        * @ignore
        * @returns {number} Error value.
        */
        this.getError = function () {
            return error;
        }

        /**
        * Save metric state to provided output stream `fout`.
        * @ignore
        * @param {module:fs.FOut} fout - The output stream.
        * @returns {module:fs.FOut} The output stream `fout`.
        */
        this.save = function (fout) {
            fout.writeJson(this.metric.state);
            return fout;
        }

        /**
        * Load metric state from provided input stream `fin`.
        * @ignore
        * @param {module:fs.FIn} fin - The output stream.
        * @returns {module:fs.FIn} The output stream `fin`.
        */
        this.load = function (fin) {
            this.metric.state = fin.readJson();
            error = this.metric.state.error;
            return fin;
        }

    }

    // MEAN ERROR (ME)
    /**
    * Create new (online) mean error instance.
    * @class
    * @classdesc Online Mean Error (ME) instance.
    * @param {module:fs.FIn} [fin] - Saved state can be loaded via constructor.
    * @extends module:analytics~createOnlineMetric
    */
    metrics.MeanError = function (fin) {
        function metric() {
            this.name = "Mean Error"
            this.shortName = "ME"
            this.state = {
                sumErr: 0,
                count: 0,
                error: 0
            }
            // update function
            this.update = function (yTrue, yPred) {
                var err = yTrue - yPred;
                this.state.sumErr += err;
                this.state.count++;
                this.state.error = this.state.sumErr / this.state.count;
                return this.state.error;
            }
        }
        // create new metric instance, and load state from fin in defined
        var errorMetric = new createOnlineMetric(metric);
        if (typeof fin !== 'undefined') errorMetric.load(fin);

        return errorMetric;
    };

    // MEAN ABSOLUTE ERROR (MAE)
    /**
    * Create new (online) mean absolute error instance.
    * @class
    * @classdesc Online Mean Absolute Error (MAE) instance.
    * @param {module:fs.FIn} [fin] - Saved state can be loaded via constructor.
    * @extends module:analytics~createOnlineMetric
    */
    metrics.MeanAbsoluteError = function (fin) {
        function metric() {
            this.name = "Mean Absolute Error"
            this.shortName = "MAE"
            this.state = {
                sumErr: 0,
                count: 0,
                error: 0
            }
            // update function
            this.update = function (yTrue, yPred) {
                var err = yTrue - yPred;
                this.state.sumErr += Math.abs(err);
                this.state.count++;
                this.state.error = this.state.sumErr / this.state.count;
                return this.state.error;
            }
        }
        // create new metric instance, and load state from fin in defined
        var errorMetric = new createOnlineMetric(metric);
        if (typeof fin !== 'undefined') errorMetric.load(fin);

        return errorMetric;
    }

    // MEAN SQUARE ERROR (MSE)
    /**
    * Create new (online) mean square error instance.
    * @class
    * @classdesc Online Mean Square Error (MSE) instance.
    * @param {module:fs.FIn} [fin] - Saved state can be loaded via constructor.
    * @extends module:analytics~createOnlineMetric
    */
    metrics.MeanSquareError = function (fin) {
        function metric() {
            this.name = "Mean Square Error"
            this.shortName = "MSE"
            this.state = {
                sumErr: 0,
                count: 0,
                error: 0
            }
            // update function
            this.update = function (yTrue, yPred) {
                var err = yTrue - yPred;
                this.state.sumErr += (err * err);
                this.state.count++;
                this.state.error = this.state.sumErr / this.state.count;
                return this.state.error;
            }
        }
        // create new metric instance, and load state from fin in defined
        var errorMetric = new createOnlineMetric(metric);
        if (typeof fin !== 'undefined') errorMetric.load(fin);

        return errorMetric;
    }

    // ROOT MEAN SQUARE ERROR (RMSE)
    /**
    * Create new (online) root mean square error instance.
    * @class
    * @classdesc Online Root Mean Square Error (RMSE) instance.
    * @param {module:fs.FIn} [fin] - Saved state can be loaded via constructor.
    * @extends module:analytics~createOnlineMetric
    */
    metrics.RootMeanSquareError = function (fin) {
        function metric() {
            this.name = "Root Mean Square Error"
            this.shortName = "RMSE"
            this.state = {
                sumErr: 0,
                count: 0,
                error: 0
            }
            // update function
            this.update = function (yTrue, yPred) {
                var err = yTrue - yPred;
                this.state.sumErr += (err * err);
                this.state.count++;
                this.state.error = Math.sqrt(this.state.sumErr / this.state.count);
                return this.state.error;
            }
        }
        // create new metric instance, and load state from fin in defined
        var errorMetric = new createOnlineMetric(metric);
        if (typeof fin !== 'undefined') errorMetric.load(fin);

        return errorMetric;
    }

    // MEAN ABSOLUTE PERCENTAGE ERROR (MAPE)
    /**
    * Create new (online) mean absolute percentage error instance.
    * @class
    * @classdesc Online Mean Absolute Percentage Error (MAPE) instance.
    * @param {module:fs.FIn} [fin] - Saved state can be loaded via constructor.
    * @extends module:analytics~createOnlineMetric
    */
    metrics.MeanAbsolutePercentageError = function (fin) {
        function metric() {
            this.name = "Mean Absolute Percentage Error"
            this.shortName = "MAPE"
            this.state = {
                sumErr: 0,
                count: 0,
                error: 0
            }
            // update function
            this.update = function (yTrue, yPred) {
                if (yTrue != 0) { // skip if yTrue is 0, otherwise we have devision by zero in the next step.
                    var err = yTrue - yPred;
                    this.state.sumErr += Math.abs(err / yTrue) * 100;
                }
                this.state.count++;
                this.state.error = this.state.sumErr / this.state.count;
                return this.state.error;
            }
        }
        // create new metric instance, and load state from fin in defined
        var errorMetric = new createOnlineMetric(metric);
        if (typeof fin !== 'undefined') errorMetric.load(fin);

        return errorMetric;
    }

    // R SQUARED SCORE (R2)
    /**
    * Create new (online) R Square instance. This statistic measures how successful the fit is in explaining the variation of the data. Best possible score is 1.0, lower values are worse.
    * @class
    * @classdesc Online R Squared (R2) score instance.
    * @param {module:fs.FIn} [fin] - Saved state can be loaded via constructor.
    * @extends module:analytics~createOnlineMetric
    */
    metrics.R2Score = function (fin) {
        function metric() {
            this.name = "R2 Score"
            this.shortName = "R2"
            this.state = {
                sst: 0,
                sse: 0,
                mean: 0,
                count: 0,
                sumTrue: 0,
                sumTrue2: 0,
                error: 0
            }
            // update function
            this.update = function (yTrue, yPred) {
                this.state.count++;
                this.state.sumTrue += yTrue;
                this.state.sumTrue2 += yTrue * yTrue;
                this.state.mean = this.state.sumTrue / this.state.count;
                //calculate R squared score
                this.state.sse += (yTrue - yPred) * (yTrue - yPred);
                this.state.sst = this.state.sumTrue2 - this.state.count * this.state.mean * this.state.mean;
                if (this.state.sst == 0.0) {
                    return (this.state.sse == 0.0) ? 1.0 : 0.0;
                }
                this.state.error = 1 - this.state.sse / this.state.sst;
                return this.state.error;
            }
        }
        // create new metric instance, and load state from fin in defined
        var errorMetric = new createOnlineMetric(metric);
        if (typeof fin !== 'undefined') errorMetric.load(fin);

        return errorMetric;
    }


    //////////////////////////////////////////////////
    //////////// BATCH REGRESSION METRICS ////////////
    //////////////////////////////////////////////////

    // function checks if input parameters are of appropriate type
    function checkBatchParams() {
        for (var i = 0, j = arguments.length; i < j; i++) {
            var argumentType = arguments[i].constructor.name;
            if (argumentType !== "Array" && argumentType !== "Vector") {
                throw new TypeError('input param ' + i + ' must be of type "Array" or "Vector", but is ' + argumentType + ' instead');
            }
        }
    }

    // calculate batch regression metrics
    function calcBatchError(yTrueVec, yPredVec) {
        // check input parameters
        checkBatchParams(yTrueVec, yPredVec);
        // calculate error with metric defined as callback functio
        function calcErr(metric) {
            // iterage over array of input data
            for (var i = 0; i < yTrueVec.length; i++) {
                metric.push(yTrueVec[i], yPredVec[i]);
            }
            // return final error
            return metric.getError()
        }

        // expose metrics which will be used in calcErr() to return error
        this.ME = function () { return calcErr(new metrics.MeanError()) };
        this.MAE = function () { return calcErr(new metrics.MeanAbsoluteError()) };
        this.MSE = function () { return calcErr(new metrics.MeanSquareError()) };
        this.RMSE = function () { return calcErr(new metrics.RootMeanSquareError()) };
        this.MAPE = function () { return calcErr(new metrics.MeanAbsolutePercentageError()) };
        this.R2 = function () { return calcErr(new metrics.R2Score()) };
    };

    /**
    * Mean error (ME) regression loss.
    * @param {(Array<number> | module:la.Vector)} yTrueVec - ground truth values in `yTrueVec`.
    * @param {(Array<number> | module:la.Vector)} yPredVec - estimated values in `yPredVec`.
    * @returns {number} Error value.
    */
    metrics.meanError = function (yTrueVec, yPredVec) {
        return new calcBatchError(yTrueVec, yPredVec).ME()
    }

    /**
    * Mean absolute error (MAE) regression loss.
    * @param {(Array<number> | module:la.Vector)} yTrueVec - ground truth values in `yTrueVec`.
    * @param {(Array<number> | module:la.Vector)} yPredVec - estimated values in `yPredVec`.
    * @returns {number} Error value.
    */
    metrics.meanAbsoluteError = function (yTrueVec, yPredVec) {
        return new calcBatchError(yTrueVec, yPredVec).MAE()
    }

    /**
    * Mean square error (MSE) regression loss.
    * @param {(Array<number> | module:la.Vector)} yTrueVec - ground truth values in `yTrueVec`.
    * @param {(Array<number> | module:la.Vector)} yPredVec - estimated values in `yPredVec`.
    * @returns {number} Error value.
    */
    metrics.meanSquareError = function (yTrueVec, yPredVec) {
        return new calcBatchError(yTrueVec, yPredVec).MSE()
    }

    /**
    * Root mean square (RMSE) error regression loss.
    * @param {(Array<number> | module:la.Vector)} yTrueVec - ground truth values in `yTrueVec`.
    * @param {(Array<number> | module:la.Vector)} yPredVec - estimated values in `yPredVec`.
    * @returns {number} Error value.
    */
    metrics.rootMeanSquareError = function (yTrueVec, yPredVec) {
        return new calcBatchError(yTrueVec, yPredVec).RMSE()
    }

    /**
    * Mean absolute percentage error (MAPE) regression loss.
    * @param {(Array<number> | module:la.Vector)} yTrueVec - ground truth values in `yTrueVec`.
    * @param {(Array<number> | module:la.Vector)} yPredVec - estimated values in `yPredVec.`
    * @returns {number} Error value.
    */
    metrics.meanAbsolutePercentageError = function (yTrueVec, yPredVec) {
        return new calcBatchError(yTrueVec, yPredVec).MAPE()
    }

    /**
    * R^2 (coefficient of determination) regression score.
    * @param {(Array<number> | module:la.Vector)} yTrueVec - ground truth values in `yTrueVec`.
    * @param {(Array<number> | module:la.Vector)} yPredVec - estimated values in `yPredVec`.
    * @returns {number} Error value.
    */
    metrics.r2Score = function (yTrueVec, yPredVec) {
        return new calcBatchError(yTrueVec, yPredVec).R2()
    }

    // Exports metrics namespace
    exports.metrics = metrics;

    /**
    * @typedef {Object} PCAParam
    * An object used for the construction of {@link module:analytics.PCA}.
    * @property {number} [k = null] - Number of eigenvectors to be computed.
    * @property {number} [iter = 100] - Number of iterations.
    */

    /**
    * Principal Components Analysis
    * @class
    * @classdesc Principal Components Analysis
    * @param {module:analytics~PCAParam | module:fs.FIn} [arg] - Construction arguments. There are two ways of constructing:
    * <br>1. Using the {@link module:analytics~PCAParam} object,
    * <br>2. using the file input stream {@link module:fs.FIn}.
    * @example <caption>Using default constructor</caption>
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // construct model
    * var pca = new analytics.PCA();
    *
    * @example <caption>Using custom constructor</caption>
    * // import analytics module
    * var analytics = require('qminer').analytics;
    * // construct model
    * var pca = new analytics.PCA({ k: 5, iter: 50 });
    */
    exports.PCA = function (arg) {
        var iter, k;
        var initParam;
        this.P = undefined;
        this.mu = undefined;
        this.lambda = undefined;
        var count = 1;
        if (arg != undefined && arg.constructor.name == 'FIn') {
            this.P = new la.Matrix();
            this.P.load(arg);
            this.mu = new la.Vector();
            this.mu.load(arg);
            this.lambda = new la.Vector();
            this.lambda.load(arg);
            var params_vec = new la.Vector();
            params_vec.load(arg);
            iter = params_vec[0];
            k = params_vec[1];
        } else if (arg == undefined || typeof arg == 'object') {
            arg = arg == undefined ? {} : arg;
            // Fit params
            var iter = arg.iter == undefined ? 100 : arg.iter;
            var k = arg.k; // can be undefined
        } else {
            throw "PCA.constructor: parameter must be a JSON object or a fs.FIn!";
        }
        initParam = { iter: iter, k: k };
        /**
        * Returns the model.
        * @returns {Object} The object `pcaModel` containing the properties:
        * <br>1. `pcaModel.P` - The eigenvectors. Type {@link module:la.Matrix}.
        * <br>2. `pcaModel.lambda` - The eigenvalues. Type {@link module:la.Vector}.
        * <br>3. `pcaModel.mu` - The mean values. Type {@link module:la.Vector}.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit matrix before getting the model
        * pca.fit(matrix)
        * // get your model using function getModel
        * var model = pca.getModel();
        */
        this.getModel = function () {
            return { P: this.P, mu: this.mu, lambda: this.lambda };
        }

        /**
        * Saves the model.
        * @param {module:fs.FOut} fout - The output stream.
        * @returns {module:fs.FOut} The output stream `fout`.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit matrix
        * pca.fit(matrix);
        * var model = pca.getModel();
        * // save model
        * pca.save(require('qminer').fs.openWrite('pca_test.bin')).close();
        */
        this.save = function (fout) {
            if (!this.P) {
                throw new Error("PCA.save() - model not created yet");
            }

            var params_vec = new la.Vector();
            params_vec.push(iter);
            params_vec.push(k);

            if (fout.constructor.name == 'FOut') {
                this.P.save(fout);
                this.mu.save(fout);
                this.lambda.save(fout);
                params_vec.save(fout);
                return fout;
            } else {
                throw "PCA.save: input must be fs.FOut";
            }
        }


        /**
        * Sets parameters.
        * @param {module:analytics~PCAParam} param - The constructor parameters.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // set 5 eigenvectors and 10 iterations using setParams
        * pca.setParams({iter: 10, k: 5});
        */
        this.setParams = function (param) {
            iter = param.iter == undefined ? iter : param.iter;
            k = param.k == undefined ? k : param.k;
            initParam = { iter: iter, k: k };
            return this;
        }

        /**
        * Gets parameters.
        * @returns {moduel:analytics~PCAParam} The constructor parameters.
        * @example <caption>Using default constructor</caption>
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // check the constructor parameters
        * var paramvalue = pca.getParams();
        *
        * @example <caption>Using custom constructor</caption>
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // set parameters
        * pca.setParams({iter: 10, k: 5});
        * // check the changed parameters
        * var paramvalue = pca.getParams();
        */
        this.getParams = function () {
            return initParam;
        }

        /**
        * Finds the eigenvectors of the variance matrix.
        * @param {module:la.Matrix} A - Matrix whose columns correspond to examples.
        * @example
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit the matrix
        * pca.fit(matrix);
        */
        this.fit = function (A) {
            var rows = A.rows;
            var cols = A.cols;

            k = k == undefined ? rows : k;
            //iter = iter == undefined ? -1 : iter;

            var mu = stat.mean(A, 2);
            // cov(A) = 1/(n-1) A A' - mu mu'

            // center data (same as matlab)
            var cA = A.minus(mu.outer(la.ones(cols)));
            var C = cA.multiply(cA.transpose()).multiply(1 / (cols - 1));
            // alternative computation:
            //var C = (A.multiply(A.transpose()).multiply(1 / (cols - 1))).minus(mu.outer(mu));
            var res = la.svd(C, k, { iter: iter });

            this.P = res.U;
            this.lambda = res.s;
            this.mu = mu;

            return this;
        }

        /**
        * Projects the example(s) and expresses them as coefficients in the eigenvector basis `this.P`.
        * Recovering the data in the original space: `(this.P).multiply(p)`, where `p`'s rows are the coefficients
        * in the eigenvector basis.
        * @param {(module:la.Vector | module:la.Matrix)} x - Test vector or matrix with column examples.
        * @returns {(module:la.Vector | module:la.Matrix)} Returns projected vector or matrix.
        * @example <caption>Transforming the matrix</caption>
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit the matrix
        * pca.fit(matrix);
        * var model = pca.getModel();
        * // transform matrix
        * var transform = pca.transform(matrix);
        *
        * @example <caption>Transforming the vector</caption>
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create vector you wish to transform
        * var vector = new la.Vector([0, -1]);
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit the matrix
        * pca.fit(matrix);
        * var model = pca.getModel();
        * // transform vector
        * var transform = pca.transform(vector);
        */
        this.transform = function (x) {
            if (x.constructor.name == 'Matrix') {
                // P * (x - mu*ones(1, size(x,2)))
                return this.P.multiplyT(x.minus(this.mu.outer(la.ones(x.cols))));

            } else if (x.constructor.name == 'Vector') {
                // P * (x - mu)
                return this.P.multiplyT(x.minus(this.mu));
            }
        }

        /**
        * Reconstructs the vector in the original space, reverses centering.
        * @param {(module:la.Vector | module:la.Matrix)} x - Test vector or matrix with column examples, in the PCA space.
        * @returns {(module:la.Vector | module:la.Matrix)} Returns the reconstruction.
        * @example <caption>Inverse transform of matrix</caption>
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit the matrix
        * pca.fit(matrix);
        * var model = pca.getModel();
        * // use inverseTransform on matrix
        * var invTransform = pca.inverseTransform(matrix);
        *
        * @example <caption>Inverse transform of vector</caption>
        * // import analytics module
        * var analytics = require('qminer').analytics;
        * // construct model
        * var pca = new analytics.PCA();
        * // create vector
        * var vector = new la.Vector([0, -1]);
        * // create matrix
        * var matrix = new la.Matrix([[0, 1], [-1, 0]]);
        * // fit the matrix
        * pca.fit(matrix);
        * var model = pca.getModel();
        * // use inverseTransform on vector
        * var invTransform = pca.inverseTransform(vector);
        */
        this.inverseTransform = function (x) {
            if (x.constructor.name == 'Matrix') {
                // P x + mu*ones(1, size(x,2)
                return (this.P.multiply(x)).plus(this.mu.outer(la.ones(x.cols)));
            } else if (x.constructor.name == 'Vector') {
                // P x + mu
                return (this.P.multiply(x)).plus(this.mu);
            }
        }
    }



    /**
     * @typedef {Object} KMeansExplain
     * The examplanation returned by {@link module:analytics.KMeans#explain}.
     * @property {number} medoidID - The ID of the nearest medoids.
     * @property {module:la.IntVector} featureIDs - The IDs of features, sorted by contribution.
     * @property {module:la.Vector} featureContributions - Weights of each feature contribution (sum to 1.0).
     */

    /**
     * Returns the IDs of the nearest medoid for each example.
     * @param {(module:la.Matrix | module:la.SparseMatrix)} X - Matrix whose columns correspond to examples.
     * @returns {Array.<module:analytics~KMeansExplain>} Array containing the KMeans explanantions.
     * @example
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * // import linear algebra module
     * var la = require('qminer').la;
     * // create a new KMeans object
     * var KMeans = new analytics.KMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X using the column IDs [0,1,2]
     * KMeans.fit(X, [1234,1142,2355]);
     * // create the matrix of the prediction vectors
     * var test = new la.Matrix([[2, -1, 1], [1, 0, -3]]);
     * // predict/explain - return the closest medoids
     * var explanation = KMeans.explain(test);
     */
    exports.KMeans.prototype.explain = function (X) {

        /**
         * Returns the weights and feature IDs that contributed to the distance between two vectors.
         * @param {(module:la.Vector | module:la.SparseVector)} x - Vector.
         * @param {(module:la.Vector | module:la.SparseVector)} y - Vector.
         * @returns {Object} Feature IDs and feature contributions.
         **/
        function featureContrib(x, y) {
            var fx = x.constructor.name == 'SparseVector' ? x.full() : x;
            var fy = y.constructor.name == 'SparseVector' ? y.full() : y;
            var diff = fx.minus(fy);
            var nor2 = Math.pow(diff.norm(), 2);
            for (var i = 0; i < diff.length; i++) {
                diff[i] = Math.pow(diff[i], 2) / nor2;
            }
            var sorted = diff.sortPerm(false); // sort descending
            return { featureIDs: sorted.perm, featureContributions: sorted.vec };
        }

        if (this.medoids == undefined) {
            return { medoidIDs: null };
        }
        var params = this.getParams();
        var norC2 = la.square(this.centroids.colNorms());
        var ones_n = la.ones(X.cols).multiply(0.5);
        var ones_k = la.ones(params.k).multiply(0.5);
        var norX2 = la.square(X.colNorms());
        var D = this.centroids.multiplyT(X).minus(norC2.outer(ones_n)).minus(ones_k.outer(norX2));
        var centroids = la.findMaxIdx(D);
        var medoidIDs = new la.IntVector(centroids);
        assert(this.medoids.length == params.k);
        var result = [];
        for (var i = 0; i < centroids.length; i++) {
            var explanation = featureContrib(X.getCol(i), this.centroids.getCol(centroids[i]));
            result[i] = {
                medoidID: this.medoids[centroids[i]],
                featureIDs: explanation.featureIDs,
                featureContributions: explanation.featureContributions
            }
        }
        return result;
    }

    /**
    * Returns the model.
    * @returns {Object} The `KMeansModel` object containing the properites:
    * <br> 1. `KMeansModel.C` - The {@link module:la.Matrix} or {@link module:la.SparseMatrix} containing the centroids,
    * <br> 2. `KMeansModel.medoids` - The {@link module:la.IntVector} of cluster medoids of the training data,
    * <br> 3. `KMeansModel.idxv` - The {@link module:la.IntVector} of cluster IDs of the training data.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create the KMeans object
    * var KMeans = new analytics.KMeans({ iter: 1000 });
    * // create a matrix to be fitted
    * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
    * // create the model
    * KMeans.fit(X);
    * // get the model
    * var model = KMeans.getModel();
    */
    exports.KMeans.prototype.getModel = function () { return { C: this.centroids, medoids: this.medoids, idxv: this.idxv }; }

    /**
     * @typedef {Object} DpMeansExplain
     * The examplanation returned by {@link module:analytics.KMeans#explain}.
     * @property {number} medoidID - The ID of the nearest medoids.
     * @property {module:la.IntVector} featureIDs - The IDs of features, sorted by contribution.
     * @property {module:la.Vector} featureContributions - Weights of each feature contribution (sum to 1.0).
     */

    /**
     * Returns the IDs of the nearest medoid for each example.
     * @param {(module:la.Matrix | module:la.SparseMatrix)} X - Matrix whose columns correspond to examples.
     * @returns {Array.<module:analytics~DpMeansExplain>} Array containing the DpMeans explanantions.
     * @example
     * // import analytics module
     * var analytics = require('qminer').analytics;
     * // import linear algebra module
     * var la = require('qminer').la;
     * // create a new DpMeans object
     * var DpMeans = new analytics.DpMeans({ iter: 1000, k: 3 });
     * // create a matrix to be fitted
     * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
     * // create the model with the matrix X using the column IDs [0,1,2]
     * DpMeans.fit(X, [1234,1142,2355]);
     * // create the matrix of the prediction vectors
     * var test = new la.Matrix([[2, -1, 1], [1, 0, -3]]);
     * // predict/explain - return the closest medoids
     * var explanation = DpMeans.explain(test);
     */
    exports.DpMeans.prototype.explain = function (X) {

        /**
         * Returns the weights and feature IDs that contributed to the distance between two vectors.
         * @param {(module:la.Vector | module:la.SparseVector)} x - Vector.
         * @param {(module:la.Vector | module:la.SparseVector)} y - Vector.
         * @returns {Object} Feature IDs and feature contributions.
         **/
        function featureContrib(x, y) {
            var fx = x.constructor.name == 'SparseVector' ? x.full() : x;
            var fy = y.constructor.name == 'SparseVector' ? y.full() : y;
            var diff = fx.minus(fy);
            var nor2 = Math.pow(diff.norm(), 2);
            for (var i = 0; i < diff.length; i++) {
                diff[i] = Math.pow(diff[i], 2) / nor2;
            }
            var sorted = diff.sortPerm(false); // sort descending
            return { featureIDs: sorted.perm, featureContributions: sorted.vec };
        }

        if (this.medoids == undefined) {
            return { medoidIDs: null };
        }
        var params = this.getParams();
        var norC2 = la.square(this.centroids.colNorms());
        var ones_n = la.ones(X.cols).multiply(0.5);
        var ones_k = la.ones(this.centroids.cols).multiply(0.5);
        var norX2 = la.square(X.colNorms());
        var D = this.centroids.multiplyT(X).minus(norC2.outer(ones_n)).minus(ones_k.outer(norX2));
        var centroids = la.findMaxIdx(D);
        var medoidIDs = new la.IntVector(centroids);
        var result = [];
        for (var i = 0; i < centroids.length; i++) {
            var explanation = featureContrib(X.getCol(i), this.centroids.getCol(centroids[i]));
            result[i] = {
                medoidID: this.medoids[centroids[i]],
                featureIDs: explanation.featureIDs,
                featureContributions: explanation.featureContributions
            }
        }
        return result;
    }

    /**
    * Returns the model.
    * @returns {Object} The `DpMeansModel` object containing the properites:
    * <br> 1. `DpMeansModel.C` - The {@link module:la.Matrix} or {@link module:la.SparseMatrix} containing the centroids,
    * <br> 2. `DpMeansModel.medoids` - The {@link module:la.IntVector} of cluster medoids of the training data,
    * <br> 3. `DpMeansModel.idxv` - The {@link module:la.IntVector} of cluster IDs of the training data.
    * @example
    * // import modules
    * var analytics = require('qminer').analytics;
    * var la = require('qminer').la;
    * // create the KMeans object
    * var dpmeans = new analytics.DpMeans({ iter: 1000 });
    * // create a matrix to be fitted
    * var X = new la.Matrix([[1, -2, -1], [1, 1, -3]]);
    * // create the model
    * dpmeans.fit(X);
    * // get the model
    * var model = dpmeans.getModel();
    */
    exports.DpMeans.prototype.getModel = function () { return { C: this.centroids, medoids: this.medoids, idxv: this.idxv }; }

    function defarg(arg, defaultval) {
        return arg == undefined ? defaultval : arg;
    }

    /**
    * @typedef {Object} ActiveLearnerParam
    * An object used for the construction of {@link module:analytics.ActiveLearner}.
    * @property {Object} [learner] - Learner parameters
    * @property {boolean} [learner.disableAsserts=false] - Disable input asserting
    * @property {module:analytics~SVMParam} [SVC] - Support vector classifier parameters.
    */

    /**
    * @classdesc Active learner. Uses a SVM model and implements an uncertainty measure (distance to the margin)
    * to select which unlabelled example should be labelled next.
    * @class
    * @param {(module:analytics~ActiveLearnerParam | module:fs~FIn | string)} [arg] - Construction arguments (JSON) or when loading: an input stream (fs.FIn) or a file name (string).
    * @example
    * // load libs
    * var qm = require('qminer');
    * var la = qm.la;
    * // create model
    * var al = new qm.analytics.ActiveLearner();
    *
    * // set data (4 labelled and 2 unlabelled examples)
    * var X = new la.Matrix([
    *     [-2, 1],
    *     [-2, 0],
    *     [-2, -1],
    *     [0, 1],
    *     [-0.9, 0],
    *     [0, -1]
    * ]).transpose(); // column examples
    * al.setX(X);
    *
    * var y = [-1, 0, -1, 1, 0, 1];
    * al.sety(y);
    * // get the array containing 1 index of the unlabelled example
    * // that is the closest to the hyperplane
    * var qidx = al.getQueryIdx(1);
    * console.log(qidx); // 4
    */
    class ActiveLearner {
        constructor(opts) {
            opts = opts || {};

            if (opts instanceof qm.fs.FIn || typeof opts == "string") {
                this.load(opts);
            } else {
                // SETTINGS
                let settings = this._getDefaultSettings();
                override(settings, opts.settings || {});
                this._settings = settings;

                // STATE
                this._X = opts.X || null;
                this._y = opts.y || new Map();
                this._SVC = new exports.SVC(this._settings.SVC);
            }
        }

        /**
        * Returns default settings
        */
        _getDefaultSettings() {
            return {
                learner: {
                    disableAsserts: false
                },
                SVC: {
                    algorithm: "LIBSVM",
                    c: 1.0,
                    j: 1.0
                }
            };
        }

        /**
        * Asserts if the object is a la matrix
        */
        _assertMatrix(X) {
            if (this._settings.learner.disableAsserts) { return; }
            assert(X instanceof la.Matrix || X instanceof la.SparseMatrix, "X should be a dense or a sparse matrix (qm.la object)");
        }

        /**
        * Asserts if a label and the index are valid, given number of examples `cols`
        */
        _assertLabel(cols, idx, label) {
            if (this._settings.learner.disableAsserts) { return; }
            if (cols == undefined) { throw new Error("Columns not defined"); }
            if (!isFinite(idx) || (idx >= cols) || (idx < 0)) { throw new Error("Label index out of range"); }
            if ((label != -1) && (label != 1)) { throw new Error("Label should be either -1 or 1"); }
        }

        /**
        * Asserts if a Map with labels is valid
        */
        _assertLabelSet(cols, y) {
            if (this._settings.learner.disableAsserts) { return; }
            assert(y instanceof Map, "y should be a map from data instance indices to +1 or -1");
            // assert y indices and values
            for (let pair of y.entries()) {
                this._assertLabel(cols, pair[0], pair[1]);
            }
        }

        /**
        * Transforms an Array of labels to a Map from indices to labels
        */
        _getLabelMapFromArr(_y) {
            assert(_y instanceof Array);
            let y = new Map();
            for (let i = 0; i < _y.length; i++) {
                let lab = _y[i];
                if (this._settings.learner.disableAsserts) {
                    assert(lab === -1 || lab === 1 || lab === 0, "Label must be ither -1, 0 or 1");
                }
                if (lab !== 0) {
                    y.set(i, lab);
                }
            }
            return y;
        }

        /**
        * Returns an array of indices of labelled examples
        */
        _getLabIdxArr(y) {
            return Array.from(y.keys());
        }

        /**
        * Returns an array of label values corresponding to the labelled examples
        */
        _getLabArr(y) {
            return Array.from(y.values());
        }

        /**
        * Returns an array of indices of unlabelled examples
        */
        _getUnlabIdxArr(cols, y) {
            let unlabIdxArr = [];
            for (let idx = 0; idx < cols; idx++) {
                if (!y.has(idx)) {
                    unlabIdxArr.push(idx);
                }
            }
            return unlabIdxArr;
        }

        /**
        * Retrains the SVC model
        * @param {(module:la.Matrix | module:la.SparseMatrix)} X - data matrix (column examples)
        * @param {Map} y - a Map from indices to 1 or -1
        * @param {module:analytics.SVC} SVC - a SVC model
        */
        _retrain(X, y, SVC) {
            // asert y indices and values
            this._assertMatrix(X);
            let cols = X.cols;
            this._assertLabelSet(cols, y);
            if (y.size == 0) { throw new Error("No labelled information in y"); }

            // get all labelled examples and fit SVM
            let labIdxArr = this._getLabIdxArr(y);
            let trainIdx = new la.IntVector(labIdxArr);
            let Xsub = X.getColSubmatrix(trainIdx);
            let yArr = this._getLabArr(y);
            let yVec = new la.Vector(yArr);
            SVC.fit(Xsub, yVec);
        }

        /**
        * Retrains the SVC model
        */
        retrain() {
            this._retrain(this._X, this._y, this._SVC);
        }

        /**
        * Return an array of indices where the model has the highest uncertainty (1 element by default)
        * @param {(module:la.Matrix | module:la.SparseMatrix)} X - data matrix (column examples)
        * @param {Map} y - a Map from indices to 1 or -1
        * @param {module:analytics.SVC} SVC - a SVC model
        * @param {number} [num=1] - the length of the array that is returned (top `num` indices where uncertainty is maximal)
        * @returns {Array<number>} - array of indices of unlabelled examples
        */
        _getQueryIdx(X, y, SVC, num) {
            num = (isFinite(num) && num > 0 && Number.isInteger(num)) ? num : 1;
            // use the classifier on unlabelled examples and return
            // get unlabelled indices
            let unlabIdxArr = this._getUnlabIdxArr(X.cols, y);
            if (unlabIdxArr.length == 0) { return []; } // exhausted
            let unlabIdxVec = new la.IntVector(unlabIdxArr);
            let Xsub = X.getColSubmatrix(unlabIdxVec);
            if (SVC.weights.length == 0) {
                this._retrain(X, y, SVC);
            }
            // get examples with largest uncertainty
            let uncertaintyArr = SVC.decisionFunction(Xsub).toArray().map((x) =>Math.abs(x));
            let u = new la.Vector(uncertaintyArr);
            let su = u.sortPerm(); // sorted in ascending order
            num = Math.min(num, u.length);
            // take `num` unlabelled indices where we are most uncertain
            let subVec = unlabIdxVec.subVec(su.perm.trunc(num));
            return subVec.toArray();
        }

        /**
        * Returns an array of 0 or more example indices sorted by uncertainty (first element is the closest to the hyperplane)
        * @param {number} [num=1] - maximal length of the array
        * @returns {Array<number>} array of unlabelled example indices
        */
        getQueryIdx(num) {
            return this._getQueryIdx(this._X, this._y, this._SVC, num)
        }

        /**
        * Sets the label
        * @param {number} idx - instance index
        * @param {number} label - should be either 1 or -1
        */
        setLabel(idx, label) {
            let cols = this._X.cols;
            this._assertLabel(cols, idx, label);
            this._y.set(idx, label);
        }

        /**
        * Sets the data matrix (column examples)
        * @param {(module:la.Matrix | module:la.SparseMatrix)} X - data matrix (column examples)
        */
        setX(X) {
            this._assertMatrix(X);
            this._X = X
        }

        /**
        * Sets the labels
        * @param {(Array<number> | module.la.Vector | module.la.IntVector | Map)} _y - array (like) object that encodes labels
        *                                                                        (-1, 0 or 1) or a Map from indices to 1 or -1
        */
        sety(_y) {
            let y = _y;
            this._assertMatrix(this._X);
            let cols = this._X.cols;
            if (_y instanceof Array) { y = this._getLabelMapFromArr(_y); }
            if (_y.toArray != undefined) { y = this._getLabelMapFromArr(_y.toArray()); }
            this._assertLabelSet(cols, y);
            this._y = y;
        }

        /**
        * Returns the SVC model
        * @returns {module:analytics.SVC} SVC model
        */
        getSVC() { return this._SVC; }

        /**
        * Returns the data matrix (column examples)
        * @returns {(module:la.Matrix | module:la.SparseMatrix)} data matrix (column examples)
        */
        getX() { return this._X; }

        /**
        * Returns the Map from example indices to labels (-1 or 1)
        * @returns {Map} label map
        */
        gety() { return this._y; }

        /**
        * Loads instance matrix, labels and the model from the input stream
        * @param {(string | module:fs.FIn)} input - a file name or an input stream
        */
        load(input) {
            if (input instanceof qm.fs.FIn) {
                this._settings = input.readJson();
                let matrixType = input.readJson().matrixType;
                if (matrixType == "null") {
                    this._X = null;
                } else if (matrixType == "full") {
                    this._X = new la.Matrix();
                    this._X.load(input);
                } else if (matrixType == "sparse") {
                    this._X = new la.SparseMatrix();
                    this._X.load(input);
                } else {
                    throw new Error("Cannot load matrix, the type is not supported");
                }
                let y = input.readJson();
                this._y = new Map(y);
                this._SVC = new exports.SVC(input);
                return input;
            } else {
                let fin = qm.fs.openRead(input);
                this.load(fin).close();
            }
        }

        /**
        * Saves the instance matrix, labels and the model to the input stream
        * @param {(string | module:fs.FOut)} output - a file name or an output stream
        */
        save(output) {
            let X = this._X;
            let y = this._y;
            let SVC = this._SVC;
            if (output instanceof qm.fs.FOut) {
                output.writeJson(this._settings);
                if (X == undefined) {
                    output.writeJson({ matrixType: "null" });
                } else if (X instanceof la.Matrix) {
                    output.writeJson({ matrixType: "full" });
                    X.save(output);
                } else if (X instanceof la.SparseMatrix) {
                    output.writeJson({ matrixType: "sparse" });
                    X.save(output);
                } else {
                    throw new Error("Cannot save matrix, the type is not supported.");
                }
                output.writeJson(Array.from(this._y));
                SVC.save(output);
                return output;
            } else {
                let fout = qm.fs.openWrite(output);
                this.save(fout).close();
            }
        }
    }

    exports.ActiveLearner = ActiveLearner;