diff --git a/ext/math.js b/ext/math.js new file mode 100644 index 0000000..abe67a2 --- /dev/null +++ b/ext/math.js @@ -0,0 +1,254 @@ +/** +* Simple Javascript eXtension - 1.0 +* (c) 2011 - 2015 Steve L. Nyemba, steve@the-phi.com +* License GPL version 3.0 +* +* dependencies: +* utils.js implementation of design patterns and utilities +* +* This file contains an enhancement of utilities integrated into the jx.math.* built-in package of javascript +* Because we implement math and numerical functions it is to be understood that most of the functions will have common preconditions +* i.e lxi.constructor == Array && isNumber(lxi) unless specified otherwise + +* jx.math.max +* jx.math.min +* jx.math.sum +* jx.math.prod +* jx.math.freq +* jx.math.avg +* jx.math.mean computes the mean/average of a list of observations (arthmetic mean included too) +* jx.math.sd computes the standard deviation of a list of observations +* jx.math.var computes the variance of a list of observations +* jx.math.diff computes the absolute difference of values in an array +* jx.math.fibonacci comptutes the fibonacci value of a given number +* jx.math.factorial computes the factorial of a given number +*/ +if(!jx){ + var jx = {} ; + +} +jx.math = {} +jx.math.sqrt = Math.sqrt; +jx.math.PHI = (1+jx.math.sqrt(5))/2 ;//1.61803399 ; + +/** +* @param lxi list of observatins xi +*/ + +jx.math.max = function(lxi){ + sortNumber= function(a,b) { + return a - b; + } + index = lxi.length -1 ; + max = jx.utils.cast(lxi,Number).sort(sortNumber)[index] ; // perhaps need to cast + return max ; +} +/** +* finds the minimum of a list of observation lxi (vector of values) +* @param lxi list/vector of values/observations +*/ +jx.math.min = function(lxi){ + sortNumber = function(a,b){ + return a- b; + } + min = jx.utils.cast(lxi,Number).sort(sortNumber)[0] ; + return min ; +} +/** +* @pre : values.constructor == Array +* @param lxi list of observed values to be summed +*/ +jx.math.sum = function(lxi){ + return eval(lxi.join('+')); +} ; +/** +* This function will compute the frequency of a vector i.e providing relative values +*/ +jx.math.freq = function(lxi){ + var N = jx.math.sum(lxi) ; + return jx.utils.patterns.visitor(lxi,function(xi){ + return xi/N ; + }); +} +/** + * This function will perform the product of a vector + * @pre lxi.constructor == Array && isNumber(lxi) + */ +jx.math.prod = function(lxi){ + return eval(lxi.join('*')) ; +} +/** +* @pre : lni != null && lxi.length == lni.length +* @param lxi list of observed values +* @param lni list of the number of times observations of index i have been made +*/ +jx.math.avg = function(lxi,lni){ + N = lxi.length ; + if(lni == null){ + return jx.math.sum(lxi)/N ; + }else{ + values = [] + for(var i=0; i < lxi.length; i++){ + values[i] = Number(lxi[i])*Number(lni[i]) ; + } + return Number(jx.math.sum(values)/N) ; + } +}; + +jx.math.mean = jx.math.avg ; +jx.math.pow = Math.pow +jx.math.sd = function(lxi,lni){ + N = lxi.length ; + mean = jx.math.mean(lxi,lni) ; + + sqr = [] ; + for(var i=0; i < lxi.length ;i++){ + console.log(lxi[i]) + sqr[i] = jx.math.pow((Number(lxi[i])-mean),2 ) ; + } + + total = jx.math.sum(sqr); + + return jx.math.sqrt(total/(N-1)) ; +} ; + +/** +* Computes the factorial of a given value +*/ +jx.math.factorial = function(value){ + r =value; + for(var i =value-1; i > 0; i--){ + r *= i ; + } + + return r; +} ; + +/** +* Computes the fibonacci value of a given number using the golden ratio +*/ +jx.math.fibonacci = function(value){ + r = (jx.math.pow(jx.math.PHI,value)/jx.math.sqrt(5)) + 0.5 ; + return jx.math.floor(r) ; +} ; + +/** +* computes the absolute difference of values in a list of observations +*/ +jx.math.diff = function(lxi){ + var r = [] ; + var x,y; + for(var i=0; i < lxi.length-1; i++){ + x = lxi[i] ; + y = lxi[i+1] ; + r.push(y-x) + } + return r ; +}; + +/** + * This section implements a few handlers based on sets + */ +jx.math.sets = {} ; +/** + * This function will perform a unique operation of values/objects + * @param list list/vector of values or objects + * @param equals operator to be used, only provide this for complex objects + */ +jx.math.sets.unique = jx.utils.unique ; +/** + * This function will perform the union of 2 sets (objects, or values) + * @param list1 list/vector of values or objects + * @param list2 list/vector of values or objects + * @param equals operator to be used to evaluate equality (use this for complex objects) + */ +jx.math.sets.union = function(list1,list2,equals){ + runion = [] ; + runion = list1.concat(list2) ; + runion = jx.math.sets.unique(runion,equals) + return runion; +} + +/** +* This function will normalize values within a vector +* By definition normalization is (x - u) / sd (assuming population parameters are known) +*/ +jx.math.normalize = function(lvalues){ + mean = jx.math.mean(lvalues) ; + sd = jx.math.sd(lvalues) ; + return jx.utils.patterns.visitor(lvalues,function(x){ + return ((x - mean) / sd) + }) +} + +/** + * This function will scale a feature vector over it's range + */ +jx.math.scale = function(lvalues,percent){ + max = jx.math.max(lvalues) ; + min = jx.math.min(lvalues) ; + return jx.utils.patterns.visitor(lvalues,function(x){ + var value = (x - min ) / max ; + if(percent == true){ + return (100*value).toFixed(2) + }else{ + return value ; + } + }) +} +/** +* This is a lightweight map reduce infrastructure +*/ +jx.mr = {} ; +/** +* This function will perform a map on a given id in rec, then will call emit with the +*/ +jx.mr.map = null +/** +* @param keys +* @param values array of values that were mapped +*/ +jx.mr.reduce = null; +jx.mr.mapreduce = function(data,fn_map,fn_reduce){ + if (fn_map == null){ + throw new "Map function is not defined" + } + map = {} ; + emit = function(id,values){ + if(map[id] == null){ + map[id] = [] + } + map[id].push(values); + } + if(data.constructor != Array){ + for (id in data){ + //rec = data[id] ; + rec = {} + rec['__id'] = id; + rec['data'] = data[id] ; + fn_map(rec,emit) + + } + }else{ + for (var i=0; i < data.length; i++){ + rec = data[i]; + fn_map(rec,emit); + //if(i == 2)break; + } + } + if(fn_reduce != null){ + keys = jx.utils.keys(map) ; + m = {} + for(var i=0; i < keys.length; i++){ + id = keys[i] ; + values = map[id] ; + value = fn_reduce(id,values) ; + id = keys[i] ; + m[id] = value; + + } + map = m + + } + return map ; +} diff --git a/ext/ml.js b/ext/ml.js new file mode 100644 index 0000000..b297be9 --- /dev/null +++ b/ext/ml.js @@ -0,0 +1,61 @@ +/** +* Simple Javascript eXtension - 1.0, Machine Leanring Module +* (c) 2011 - 2015 Steve L. Nyemba, steve@the-phi.com +* License GPL version 3.0 +* +* dependencies: +* jx.utils collection of utilities and design patterns used +* jx.math various math & statistical functions +* This file implements a few reusable machine learning models/techniques +* +* jx.ml.mapreduce Performs a standard/basic mapreduce (single thread for now) +* jx.ml.regression Will perform linear & logistic regressions +*/ +* +if(!jx){ + var jx = {} ; +} +jx.ml = {} +/** +* The function performs map/reduce and at the very least map i.e the reduce function is optional +*/ +jx.ml.mapreduce = function(data,fn_map,fn_reduce){ + // + // insure that the mapping function has been provided + // + var __map = {} + var emit = function(id,mvalue){ + if(__map[id] == null){ + __map[id] = [] + } + __map[id].push(mvalue) ; + }//-- end of the emitter + if(data.constructor != Array){ + jx.utils.patterns.visitor(data,function(id){ + fn_map(data[id],emit) ; + }); + }else{ + jx.utils.patterns.visitor(data,function(i){ + fn_map(data[i],emit) ; + }); + } + + if(fn_reduce != null){ + // + // We will be performing a reduce operation at this point + + var ids = jx.utils.keys(__map) ; + jx.utils.patterns.visitor(ids,function(id){ + return __map[id] = fn_reduce(id,__map[id]) ; + }); + } + + return __map ; + +}//-- + +/** + * The modules developed below will perform linear regression and logistic regression + */ +jx.ml.regression = {} + diff --git a/utils.js b/utils.js index d5dd657..d92ea73 100644 --- a/utils.js +++ b/utils.js @@ -1,6 +1,6 @@ /** * Simple Javascript eXtension - 1.0 -* (c) 2014 - 2015 Steve L. Nyemba, steve@the-phi.com +* (c) 2011 - 2015 Steve L. Nyemba, steve@the-phi.com * License GPL version 3.0 * * Implementation of miscellaneous utilities commonly used, These functions are reusable and simple: