siafun
Version:
A collection of structure induction algorithms
141 lines (140 loc) • 4.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const clusterfck = require("clusterfck");
const arrayutils_1 = require("arrayutils");
exports.QUANT_FUNCS = {
IDENTITY: identity,
CONSTANT: getConstant,
ROUND: getRound,
ORDER: getOrder,
SUMMARIZE: getSummarize,
SORTED_SUMMARIZE: getSortedSummarize,
TRANSP_SORTED_SUMMARIZE: getTransposedSortedSummarize,
ABOVE_MEAN: getAboveMean,
ABOVE_STD: getAboveStd,
DISCRETIZE: getDiscretize,
CLUSTER: getCluster,
SCALE: scale,
NORMALIZE: normalize,
INTERVALS: toIntervals
};
function identity() {
return toArrayMap(x => x);
}
/** maps all values of an array to the given constant */
function getConstant(value) {
return toArrayMap(() => value);
}
/** returns a function that rounds all numbers in an array to the given precision */
function getRound(precision = 2) {
return toArrayMap(_.curryRight(_.round)(precision));
}
/** returns a function that maps all numbers in an array onto their index */
function getOrder() {
return (values) => values.map((v, i) => i);
}
/** returns a function that maps all arrays in an array onto the outDims highest values */
function getSummarize(outDims) {
return toMatrixMap(_.curryRight(arrayutils_1.indicesOfNMax)(outDims));
}
/** returns a function that summarizes and sorts the arrays of an array */
function getSortedSummarize(outDims) {
return _.flow(getSummarize(outDims), sort);
}
/** returns a function that maps all arrays onto the values above their average */
function getAboveMean() {
return toMatrixMap((values) => {
const mean = _.mean(values);
return values.map((v, i) => v > mean ? i : -1).filter(i => i > -1);
});
}
/** returns a function that maps all arrays onto the values above their average */
function getAboveStd() {
return toMatrixMap((values) => {
const mean = _.mean(values);
const st = std(values, mean);
return values.map((v, i) => v > mean + st ? i : -1).filter(i => i > -1);
});
}
//TODO IS NOT REALLY SET CLASS YET, NEED TO INVERT POTENTIALLY!!
function getTransposedSortedSummarize(outDims) {
return _.flow(getSummarize(outDims), sort, toMatrixMap(toIntervals));
}
/** returns a function that maps all numbers in an array onto a discrete segment [0,...,numValues-1] */
function getDiscretize(numValues) {
return _.flow(scale, _.curryRight(multiply)(numValues), toArrayMap(_.round));
}
function getCluster(numClusters) {
return _.curryRight(cluster)(numClusters);
}
/** scales all values in an array to [0,1] */
function scale(values) {
var max = _.max(values);
var min = _.min(values);
return values.map(v => (v - min) / (max - min));
}
/** normalizes all values in an array */
function normalize(values) {
var mean = _.mean(values);
var std = std(values, mean);
return values.map(v => (v - mean) / std);
}
/** maps all values onto the interval by which they are reached */
function toIntervals(values) {
return values.map((v, i) => i > 0 ? v - values[i - 1] : 0);
}
/** clusters all values and maps them onto their cluster index */
function cluster(values, clusterCount) {
var kmeans = new clusterfck.Kmeans(null);
var clusters = kmeans.cluster(values, clusterCount, null, null, null);
return values.map(v => kmeans.classify(v, null));
}
function multiply(values, multiplier) {
return values.map(v => v * multiplier);
}
function sort(values) {
return values.map(v => _.sortBy(v));
}
function std(values, mean) {
return Math.sqrt(_.sum(values.map(v => Math.pow((v - mean), 2))) / values.length);
}
function toArrayMap(func) {
return (values) => values.map(v => func(v));
}
function toMatrixMap(func) {
return (values) => values.map(v => func(v));
}
class Quantizer {
constructor(dimFuncs) {
this.dimFuncs = dimFuncs;
}
getQuantizedPoints(points) {
if (this.dimFuncs.length > 0) {
points = this.dimFuncs.map((f, i) => f(points.map(p => p[i])));
points = _.zip(...points);
}
return points.map(p => _.flatten(p));
}
/**
* TODO WHERE TO PUT?
* returns a map with a normalized vector for each given dymo. if reduce is true, multidimensional ones are reduced
*/
normalize(vectors) {
//normalize the space
var means = [];
var vars = [];
for (var i = 0; i < vectors[0].length; i++) {
var currentDim = [];
for (var j = 0; j < vectors.length; j++) {
if (!isNaN(vectors[j][i])) {
currentDim.push(vectors[j][i]);
}
}
means[i] = _.mean(currentDim);
vars[i] = std(currentDim, means[i]);
}
return vectors.map(v => v.map((e, i) => (e - means[i]) / vars[i]));
}
}
exports.Quantizer = Quantizer;