CertainTrust.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /**
  2. * CertainTrust SDK
  3. *
  4. * Implements the computational trust model "CertainTrust"
  5. * in Java.
  6. * See <http://www.tk.informatik.tu-darmstadt.de/de/research/smart-security-and-trust/> for further details.
  7. *
  8. *
  9. * Telecooperation Department, Technische Universit�t Darmstadt
  10. * <http://www.tk.informatik.tu-darmstadt.de/>
  11. *
  12. * Prof. Dr. Max Mühlhäuser <max@informatik.tu-darmstadt.de>
  13. * Florian Volk <florian.volk@cased.de>
  14. *
  15. *
  16. * @author Maria Pelevina
  17. * @author David Kalnischkies
  18. * @version 1.1
  19. */
  20. /* This Source Code Form is subject to the terms of the Mozilla Public
  21. * License, v. 2.0. If a copy of the MPL was not distributed with this
  22. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  23. package CertainTrust;
  24. import java.util.Observable;
  25. /**
  26. *
  27. * t - average rating value, [0; 1], from very negative to very positive
  28. * c - certainty value, [0; 1] from low certainty (no evidence) to the maximal maximal certainty.
  29. * f - initial trust value
  30. * w - weight
  31. * r - number of positive evidence
  32. * s - number of negative evidence
  33. * n - maximal number of expected evidence
  34. * doc - degree of conflict
  35. *
  36. */
  37. public class CertainTrust extends Observable {
  38. private double c, t, f, r, s, doc;
  39. private String name;
  40. private int n, weight = 2;
  41. //=========== Constructors =================
  42. /**
  43. * Constructs a CertainTrust object with predefined n value.
  44. * @param n - maximal number of expected evidence
  45. */
  46. public CertainTrust(int n) {
  47. if (n > 0) {
  48. this.n = n;
  49. c = 0;
  50. t = 0.5;
  51. f = 0.5;
  52. r = 0;
  53. s = 0;
  54. }
  55. else throw new IllegalArgumentException("N should be greater than 0. Entered n = " + n + "\n");
  56. }
  57. /**
  58. * Constructs a CertainTrust object with predefined r, s, n values.
  59. * @param r - number of positive evidence
  60. * @param s - number of negative evidence
  61. * @param n - maximal number of expected evidence
  62. */
  63. public CertainTrust(double r, double s, int n) {
  64. if (n > 0) {
  65. this.n = n;
  66. this.c = 0;
  67. this.t = 0.5;
  68. this.f = 0.5;
  69. this.doc = 0;
  70. setRS(r, s);
  71. }
  72. else throw new IllegalArgumentException("N should be greater than 0. Entered n = " + n + "\n");
  73. }
  74. /**
  75. * Constructs a CertainTrust object with predefined c, t, f, n values.
  76. * @param c - certainty
  77. * @param t - average rating
  78. * @param f - initial trust value
  79. * @param n - maximal number of expected evidence
  80. */
  81. public CertainTrust(double t, double c, double f, int n) {
  82. this(t,c,f,n,0);
  83. }
  84. /**
  85. * Constructs a CertainTrust object with predefined c, t, f, n values.
  86. * @param c - certainty
  87. * @param t - average rating
  88. * @param f - initial trust value
  89. * @param n - maximal number of expected evidence
  90. * @param doc - initial degree of conflict
  91. */
  92. private CertainTrust(double t, double c, double f, int n, double doc) {
  93. if (n > 0) {
  94. if (f <= 1 && f >= 0) {
  95. this.n = n;
  96. this.f = f;
  97. this.r = 0;
  98. this.s = 0;
  99. this.doc = doc;
  100. setTC(t, c);
  101. }
  102. else throw new IllegalArgumentException("f should lie within [0;1]. Entered f = " + f + "\n");
  103. }
  104. else throw new IllegalArgumentException("N should be greater than 0. Entered n = " + n + "\n");
  105. }
  106. //=========== Setters =================
  107. /**
  108. * Resets N value. Renormalises r and s values, recalculates c and t accordingly.
  109. * @param n - new maximal number of expected evidence
  110. */
  111. public void setN(int n) {
  112. if (n > 0) {
  113. this.n = n;
  114. normaliseRS();
  115. calculateRStoTC();
  116. setChanged();
  117. notifyObservers();
  118. }
  119. else throw new IllegalArgumentException("N should be greater than 0. Entered n = " + n + "\n");
  120. }
  121. /**
  122. * Sets f value.
  123. * @param f - initial trust value.
  124. */
  125. public void setF(double f) {
  126. if (f >= 0 && f <= 1) {
  127. this.f = f;
  128. setChanged();
  129. notifyObservers();
  130. }
  131. else throw new IllegalArgumentException("f should lie within [0;1]. Entered f = " + f + "\n");
  132. }
  133. /**
  134. * Sets Distance of Conflict value.
  135. * @param doc is the new value for DoC
  136. */
  137. public void setDoC(double doc) {
  138. if (doc > 0) {
  139. this.doc = doc;
  140. }
  141. else throw new IllegalArgumentException("DoC should be greater than 0. Entered DoC = " + doc + "\n");
  142. }
  143. /**
  144. * Sets c and t values. Recalculates r and s values accordingly.
  145. * @param t - new average trust value
  146. * @param c - new certainty value
  147. */
  148. public void setTC(double t, double c) {
  149. if (c >= 0 && c <= 1) {
  150. if (t >= 0 && t <= 1) {
  151. this.c = c;
  152. this.t = t;
  153. calculateTCtoRS();
  154. setChanged();
  155. notifyObservers();
  156. }
  157. else throw new IllegalArgumentException("t should be greater than 0. Entered t = " + t + "\n");
  158. }
  159. else throw new IllegalArgumentException("c should lie within [0;1]. Entered c = " + c + "\n");
  160. }
  161. /**
  162. * Sets r and s values. Recalculates c and t values accordingly.
  163. * @param r - new number of positive evidence
  164. * @param s - new number of negative evidence
  165. */
  166. public void setRS(double r, double s) {
  167. if (r >= 0) {
  168. if (s >= 0) {
  169. this.r = r;
  170. this.s = s;
  171. normaliseRS();
  172. calculateRStoTC();
  173. setChanged();
  174. notifyObservers();
  175. }
  176. else throw new IllegalArgumentException("s should be positive. Entered s = " + s + "\n");
  177. }
  178. else throw new IllegalArgumentException("r should be positive. Entered r = " + r + "\n");
  179. }
  180. /**
  181. * Sets name value.
  182. * @param name - name of object.
  183. */
  184. public void setName(String s) {
  185. this.name = s;
  186. }
  187. /**
  188. * Add some positive evidence to r.
  189. * @param posEvidence - number of new positive evidences
  190. */
  191. public void addR(int posEvidence) {
  192. if (posEvidence >= 0) {
  193. r += posEvidence;
  194. normaliseRS();
  195. calculateRStoTC();
  196. setChanged();
  197. notifyObservers();
  198. }
  199. else throw new IllegalArgumentException("Number of positive evidences should be positive. Entered " + posEvidence + "\n");
  200. }
  201. /**
  202. * Add some negative evidence to s.
  203. * @param negEvidence - number of new negative evidences
  204. */
  205. public void addS(int negEvidence) {
  206. if (negEvidence >= 0) {
  207. s += negEvidence;
  208. normaliseRS();
  209. calculateRStoTC();
  210. setChanged();
  211. notifyObservers();
  212. }
  213. else throw new IllegalArgumentException("Number of negative evidences should be positive. Entered " + negEvidence + "\n");
  214. }
  215. //=========== Internal Calculations ==========
  216. /**
  217. * Normalises r and s values according to n - maximal number of expected evidence
  218. * Important! Doesn't notify observers.
  219. */
  220. private void normaliseRS() {
  221. if (r + s > n){
  222. double initR = r;
  223. r = r*n / (initR + s);
  224. s = s*n / (initR + s);
  225. }
  226. }
  227. /**
  228. * Calculates c and t values based on existing r and s values
  229. * Important! Doesn't notify observers.
  230. */
  231. private void calculateRStoTC() {
  232. c = n * (r + s) / ( weight*(n-r-s) + n*(r+s));
  233. if (c == 0)
  234. t = 0.5;
  235. else t = r / (r + s);
  236. }
  237. /**
  238. * Calculates r and s values based on existing c and t values
  239. * Important! Doesn't notify observers.
  240. */
  241. private void calculateTCtoRS() {
  242. if (c == 0) {
  243. r = 0;
  244. s = 0;
  245. t = 0.5;
  246. }
  247. else {
  248. r = (2*c*weight*n*t) / (2*c*weight + n - c*n);
  249. s = (2*c*weight*n - 2*c*weight*n*t) / (2*c*weight + n - c*n);
  250. }
  251. }
  252. //=========== Getters =================
  253. public double getC() {
  254. return c;
  255. }
  256. public double getT() {
  257. return t;
  258. }
  259. public double getF() {
  260. return f;
  261. }
  262. public double getR() {
  263. return r;
  264. }
  265. public double getS() {
  266. return s;
  267. }
  268. public int getN() {
  269. return n;
  270. }
  271. public double getDoC() {
  272. return doc;
  273. }
  274. public String getName() {
  275. return name;
  276. }
  277. public double getExpectation() {
  278. return t*c + (1-c)*f;
  279. }
  280. //=========== Logic =================
  281. /**
  282. * Computes OR function for this CertainTrust object and the specified argument. Result is returned as a new object,
  283. * argument and this CertainTrust object remain unchanged.
  284. * N values of both objects should be equal.
  285. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  286. * @param arg - CertainTrust object
  287. * @return - result of OR computation for this object and an argument.
  288. */
  289. private CertainTrust OR(CertainTrust arg){
  290. double c1 = getC();
  291. double t1 = getT();
  292. double f1 = getF();
  293. double c2 = arg.getC();
  294. double t2 = arg.getT();
  295. double f2 = arg.getF();
  296. double resT = 0.5, resF = 0.5, resC = 0;
  297. if (this.getN() != arg.getN())
  298. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  299. resF = f1 + f2 - f1*f2;
  300. if (almostEqual(resF, 0)) { //--------Modified by Debashis----------------//
  301. f1 = 0.99999;
  302. f2 = 0.99999;
  303. resF = f1 + f2 - f1*f2;
  304. resC = c1 + c2 - c1*c2- (c1*f2*(1-c2)*(1-t1)+c2*f1*(1-c1)*(1-t2)) / resF;
  305. }
  306. else
  307. resC = c1 + c2 - c1*c2 - (c1*f2*(1-c2)*(1-t1)+c2*f1*(1-c1)*(1-t2)) / resF;
  308. if (almostEqual(resC, 0))
  309. resT = 0.5;
  310. else resT = (1/resC) * (c1*t1 + c2*t2 - c1*c2*t1*t2);
  311. resT = adjustValue(resT);
  312. resC = adjustValue(resC);
  313. resF = adjustValue(resF);
  314. CertainTrust result = new CertainTrust(resT, resC, resF, n, 0);
  315. return result;
  316. }
  317. /**
  318. * Computes OR function for this CertainTrust object and the specified arguments.
  319. * Result is returned as a new object, arguments and this CertainTrust object remain unchanged.
  320. * Example: a.OR(b, c, d) returns new CertainTrust object that equals a OR b OR c OR d.
  321. * Multiple arguments allowed, but not less than one.
  322. * N values of all objects should be equal.
  323. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  324. * @param args - arguments
  325. * @return - result of OR computation for this object and all arguments.
  326. */
  327. public CertainTrust OR(CertainTrust ...args) {
  328. CertainTrust result = clone();
  329. for (CertainTrust m: args) {
  330. if (n != m.getN())
  331. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  332. result = result.OR(m);
  333. }
  334. return result;
  335. }
  336. /**
  337. * Computes AND function for this CertainTrust object and the specified argument. Result is returned as a new object,
  338. * argument and this CertainTrust object remain unchanged.
  339. * N values of both objects should be equal.
  340. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  341. * @param arg - CertainTrust object
  342. * @return - result of AND computation for this object and an argument.
  343. */
  344. private CertainTrust AND(CertainTrust arg){
  345. double c1 = getC();
  346. double f1 = getF();
  347. double t1 = getT();
  348. double c2 = arg.getC();
  349. double f2 = arg.getF();
  350. double t2 = arg.getT();
  351. double resC = 0, resT = 0.5, resF = 0.5;
  352. if (n != arg.getN())
  353. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  354. resF = f1*f2;
  355. if (almostEqual(resF, 1)) { //--------Modified by Debashis----------------//
  356. f1 = 0.99999;
  357. f2 = 0.99999;
  358. resF = f1*f2;
  359. resC = c1 + c2 - c1*c2- (c2*t2*(1-c1)*(1-f1)+c1*t1*(1-c2)*(1-f2)) / (1 - resF);
  360. }
  361. else
  362. resC = c1 + c2 - c1*c2 - (c2*t2*(1-c1)*(1-f1)+c1*t1*(1-c2)*(1-f2)) / (1 - resF);
  363. if (almostEqual(resC, 0))
  364. resT = 0.5;
  365. else if (almostEqual(resF, 1)) //avoid division by 0
  366. resT = (1/resC) * (c1*t1*c2*t2);
  367. else resT = (1/resC) * ((c1*t1*c2*t2) + (c1*f2*t1*(1-c2)*(1-f1)+c2*f1*t2*(1-c1)*(1-f2)) / (1 - resF));
  368. resT = adjustValue(resT);
  369. resC = adjustValue(resC);
  370. resF = adjustValue(resF);
  371. CertainTrust result = new CertainTrust(resT, resC, resF, n, 0);
  372. return result;
  373. }
  374. /**
  375. * Computes AND function for this CertainTrust object and the specified arguments.
  376. * Result is returned as a new object, arguments and this CertainTrust object remain unchanged.
  377. * Example: a.AND(b, c, d) returns new CertainTrust object that equals a AND b AND c AND d.
  378. * Multiple arguments allowed, but not less than one.
  379. * N values of all objects should be equal.
  380. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  381. * @param args - arguments
  382. * @return - result of AND computation for this object and all arguments.
  383. */
  384. public CertainTrust AND(CertainTrust ...args) {
  385. CertainTrust result = clone();
  386. for (CertainTrust m: args) {
  387. if (n != m.getN())
  388. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  389. result = result.AND(m);
  390. }
  391. return result;
  392. }
  393. /**
  394. * Returns NOT of this CertainTrust object.
  395. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  396. * @return - NOT of this CertainTrust object.
  397. */
  398. public CertainTrust NOT(){
  399. return new CertainTrust(getC(), adjustValue(1 - getT()), adjustValue(1 - getF()), n, 0);
  400. }
  401. /**
  402. * an internal implementation of fusion function.
  403. * Is called by wFusion and cFusion
  404. * @param args - an array of CertainTrust objects
  405. * @param weights - an integer array of corresponding weights
  406. * @param doc - a degree of conflict (always 0 for wFusion)
  407. * @return - new CertainTrust object
  408. */
  409. private static CertainTrust internalFusion(CertainTrust[] args, int[] weights, double doc) {
  410. double resC, resT, resF;
  411. boolean allOne = true;
  412. boolean allZero = true;
  413. boolean allWeightsZero = true;
  414. boolean atLeastOne1 = false;
  415. int arrLength = args.length;
  416. // set the flags about C and Weight values
  417. for (int i = 0; i < arrLength; i++)
  418. if (args[i].getC() != 1) {
  419. allOne = false;
  420. i = arrLength;
  421. }
  422. for (int i = 0; i < arrLength; i++)
  423. if (args[i].getC() != 0) {
  424. allZero = false;
  425. i = arrLength;
  426. }
  427. for (int i = 0; i < arrLength; i++)
  428. if (weights[i] != 0) {
  429. allWeightsZero = false;
  430. i = arrLength;
  431. }
  432. for (int i = 0; i < arrLength; i++)
  433. if (args[i].getC() == 1) {
  434. atLeastOne1 = true;
  435. i = arrLength;
  436. }
  437. //-------------Modified by Debashis-----------------//
  438. if(atLeastOne1 && !allOne){
  439. for (int i = 0; i < arrLength; ++i)
  440. if (args[i].getC() == 1) {
  441. args[i].setTC(args[i].getT(),0.99999);
  442. }
  443. }
  444. //Calculate T and C
  445. // 1. all C's = 1
  446. if (allOne) {
  447. // set C
  448. resC = 1 * (1 - doc);
  449. // set T
  450. if (allWeightsZero) {// save some calculation time
  451. resT = 0;
  452. }
  453. else { // or use the function
  454. double numeratorT = 0, denominatorT = 0;
  455. for (int i = 0; i < arrLength; i++) {
  456. numeratorT += weights[i] * args[i].getT();
  457. denominatorT += weights[i];
  458. }
  459. resT = numeratorT/denominatorT;
  460. }
  461. }
  462. else {
  463. if (atLeastOne1)
  464. throw new IllegalStateException("Illeagal arguments. Either all C values must equal 1 or none of them. Operation not allowed \n");
  465. // 2. Any other combination
  466. if (allWeightsZero) { // save some calculation time
  467. resT = 0;
  468. resC = 0;
  469. }
  470. else { // or use the function
  471. double numeratorT = 0, denominatorT = 0, numeratorC = 0, denominatorC = 0, mult;
  472. for (int i = 0; i < arrLength; i++) {
  473. mult = 1;
  474. for (int j = 0; j < arrLength; j++) // Count the product for each sum element
  475. if (j != i)
  476. mult *= 1 - args[j].getC();
  477. numeratorT += weights[i] * args[i].getT() * args[i].getC() * mult;
  478. denominatorT += weights[i] * args[i].getC() * mult;
  479. denominatorC += weights[i] * mult;
  480. }
  481. numeratorC = denominatorT;
  482. resC = (numeratorC/denominatorC) * (1 - doc);
  483. if (allZero)
  484. resT = 0.5;
  485. else
  486. resT = numeratorT/denominatorT;
  487. }
  488. // Special case for T
  489. if (allZero)
  490. resT = 0.5;
  491. }
  492. // Calculate F
  493. if (allWeightsZero)
  494. resF = 0;
  495. else {
  496. double numerator = 0, denominator = 0;
  497. for (int i = 0; i < arrLength; i ++) {
  498. numerator += weights[i] * args[i].getF();
  499. denominator += weights[i];
  500. }
  501. resF = numerator/denominator;
  502. }
  503. return new CertainTrust(resT, resC, resF, args[0].getN(), doc);
  504. }
  505. /**
  506. * Performs weighted fusion for an array of CertainTrust objects in correspondence with
  507. * an array of weights. Returns new CertainTrust object.
  508. * Requirements: N values of CertainTrust objects must be equal.
  509. * Number of weights should equal the number of CertainTrust objects.
  510. * Arrays must be non-empty
  511. * Either all of CertainTrust must be of certainty 1 or none of them.
  512. * @param args - an array of CertainTrust objects
  513. * @param weights - an integer array of corresponding weights
  514. * @return - new CertainTrust object
  515. */
  516. public static CertainTrust wFusion(CertainTrust[] args, int[] weights) {
  517. //arrays should be equal
  518. if (args.length == weights.length) {
  519. //and not empty
  520. if (args.length != 0) {
  521. boolean equalNs = true;
  522. int N = args[0].getN();
  523. for (int i = 1; i < args.length; i++)
  524. if (N != args[i].getN()) {
  525. equalNs = false;
  526. i = args.length;
  527. }
  528. //and all N's of TC's must be equal
  529. if (equalNs) {
  530. return internalFusion(args, weights, 0);
  531. }
  532. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  533. }
  534. throw new IllegalStateException("Arrays are empty. Operation not allowed. \n");
  535. }
  536. throw new IllegalStateException("Different lengths of arrays. Operation not allowed. \n");
  537. }
  538. /**
  539. * Conflicted Fusion is a variation of weighted fusion, which additionally computes the degree of conflict
  540. * between given opinions (CertainTrust objects) and takes it into consideration while performing fusion.
  541. * The degree of conflict is then saved in the resulting CertainTrust object and may be checked with getDoC() function.
  542. * @param args - an array of CertainTrust objects
  543. * @param weights - an integer array of corresponding weights
  544. * @return - new CertainTrust object
  545. */
  546. public static CertainTrust cFusion(CertainTrust[] args, int[] weights) {
  547. //arrays should be equal
  548. if (args.length == weights.length) {
  549. //and not empty
  550. if (args.length != 0) {
  551. boolean equalNs = true;
  552. int N = args[0].getN();
  553. for (int i = 1; i < args.length; i++)
  554. if (N != args[i].getN()) {
  555. equalNs = false;
  556. i = args.length;
  557. }
  558. //and all N's of TC's must be equal
  559. if (equalNs) {
  560. double denominator = args.length*(args.length - 1) / 2;
  561. double numerator = 0;
  562. for (int i = 0; i < args.length; i++)
  563. for (int j = i; j < args.length; j++)
  564. numerator += Math.abs(args[i].getT() - args[j].getT()) * args[i].getC() * args[j].getC()*(1 - Math.abs((double)(weights[i] - weights[j])/(weights[i] + weights[j])));
  565. double doc = numerator/denominator;
  566. return internalFusion(args, weights, doc);
  567. }
  568. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  569. }
  570. throw new IllegalStateException("Arrays are empty. Operation not allowed. \n");
  571. }
  572. throw new IllegalStateException("Different lengths of arrays. Operation not allowed. \n");
  573. }
  574. /**
  575. * Computes CONSENSUS function for this CertainTrust object and the specified argument. Result is returned as a new object,
  576. * argument and this CertainTrust object remain unchanged.
  577. * N values of both objects should be equal.
  578. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  579. * @param arg - CertainTrust object
  580. * @return - result of CONSENSUS computation for this object and an argument.
  581. */
  582. private CertainTrust CONSENSUS(CertainTrust arg){
  583. double c1 = getC();
  584. double f1 = getF();
  585. double t1 = getT();
  586. double c2 = arg.getC();
  587. double f2 = arg.getF();
  588. double t2 = arg.getT();
  589. double resC = 0, resT = 0.5, resF = 0.5;
  590. if (n != arg.getN())
  591. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  592. double tempC = c1*c2;
  593. if (this.almostEqual(tempC, 1)){ //avoid division by 0
  594. c1 = 0.99999;
  595. c2 = 0.99999;
  596. }
  597. resF = (f1*c1*(1-c2) + f2*c2*(1-c1))/(c1+c2-2*c1*c2);
  598. resC = (c1+c2-2*c1*c2)/(1-c1*c2);
  599. resT = (c1*t1*(1-c2)+c2*t2*(1-c1))/(c1+c2-2*c1*c2);
  600. resT = adjustValue(resT);
  601. resC = adjustValue(resC);
  602. resF = adjustValue(resF);
  603. CertainTrust result = new CertainTrust(resT, resC, resF, n, 0);
  604. return result;
  605. }
  606. /**
  607. * Computes CONSENSUS function for this CertainTrust object and the specified arguments.
  608. * Result is returned as a new object, arguments and this CertainTrust object remain unchanged.
  609. * Example: a.CONSENSUS(b, c, d) returns new CertainTrust object that equals a CONSENSUS b CONSENSUS c CONSENSUS d.
  610. * Multiple arguments allowed, but not less than one.
  611. * N values of all objects should be equal.
  612. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  613. * @param args - arguments
  614. * @return - result of CONSENSUS computation for this object and all arguments.
  615. */
  616. public CertainTrust CONSENSUS(CertainTrust ...args) {
  617. CertainTrust result = clone();
  618. for (CertainTrust m: args) {
  619. if (n != m.getN())
  620. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  621. result = result.CONSENSUS(m);
  622. }
  623. return result;
  624. }
  625. /**
  626. * Computes DISCOUNTING function for this CertainTrust object and the specified argument. Result is returned as a new object,
  627. * argument and this CertainTrust object remain unchanged.
  628. * N values of both objects should be equal.
  629. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  630. * @param arg - CertainTrust object
  631. * @return - result of DISCOUNTING computation for this object and an argument.
  632. */
  633. private CertainTrust DISCOUNTING(CertainTrust arg){
  634. double c1 = getC();
  635. double f1 = getF();
  636. double t1 = getT();
  637. double c2 = arg.getC();
  638. double f2 = arg.getF();
  639. double t2 = arg.getT();
  640. double resC = 0, resT = 0.5, resF = 0.5;
  641. if (n != arg.getN())
  642. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  643. resF = f2;
  644. if (almostEqual(resF, 1))
  645. resC = t1*c1*c2;
  646. else
  647. resC = t1*c1*c2;
  648. if (almostEqual(resC, 0))
  649. resT = 0.5;
  650. else if (almostEqual(resF, 1))
  651. resT = t2;
  652. else resT = t2;
  653. resT = adjustValue(resT);
  654. resC = adjustValue(resC);
  655. resF = adjustValue(resF);
  656. CertainTrust result = new CertainTrust(resT, resC, resF, n, 0);
  657. return result;
  658. }
  659. /**
  660. * Computes DISCOUNTING function for this CertainTrust object and the specified arguments.
  661. * Result is returned as a new object, arguments and this CertainTrust object remain unchanged.
  662. * Example: a.DISCOUNTING(b, c, d) returns new CertainTrust object that equals a DISCOUNTING b DISCOUNTING c DISCOUNTING d.
  663. * Multiple arguments allowed, but not less than one.
  664. * N values of all objects should be equal.
  665. * For detailed information see CertainLogic: A Logic for Modeling Trust and Uncertainty
  666. * @param args - arguments
  667. * @return - result of DISCOUNTING computation for this object and all arguments.
  668. */
  669. public CertainTrust DISCOUNTING(CertainTrust ...args) {
  670. CertainTrust result = clone();
  671. for (CertainTrust m: args) {
  672. if (n != m.getN())
  673. throw new IllegalStateException("Different N values. Operation not allowed. \n");
  674. result = result.DISCOUNTING(m);
  675. }
  676. return result;
  677. }
  678. //=========== Additional Functions =================
  679. @Override
  680. public CertainTrust clone() {
  681. CertainTrust copy = new CertainTrust(n);
  682. copy.c = this.c;
  683. copy.t = this.t;
  684. copy.f = this.f;
  685. copy.r = this.r;
  686. copy.s = this.s;
  687. copy.doc = this.doc;
  688. return copy;
  689. }
  690. /**
  691. * Adjusts the value of a into the allowed range [0,1].
  692. * @param a - value to be adjusted
  693. */
  694. private double adjustValue(double a) {
  695. return Math.max(Math.min(a, 1), 0);
  696. }
  697. /**
  698. * compares two double values using an epsilon
  699. * @param value - given value
  700. * @param target - expected value
  701. * @return
  702. */
  703. private boolean almostEqual(double value, double target) {
  704. return Math.abs(value - target) < 1E-10;
  705. }
  706. }