12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310 |
- /**
- * CertainTrust SDK
- *
- * Implements the computational trust model "CertainTrust"
- * in JavaScript.
- * See <http://www.tk.informatik.tu-darmstadt.de/de/research/smart-security-and-trust/> for further details.
- *
- *
- * Telecooperation Department, Technische Universität Darmstadt
- * <http://www.tk.informatik.tu-darmstadt.de/>
- *
- * Prof. Dr. Max Mühlhäuser <max@informatik.tu-darmstadt.de>
- * Florian Volk <florian.volk@cased.de>
- *
- *
- * @author Maria Pelevina
- * @author David Kalnischkies
- * @version 1.1
- */
-
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
- /**
- * Available Constructors:
- * - CertainTrust(t, c, f, n)
- * - CertainTrust(r, s, n)
- * - CertainTrust(n)
- * optionally arguments can be preceded by name, e.g. CertainTrust(name, r, s, n)
- *
- * t - average rating value, [0; 1], from very negative to very positive
- * c - certainty value, [0; 1] from low certainty (no evidence) to the maximal maximal certainty.
- * f - initial trust value
- * w - weight
- * r - number of positive evidence
- * s - number of negative evidence
- * n - maximal number of expected evidence
- */
- var CertainTrust = function() {
- this.weight = 2;
- this.observers = [];
- var offset = 0;
- this.name = "";
- if (this._isString(arguments[0])) {
- this.name = arguments[0];
- offset = 1;
- }
- if (arguments.length == 4 + offset || arguments.length == 5 + offset) {
- // CertainTrust(t, c, f, n, doc)
- // doc is a 'private' parameter
- this.t = arguments[0 + offset];
- this.c = arguments[1 + offset];
- this.f = arguments[2 + offset];
- this.n = arguments[3 + offset];
- this.doc = (arguments.length == 4 + offset) ? 0 : arguments[4 + offset];
- this.r = 0;
- this.s = 0;
- if (this.n <= 0)
- throw "N should be greater than 0. Entered n = " + this.n + "\n";
- if (this.f < 0 && this.f > 1)
- throw "f should lie within [0;1]. Entered f = " + this.f + "\n";
- if (this.c < 0 && this.c > 1)
- throw "c should lie within [0;1]. Entered c = " + this.c + "\n";
- if (this.t < 0 && this.t > 1)
- throw "t should lie within [0;1]. Entered t = " + this.t + "\n";
- this._calculateTCtoRS();
- } else if (arguments.length == 3 + offset) {
- // CertainTrust(r, s, n)
- this.n = arguments[2 + offset];
- this.c = 0;
- this.t = 0.5;
- this.f = 0.5;
- this.r = arguments[0 + offset];
- this.s = arguments[1 + offset];
- this.doc = 0;
- if (this.n <= 0)
- throw "N should be greater than 0. Entered n = " + this.n + "\n";
- if (this.r < 0)
- throw "r should be positive. Entered r = " + this.r + "\n";
- if (this.s < 0)
- throw "s should be positive. Entered s = " + this.s + "\n";
- this._normaliseRS();
- this._calculateRStoTC();
- } else {
- if (arguments.length == 1 + offset) {
- // CertainTrust(n)
- this.n = arguments[0 + offset];
- if (this.n <= 0)
- throw "N should be greater than 0. Entered n = " + this.n + "\n";
- this.c = 0;
- this.t = 0.5;
- this.f = 0.5;
- this.r = 0;
- this.s = 0;
- this.doc = 0;
- }
- else throw "Illegal number of arguments: " + arguments.length + "\n";
- }
- };
- //=========== Getters =================
- CertainTrust.prototype.getName = function() {
- return this.name;
- };
- CertainTrust.prototype.getC = function() {
- return this.c;
- };
- CertainTrust.prototype.getT = function() {
- return this.t;
- };
- CertainTrust.prototype.getF = function() {
- return this.f;
- };
- CertainTrust.prototype.getR = function() {
- return this.r;
- };
- CertainTrust.prototype.getS = function() {
- return this.s;
- };
- CertainTrust.prototype.getN = function() {
- return this.n;
- };
- CertainTrust.prototype.getDoC = function() {
- return this.doc;
- };
- CertainTrust.prototype.getExpectation = function() {
- return (this.t * this.c) + ((1 - this.c) * this.f);
- };
- //=========== Setters =================
- /**
- * Resets N value. Renormalises r and s values, recalculates c and t accordingly.
- * @param n - new maximal number of expected evidence
- */
- CertainTrust.prototype.setN = function(n) {
- if (n > 0) {
- this.n = n;
- this._normaliseRS();
- this._calculateRStoTC();
- this.notifyObservers();
- }
- else throw "N should be greater than 0. Entered n = " + n + "\n";
- };
- /**
- * Sets f value.
- * @param f - initial trust value.
- */
- CertainTrust.prototype.setF = function(f) {
- if (f >= 0 && f <= 1) {
- this.f = f;
- this.notifyObservers();
- }
- else throw "f should lie within [0;1]. Entered f = " + f + "\n";
- };
- /**
- * Sets Degree of Conflict value.
- * @param doc is the new value for DoC
- */
- CertainTrust.prototype.setDoC = function(doc) {
- if (doc >= 0)
- this.doc = doc;
- else throw "DoC should be greater than 0. Entered DoC = " + doc + "\n";
- };
- /**
- * Sets c and t values. Recalculates r and s values accordingly.
- * @param t - new average trust value
- * @param c - new certainty value
- */
- CertainTrust.prototype.setTC = function(t, c) {
- if (c >= 0 && c <= 1) {
- if (t >= 0 && t <= 1) {
- this.c = c;
- this.t = t;
- this._calculateTCtoRS();
- this.notifyObservers();
- }
- else throw "t should be greater than 0. Entered t = " + t + "\n";
- }
- else throw "c should lie within [0;1]. Entered c = " + c + "\n";
- };
- /**
- * Sets r and s values. Recalculates c and t values accordingly.
- * @param r - new number of positive evidence
- * @param s - new number of negative evidence
- */
- CertainTrust.prototype.setRS = function(r, s) {
- if (r >= 0) {
- if (s >= 0) {
- this.r = r;
- this.s = s;
- this._normaliseRS();
- this._calculateRStoTC();
- this.notifyObservers();
- }
- else throw "s should be positive. Entered s = " + s + "\n";
- }
- else throw "r should be positive. Entered r = " + r + "\n";
- };
- /**
- * Add some positive evidence to r.
- * @param posEvidence - number of new positive evidences
- */
- CertainTrust.prototype.addR = function(posEvidence) {
- if (posEvidence >= 0) {
- this.r += posEvidence;
- this._normaliseRS();
- this._calculateRStoTC();
- this.notifyObservers();
- }
- else throw "Number of positive evidences should be positive. Entered " + posEvidence + "\n";
- };
- /**
- * Add some negative evidence to s.
- * @param negEvidence - number of new negative evidences
- */
- CertainTrust.prototype.addS = function(negEvidence) {
- if (negEvidence >= 0) {
- this.s += negEvidence;
- this._normaliseRS();
- this._calculateRStoTC();
- this.notifyObservers();
- }
- else throw "Number of negative evidences should be positive. Entered " + negEvidence + "\n";
- };
- //=========== Logic =================
- /**
- * Computes OR function for this CertainTrust object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrust object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrust object
- * @return - result of OR computation for this object and an argument.
- */
- CertainTrust.prototype._singleOR = function(arg) {
- var c1 = this.getC();
- var t1 = this.getT();
- var f1 = this.getF();
- var c2 = arg.getC();
- var t2 = arg.getT();
- var f2 = arg.getF();
- var resT = 0.5, resF = 0.5, resC = 0;
- if (!this._operationAllowed(this, arg))
- return undefined;
- resF = f1 + f2 - f1*f2;
- if (this._almostEqual(resF, 0)){
- f1 = 0.99999;
- f2 = 0.99999;
- resF = f1 + f2 - f1*f2;
- resC = c1 + c2 - c1*c2- (c1*f2*(1-c2)*(1-t1)+c2*f1*(1-c1)*(1-t2)) / resF;
- }
- else
- resC = c1 + c2 - c1*c2 - (c1*f2*(1-c2)*(1-t1)+c2*f1*(1-c1)*(1-t2)) / resF;
- if (this._almostEqual(resC, 0))
- resT = 0.5;
- else resT = (1/resC) * (c1*t1 + c2*t2 - c1*c2*t1*t2);
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- var result = new CertainTrust(resT, resC, resF, this.n, 0);
- return result;
- };
- /**
- * Computes OR function for this CertainTrust object and the specified arguments.
- * Result is returned as a new object, arguments and this CertainTrust object remain unchanged.
- * Example: a.OR(b, c, d) returns new CertainTrust object that equals a OR b OR c OR d.
- * Multiple arguments allowed, but not less than one.
- * N values of all objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param args - arguments
- * @return - result of OR computation for this object and all arguments.
- */
- CertainTrust.prototype.OR = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; ++i) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singleOR(m);
- }
- return result;
- };
- /**
- * Computes AND function for this CertainTrust object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrust object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrust object
- * @return - result of AND computation for this object and an argument.
- */
- CertainTrust.prototype._singleAND = function(arg){
- var c1 = this.getC();
- var f1 = this.getF();
- var t1 = this.getT();
- var c2 = arg.getC();
- var f2 = arg.getF();
- var t2 = arg.getT();
- var resC = 0, resT = 0.5, resF = 0.5;
- if (!this._operationAllowed(this, arg))
- return undefined;
- resF = f1*f2;
- if (this._almostEqual(resF, 1)){ //avoid division by 0
- f1 = 0.99999;
- f2 = 0.99999;
- resF = f1*f2;
- resC = c1 + c2 - c1*c2- (c2*t2*(1-c1)*(1-f1)+c1*t1*(1-c2)*(1-f2)) / (1 - resF);
- }
- else
- resC = c1 + c2 - c1*c2 - (c2*t2*(1-c1)*(1-f1)+c1*t1*(1-c2)*(1-f2)) / (1 - resF);
- if (this._almostEqual(resC, 0))
- resT = 0.5;
- else resT = (1/resC) * ((c1*t1*c2*t2) + (c1*f2*t1*(1-c2)*(1-f1)+c2*f1*t2*(1-c1)*(1-f2)) / (1 - resF));
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- return new CertainTrust(resT, resC, resF, this.n, 0);
- };
- CertainTrust.prototype._adjustValue = function(arg) {
- return Math.max(Math.min(arg, 1), 0);
- };
- CertainTrust.prototype._almostEqual = function(value, target) {
- return Math.abs(value - target) < 1E-10;
- };
- CertainTrust.prototype._operationAllowed = function(arg1, arg2) {
- //and all N's of TC's must be equal
- /*if (arg1.getN() != arg2.getN()) //Disabled by Debashis C. Ray for AND calculation
- throw "Different N values. Operation not allowed. \n"; */
- return true;
- }
- /**
- * Computes AND function for this CertainTrust object and the specified arguments.
- * Result is returned as a new object, arguments and this CertainTrust object remain unchanged.
- * Example: a.AND(b, c, d) returns new CertainTrust object that equals a AND b AND c AND d.
- * Multiple arguments allowed, but not less than one.
- * N values of all objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param args - arguments
- * @return - result of AND computation for this object and all arguments.
- */
- CertainTrust.prototype.AND = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; i++) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singleAND(m);
- }
- return result;
- };
- /**
- * Returns NOT of this CertainTrust object.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @return - NOT of this CertainTrust object.
- */
- CertainTrust.prototype.NOT = function() {
- var result = this.clone();
- result.setTC(1 - this.getT(), this.getC());
- result.setF(1 - this.getF());
- result.setDoC(0);
- return result;
- };
- /**
- * an internal implementation of fusion function.
- * Is called by wFusion and cFusion
- * @param args - an array of CertainTrust objects
- * @param weights - an integer array of corresponding weights
- * @param doc - a degree of conflict (always 0 for wFusion)
- * @return - new CertainTrust object
- */
- CertainTrust.prototype._internalFusion = function(args, weights, doc) {
- var resC, resT, resF;
- var allOne = true;
- var allZero = true;
- var allWeightsZero = true;
- var atLeastOne1 = false;
- var arrLength = args.length;
- // set the flags about C and Weight values
- for (var i = 0; i < arrLength; ++i)
- if (args[i].getC() !== 1) {
- allOne = false;
- i = arrLength;
- }
- for (i = 0; i < arrLength; ++i)
- if (args[i].getC() !== 0) {
- allZero = false;
- i = arrLength;
- }
- for (i = 0; i < arrLength; ++i)
- if (weights[i] !== 0) {
- allWeightsZero = false;
- i = arrLength;
- }
- for (i = 0; i < arrLength; ++i)
- if (args[i].getC() === 1) {
- atLeastOne1 = true;
- i = arrLength;
- }
- //Calculate T and C
- // 1. all C's = 1
- var numeratorT = 0, denominatorT = 0;
- if (allOne) {
- // set C
- resC = 1 * (1 - doc);
- // set T
- if (allWeightsZero) {// save some calculation time
- resT = 0;
- }
- else { // or use the function
- for (i = 0; i < arrLength; ++i) {
- numeratorT += weights[i] * args[i].getT();
- denominatorT += weights[i];
- }
- resT = numeratorT/denominatorT;
- }
- } else {
- if (atLeastOne1)
- throw "Illegal arguments. Either all C values must equal 1 or none of them. Operation not allowed\n";
- else {
- // 2. Any other combination
- if (allWeightsZero) { // save some calculation time
- resT = 0;
- resC = 0;
- }
- else { // or use the function
- var numeratorC = 0, denominatorC = 0, mult;
- for (i = 0; i < arrLength; ++i) {
- mult = 1;
- for (var j = 0; j < arrLength; ++j) // Count the product for each sum element
- if (j !== i)
- mult *= 1 - args[j].getC();
- numeratorT += weights[i] * args[i].getT() * args[i].getC() * mult;
- denominatorT += weights[i] * args[i].getC() * mult;
- denominatorC += weights[i] * mult;
- }
- numeratorC = denominatorT;
- resC = (numeratorC/denominatorC) * (1 - doc);
- if (allZero)
- resT = 0.5;
- else
- resT = numeratorT/denominatorT;
- }
- // Special case for T
- if (allZero)
- resT = 0.5;
- }
- }
- // Calculate F
- if (allWeightsZero)
- resF = 0;
- else {
- var numerator = 0, denominator = 0;
- for (i = 0; i < arrLength; ++i) {
- numerator += weights[i] * args[i].getF();
- denominator += weights[i];
- }
- resF = numerator/denominator;
- }
- var result = args[0].clone();
- result.setTC(resT, resC);
- result.setF(resF);
- result.setDoC(doc);
- return result;
- };
- /**
- * Performs weighted fusion for an array of CertainTrust objects in correspondence with
- * an array of weights. Returns new CertainTrust object.
- * Requirements: N values of CertainTrust objects must be equal.
- * Number of weights should equal the number of CertainTrust objects.
- * Arrays must be non-empty
- * Either all of CertainTrust must be of certainty 1 or none of them.
- * @param args - an array of CertainTrust objects
- * @param weights - an integer array of corresponding weights
- * @return - new CertainTrust object
- */
- CertainTrust.prototype.wFusion = function(args, weights) {
- //arrays should be equal
- if (args.length == weights.length) {
- //and not empty
- if (args.length !== 0) {
- for (var i = 1; i < args.length; ++i)
- if (!this._operationAllowed(args[0], args[i]))
- return undefined;
- return this._internalFusion(args, weights, 0);
- }
- else throw "Arrays are empty. Operation not allowed. \n";
- }
- else throw "Different lengths of arrays. Operation not allowed. \n";
- };
- /**
- * Conflicted Fusion is a variation of weighted fusion, which additionally computes the degree of conflict
- * between given opinions (CertainTrust objects) and takes it into consideration while performing fusion.
- * The degree of conflict is then saved in the resulting CertainTrust object and may be checked with getDoC() function.
- * @param args - an array of CertainTrust objects
- * @param weights - an integer array of corresponding weights
- * @return - new CertainTrust object
- */
- CertainTrust.prototype.cFusion = function(args, weights) {
- //arrays should be equal
- if (args.length == weights.length) {
- //and not empty
- if (args.length !== 0) {
- for (var i = 1; i < args.length; ++i)
- if (!this._operationAllowed(args[0], args[i]))
- return undefined;
- var denominator = args.length*(args.length - 1) / 2;
- var numerator = 0;
- for (i = 0; i < args.length; ++i)
- for (var j = i; j < args.length; ++j)
- numerator += Math.abs(args[i].getT() - args[j].getT()) *
- args[i].getC() * args[j].getC() *
- (1 - Math.abs((weights[i] - weights[j]) /
- (weights[i] + weights[j])));
- var doc = numerator/denominator;
- return this._internalFusion(args, weights, doc);
- }
- else throw "Arrays are empty. Operation not allowed. \n";
- }
- else throw "Different lengths of arrays. Operation not allowed. \n";
- };
- //=========== Internal Calculations ==========
- /**
- * Normalises r and s values according to n - maximal number of expected evidence
- * Important! Doesn't notify observers.
- */
- CertainTrust.prototype._normaliseRS = function() {
- if ((this.r + this.s) > this.n) {
- var initR = this.r;
- this.r = (this.r * this.n) / (initR + this.s);
- this.s = (this.s * this.n) / (initR + this.s);
- }
- };
- /**
- * Calculates t and c values based on existing r and s values
- * Important! Doesn't notify observers.
- */
- CertainTrust.prototype._calculateRStoTC = function() {
- var rs = this.r + this.s;
- var nrs = this.n * rs;
- this.c = nrs / ((2 * this.weight * (this.n - this.r - this.s)) + nrs);
- if (this._almostEqual(this.c, 0))
- this.t = 0.5;
- else
- this.t = this.r / rs;
- };
- /**
- * Calculates r and s values based on existing c and t values
- * Important! Doesn't notify observers.
- */
- CertainTrust.prototype._calculateTCtoRS = function() {
- if (this._almostEqual(this.c, 0)) {
- this.r = 0;
- this.s = 0;
- this.t = 0.5;
- }
- else {
- var c2w = this.c * 2 * this.weight;
- var c2wn = c2w * this.n;
- var cn = this.c * this.n;
- this.r = (c2wn * this.t) / (c2w + this.n - cn);
- this.s = (c2wn - (c2wn * this.t)) / (c2w + this.n - cn);
- }
- };
- CertainTrust.prototype.clone = function() {
- var copy = new CertainTrust(this.getN());
- copy.c = this.c;
- copy.t = this.t;
- copy.f = this.f;
- copy.r = this.r;
- copy.s = this.s;
- copy.doc = this.doc;
- return copy;
- };
- CertainTrust.prototype._isString = function (obj) {
- return typeof(obj) === 'string';
- };
- //=========== Observer =================
- CertainTrust.prototype.notifyObservers = function(message) {
- for (var i = 0; i < this.observers.length; ++i)
- this.observers[i].update(this.observers[i], message);
- };
- CertainTrust.prototype.addObserver = function(observer) {
- this.observers.push(observer);
- };
- CertainTrust.prototype.deleteObserver = function(observer) {
- var idx = this.observers.indexOf(observer);
- if(idx !== -1)
- this.observers.splice(idx, 1);
- };
- //=== shared functions for frontends ===
- CertainTrust.prototype._insertElement = function(config, element) {
- var dom;
- if (config.domReturn === true) {
- return element;
- } else if (config.domParent !== undefined) {
- if (this._isString(config.domParent))
- document.getElementById(config.domParent).appendChild(element);
- else
- config.domParent.appendChild(element);
- } else if (config.domBefore !== undefined) {
- if (this._isString(config.domBefore))
- dom = document.getElementById(config.domBefore);
- else
- dom = config.domBefore;
- dom.parentNode.insertBefore(element, dom);
- } else {
- if (config.domAfter === undefined) {
- // the last script tag in DOM tree is the one creating this widget
- var scripts = document.getElementsByTagName('script');
- dom = scripts[scripts.length - 1];
- } else if (this._isString(config.domAfter))
- dom = document.getElementById(config.domAfter);
- else
- dom = config.domAfter;
- dom.parentNode.insertBefore(element, dom.nextSibling);
- }
- return undefined;
- };
- CertainTrust.prototype._getColor = function(certainty, trust, initf) {
- var resultp2 = ((1 - certainty) * initf);
- var result = (trust * certainty) + resultp2;
- var color;
- if (result < 0.5) {
- color = [
- 255,
- Math.min(255, (255 * 2 * result)),
- 0
- ];
- } else {
- color = [
- Math.min(255, ((2 - (2 * result)) * 255)),
- 255,
- 0
- ];
- }
- return color;
- };
- CertainTrust.prototype._pointOnCircle = function(centerx, centery, pointgrade, radius) {
- var pointrad = ((360 + pointgrade) % 360) * ((2 * Math.PI) / 360);
- var chord = 2 * radius * Math.sin((pointrad / 2));
- // height of our new point above the base-edge
- var y = Math.sqrt(2
- * (Math.pow(chord, 2) * Math.pow(radius, 2)
- + Math.pow(radius, 4) + Math.pow(radius, 2)
- * Math.pow(chord, 2))
- - (Math.pow(chord, 4) + 2 * Math.pow(radius, 4)))
- / (2 * radius);
- // distance to the cross-point of base-edge and height
- var a = Math.pow(radius, 2);
- var c = Math.pow(y, 2);
- // we do this to protect us from NaN cause by 1 - 1.00000004
- var x = (a < c) ? 0 : Math.sqrt(a - c);
- var directions = new Array("NE", "SE", "SW", "NW");
- var direction = 0;
- var alpharad = pointrad;
- while (alpharad > (0.5 * Math.PI)) {
- ++direction;
- alpharad -= (0.5 * Math.PI);
- }
- if (directions[direction] == "NE" || directions[direction] == "NW")
- x *= -1;
- if (directions[direction] == "SW" || directions[direction] == "NW")
- y *= -1;
- return new Array((centerx + x), (centery + y));
- };
- /* optional implementation of CertainTrust without R and S calculations */
- var CertainTrustSimple = function() {
- this.weight = 2;
- this.observers = [];
- var offset = 0;
- this.name = "";
- if (this._isString(arguments[0])) {
- this.name = arguments[0];
- offset = 1;
- }
- if (arguments.length == 3 + offset || arguments.length == 4 + offset) {
- // CertainTrustSimple(t, c, f, doc)
- // doc is a 'private' parameter
- this.t = arguments[0 + offset];
- this.c = arguments[1 + offset];
- this.f = arguments[2 + offset];
- this.doc = (arguments.length == 3 + offset) ? 0 : arguments[3 + offset];
- if (this.f < 0 && this.f > 1)
- throw "f should lie within [0;1]. Entered f = " + this.f + "\n";
- if (this.c < 0 && this.c > 1)
- throw "c should lie within [0;1]. Entered c = " + this.c + "\n";
- if (this.t < 0 && this.t > 1)
- throw "t should lie within [0;1]. Entered t = " + this.t + "\n";
- } else {
- this.c = 0;
- this.t = 0.5;
- this.f = 0.5;
- this.doc = 0;
- }
- };
- CertainTrustSimple.prototype = new CertainTrust(1);
- CertainTrustSimple.prototype.constructor = CertainTrustSimple;
- CertainTrustSimple.prototype._operationAllowed = function() { return true; }
- CertainTrustSimple.prototype._calculateTCtoRS = function() { }
- CertainTrustSimple.prototype._calculateRStoTC = function() { }
- CertainTrustSimple.prototype._normaliseRS = function() { }
- CertainTrustSimple.prototype.setRS = undefined;
- CertainTrustSimple.prototype.addR = undefined;
- CertainTrustSimple.prototype.addS = undefined;
- CertainTrustSimple.prototype.setN = undefined;
- CertainTrustSimple.prototype.getR = undefined;
- CertainTrustSimple.prototype.getS = undefined;
- CertainTrustSimple.prototype.getN = undefined;
- CertainTrustSimple.prototype.clone = function() {
- var copy = new CertainTrustSimple();
- copy.c = this.c;
- copy.t = this.t;
- copy.f = this.f;
- copy.doc = this.doc;
- return copy;
- };
- /*Added by Debashis*/
- /**
- * Computes OR function for this CertainTrustSimple object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrust object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrustSimple object
- * @return - result of OR computation for this object and an argument.
- */
- CertainTrust.prototype._singlesimpleOR = function(arg) {
- var c1 = this.getC();
- var t1 = this.getT();
- var f1 = this.getF();
- var c2 = arg.getC();
- var t2 = arg.getT();
- var f2 = arg.getF();
- var resT = 0.5, resF = 0.5, resC = 0;
- if (!this._operationAllowed(this, arg))
- return undefined;
- resF = f1 + f2 - f1*f2;
- if (this._almostEqual(resF, 0)){
- f1 = 0.99999;
- f2 = 0.99999;
- resF = f1 + f2 - f1*f2;
- resC = c1 + c2 - c1*c2- (c1*f2*(1-c2)*(1-t1)+c2*f1*(1-c1)*(1-t2)) / resF;
- }
- else
- resC = c1 + c2 - c1*c2 - (c1*f2*(1-c2)*(1-t1)+c2*f1*(1-c1)*(1-t2)) / resF;
- if (this._almostEqual(resC, 0))
- resT = 0.5;
- else resT = (1/resC) * (c1*t1 + c2*t2 - c1*c2*t1*t2);
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- var result = new CertainTrustSimple(resT, resC, resF, this.n, 0);
- return result;
- };
- /**
- * Computes OR function for this CertainTrustSimple object and the specified arguments.
- * Result is returned as a new object, arguments and this CertainTrustSimple object remain unchanged.
- * Example: a.OR(b, c, d) returns new CertainTrust object that equals a OR b OR c OR d.
- * Multiple arguments allowed, but not less than one.
- * N values of all objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param args - arguments
- * @return - result of OR computation for this object and all arguments.
- */
- CertainTrustSimple.prototype.simpleOR = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; ++i) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singlesimpleOR(m);
- }
- return result;
- };
- /**
- * Computes AND function for this CertainTrustSimple object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrustSimple object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrustSimple object
- * @return - result of AND computation for this object and an argument.
- */
- CertainTrustSimple.prototype._singlesimpleAND = function(arg){
- var c1 = this.getC();
- var f1 = this.getF();
- var t1 = this.getT();
- var c2 = arg.getC();
- var f2 = arg.getF();
- var t2 = arg.getT();
- var resC = 0, resT = 0.5, resF = 0.5;
- if (!this._operationAllowed(this, arg))
- return undefined;
- resF = f1*f2;
- if (this._almostEqual(resF, 1)){ //avoid division by 0
- f1 = 0.99999;
- f2 = 0.99999;
- resF = f1*f2;
- resC = c1 + c2 - c1*c2 - (c2*t2*(1-c1)*(1-f1)+c1*t1*(1-c2)*(1-f2)) / (1 - resF);
- }
- else
- resC = c1 + c2 - c1*c2 - (c2*t2*(1-c1)*(1-f1)+c1*t1*(1-c2)*(1-f2)) / (1 - resF);
- if (this._almostEqual(resC, 0))
- resT = 0.5;
- else resT = (1/resC) * ((c1*t1*c2*t2) + (c1*f2*t1*(1-c2)*(1-f1)+c2*f1*t2*(1-c1)*(1-f2)) / (1 - resF));
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- return new CertainTrustSimple(resT, resC, resF);
- };
- /**
- * Computes AND function for this CertainTrustSimple object and the specified arguments.
- * Result is returned as a new object, arguments and this CertainTrustSimple object remain unchanged.
- * Example: a.AND(b, c, d) returns new CertainTrustSimple object that equals a AND b AND c AND d.
- * Multiple arguments allowed, but not less than one.
- * N values of all objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param args - arguments
- * @return - result of AND computation for this object and all arguments.
- */
- CertainTrustSimple.prototype.simpleAND = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; i++) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singlesimpleAND(m);
- }
- return result;
- };
- /**
- * Returns NOT of this CertainTrustSimple object.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @return - NOT of this CertainTrustSimple object.
- */
- CertainTrustSimple.prototype.simpleNOT = function() {
- var result = this.clone();
- result.setTC(1 - this.getT(), this.getC());
- result.setF(1 - this.getF());
- result.setDoC(0);
- return result;
- };
- CertainTrust.prototype.setName = function(newname) {
- this.name = newname;
- };
- /**
- * Computes CONSENSUS function for this CertainTrust object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrust object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrust object
- * @return - result of CONSENSUS computation for this object and an argument.
- */
- CertainTrust.prototype._singleCONSENSUS = function(arg){
- var c1 = this.getC();
- var f1 = this.getF();
- var t1 = this.getT();
- var c2 = arg.getC();
- var f2 = arg.getF();
- var t2 = arg.getT();
- var resC = 0, resT = 0.5, resF = 0.5;
- if (!this._operationAllowed(this, arg))
- return undefined;
- var tempC = c1*c2;
- if (this._almostEqual(tempC, 1)){ //avoid division by 0
- c1 = 0.99999;
- c2 = 0.99999;
- }
- resF = (f1*c1*(1-c2) + f2*c2*(1-c1))/(c1+c2-2*c1*c2);
- resC = (c1+c2-2*c1*c2)/(1-c1*c2);
- resT = (c1*t1*(1-c2)+c2*t2*(1-c1))/(c1+c2-2*c1*c2);
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- return new CertainTrust(resT, resC, resF, this.n, 0);
- };
- CertainTrust.prototype.CONSENSUS = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; i++) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singleCONSENSUS(m);
- }
- return result;
- };
- /**
- * Computes DISCOUNTING function for this CertainTrust object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrust object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrust object
- * @return - result of DISCOUNTING computation for this object and an argument.
- */
- CertainTrust.prototype._singleDISCOUNTING = function(arg){
- var c1 = this.getC();
- var f1 = this.getF();
- var t1 = this.getT();
- var c2 = arg.getC();
- var f2 = arg.getF();
- var t2 = arg.getT();
- var resC = 0, resT = 0.5, resF = 0.5;
- if (!this._operationAllowed(this, arg))
- return undefined;
- //resF = f1*f2;
- if (this._almostEqual(resF, 1)) //avoid division by 0
- resC = t1*c1*c2;
- else
- resC = t1*c1*c2;
- if (this._almostEqual(resC, 0))
- resT = t2;
- else if (this._almostEqual(resF, 1)) //avoid division by 0
- resT = t2;
- else resT = t2;
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- return new CertainTrust(resT, resC, resF, this.n, 0);
- };
- CertainTrust.prototype.DISCOUNTING = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; i++) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singleDISCOUNTING(m);
- }
- return result;
- };
- /**
- * Computes CONSENSUS function for this CertainTrustSimple object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrust object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrustSimple object
- * @return - result of CONSENSUS computation for this object and an argument.
- */
- CertainTrustSimple.prototype._singlesimpleCONSENSUS = function(arg){
- var c1 = this.getC();
- var f1 = this.getF();
- var t1 = this.getT();
- var c2 = arg.getC();
- var f2 = arg.getF();
- var t2 = arg.getT();
- var resC = 0, resT = 0.5, resF = 0.5;
- if (!this._operationAllowed(this, arg))
- return undefined;
- var tempC = c1*c2;
- if (this._almostEqual(tempC, 1)){ //avoid division by 0
- c1 = 0.99999;
- c2 = 0.99999;
- }
- resF = (f1*c1*(1-c2) + f2*c2*(1-c1))/(c1+c2-2*c1*c2);
- resC = (c1+c2-2*c1*c2)/(1-c1*c2);
- resT = (c1*t1*(1-c2)+c2*t2*(1-c1))/(c1+c2-2*c1*c2);
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- return new CertainTrustSimple(resT, resC, resF);
- };
- CertainTrustSimple.prototype.simpleCONSENSUS = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; i++) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singlesimpleCONSENSUS(m);
- }
- return result;
- };
- /**
- * Computes DISCOUNTING function for this CertainTrustSimple object and the specified argument. Result is returned as a new object,
- * argument and this CertainTrustSimple object remain unchanged.
- * N values of both objects should be equal.
- * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
- * @param arg - CertainTrustSimple object
- * @return - result of DISCOUNTING computation for this object and an argument.
- */
- CertainTrustSimple.prototype._singlesimpleDISCOUNTING = function(arg){
- var c1 = this.getC();
- var f1 = this.getF();
- var t1 = this.getT();
- var c2 = arg.getC();
- var f2 = arg.getF();
- var t2 = arg.getT();
- var resC = 0, resT = 0.5, resF = 0.5;
- if (!this._operationAllowed(this, arg))
- return undefined;
- //resF = f1*f2;
- if (this._almostEqual(resF, 1)) //avoid division by 0
- resC = t1*c1*c2;
- else
- resC = t1*c1*c2;
- if (this._almostEqual(resC, 0))
- resT = t2;
- else if (this._almostEqual(resF, 1)) //avoid division by 0
- resT = t2;
- else resT = t2;
- resT = this._adjustValue(resT);
- resC = this._adjustValue(resC);
- resF = this._adjustValue(resF);
- return new CertainTrustSimple(resT, resC, resF, this.n, 0);
- };
- CertainTrustSimple.prototype.simpleDISCOUNTING = function() {
- var result = this.clone();
- for (var i = 0; i < arguments.length; i++) {
- var m = arguments[i];
- if (!this._operationAllowed(this, m))
- continue;
- result = result._singlesimpleDISCOUNTING(m);
- }
- return result;
- };
- /**
- * an internal implementation of fusion function.
- * Is called by wFusion and cFusion
- * @param args - an array of CertainTrustSimple objects
- * @param weights - an integer array of corresponding weights
- * @param doc - a degree of conflict (always 0 for wFusion)
- * @return - new CertainTrustSimple object
- */
- CertainTrustSimple.prototype._simpleinternalFusion = function(args, weights, doc) {
- var resC, resT, resF;
- var allOne = true;
- var allZero = true;
- var allWeightsZero = true;
- var atLeastOne1 = false;
- var arrLength = args.length;
- // set the flags about C and Weight values
- for (var i = 0; i < arrLength; ++i)
- if (args[i].getC() !== 1) {
- allOne = false;
- i = arrLength;
- }
- for (i = 0; i < arrLength; ++i)
- if (args[i].getC() !== 0) {
- allZero = false;
- i = arrLength;
- }
- for (i = 0; i < arrLength; ++i)
- if (weights[i] !== 0) {
- allWeightsZero = false;
- i = arrLength;
- }
- for (i = 0; i < arrLength; ++i)
- if (args[i].getC() === 1) {
- atLeastOne1 = true;
- i = arrLength;
- }
- //Calculate T and C
- // 1. all C's = 1
- var numeratorT = 0, denominatorT = 0;
- if (allOne) {
- // set C
- resC = 1 * (1 - doc);
- // set T
- if (allWeightsZero) {// save some calculation time
- resT = 0;
- }
- else { // or use the function
- for (i = 0; i < arrLength; ++i) {
- numeratorT += weights[i] * args[i].getT();
- denominatorT += weights[i];
- }
- resT = numeratorT/denominatorT;
- }
- } else {
- if (atLeastOne1)
- throw "Illegal arguments. Either all C values must equal 1 or none of them. Operation not allowed\n";
- else {
- // 2. Any other combination
- if (allWeightsZero) { // save some calculation time
- resT = 0;
- resC = 0;
- }
- else { // or use the function
- var numeratorC = 0, denominatorC = 0, mult;
- for (i = 0; i < arrLength; ++i) {
- mult = 1;
- for (var j = 0; j < arrLength; ++j) // Count the product for each sum element
- if (j !== i)
- mult *= 1 - args[j].getC();
- numeratorT += weights[i] * args[i].getT() * args[i].getC() * mult;
- denominatorT += weights[i] * args[i].getC() * mult;
- denominatorC += weights[i] * mult;
- }
- numeratorC = denominatorT;
- resC = (numeratorC/denominatorC) * (1 - doc);
- if (allZero)
- resT = 0.5;
- else
- resT = numeratorT/denominatorT;
- }
- // Special case for T
- if (allZero)
- resT = 0.5;
- }
- }
- // Calculate F
- if (allWeightsZero)
- resF = 0;
- else {
- var numerator = 0, denominator = 0;
- for (i = 0; i < arrLength; ++i) {
- numerator += weights[i] * args[i].getF();
- denominator += weights[i];
- }
- resF = numerator/denominator;
- }
- var result = args[0].clone();
- result.setTC(resT, resC);
- result.setF(resF);
- result.setDoC(doc);
- return result;
- };
- /**
- * Performs weighted fusion for an array of CertainTrustSimple objects in correspondence with
- * an array of weights. Returns new CertainTrust object.
- * Requirements: N values of CertainTrustSimple objects must be equal.
- * Number of weights should equal the number of CertainTrust objects.
- * Arrays must be non-empty
- * Either all of CertainTrust must be of certainty 1 or none of them.
- * @param args - an array of CertainTrustSimple objects
- * @param weights - an integer array of corresponding weights
- * @return - new CertainTrustSimple object
- */
- CertainTrustSimple.prototype.simplewFusion = function(args, weights) {
- //arrays should be equal
- if (args.length == weights.length) {
- //and not empty
- if (args.length !== 0) {
- for (var i = 1; i < args.length; ++i)
- if (!this._operationAllowed(args[0], args[i]))
- return undefined;
- return this._simpleinternalFusion(args, weights, 0);
- }
- else throw "Arrays are empty. Operation not allowed. \n";
- }
- else throw "Different lengths of arrays. Operation not allowed. \n";
- };
- /**
- * Conflicted Fusion is a variation of weighted fusion, which additionally computes the degree of conflict
- * between given opinions (CertainTrustSimple objects) and takes it into consideration while performing fusion.
- * The degree of conflict is then saved in the resulting CertainTrust object and may be checked with getDoC() function.
- * @param args - an array of CertainTrustSimple objects
- * @param weights - an integer array of corresponding weights
- * @return - new CertainTrustSimple object
- */
- CertainTrustSimple.prototype.simplecFusion = function(args, weights) { //
- //arrays should be equal
- if (args.length == weights.length) {
- //and not empty
- if (args.length !== 0) {
- for (var i = 1; i < args.length; ++i)
- if (!this._operationAllowed(args[0], args[i]))
- return undefined;
- var denominator = args.length*(args.length - 1) / 2;
- var numerator = 0;
- for (i = 0; i < args.length; ++i)
- for (var j = i; j < args.length; ++j)
- numerator += Math.abs(args[i].getT() - args[j].getT()) *
- args[i].getC() * args[j].getC() *
- (1 - Math.abs((weights[i] - weights[j]) /
- (weights[i] + weights[j])));
- var doc = numerator/denominator;
- return this._simpleinternalFusion(args, weights, doc);
- }
- else throw "Arrays are empty. Operation not allowed. \n";
- }
- else throw "Different lengths of arrays. Operation not allowed. \n";
- };
|