UNPKG

human-logic

Version:
326 lines 14.7 kB
"use strict"; /** * Fuzzy Common Sense Logic * * Human Logic (also known as “common sense”) is based on five categories: * - `true` = certainly positive * - `false` = certainly negative * - `maybe` = uncertain (could be either positive or negative) * - `never` = impossible (neither positive nor negative) * - `undefined` = totally unknown * * In Fuzzy Common Sense Logic the value is five-dimensional unit vector. * Each vector component is a fuzzy value (between 0.0 and 1.0 inclusive) * of respective `true`, `false`, `maybe`, `never` or `undefined` category. * @module */ Object.defineProperty(exports, "__esModule", { value: true }); exports.normalize = exports.or = exports.and = exports.not = exports.Logic = void 0; var tslib_1 = require("tslib"); /** @hidden */ var Fuzzy_1 = require("./Fuzzy"); /** @hidden */ var Category_1 = require("./Category"); /** * Main Fuzzy Common Sense Logic Class */ var Logic = /** @class */ (function () { /** * Basic constructor. See {@link fromCategory}, {@link fromArray} and {@link fromValues} * for more convenient instantiation methods. */ function Logic(_undef, _false, _never, _maybe, _true) { var _a; this.values = (_a = {}, _a[Category_1.UNDEF] = _undef || Fuzzy_1.FUZZY_FALSE, _a[Category_1.FALSE] = _false || Fuzzy_1.FUZZY_FALSE, _a[Category_1.NEVER] = _never || Fuzzy_1.FUZZY_FALSE, _a[Category_1.MAYBE] = _maybe || Fuzzy_1.FUZZY_FALSE, _a[Category_1.TRUE] = _true || Fuzzy_1.FUZZY_FALSE, _a); } /** * Creates new {@link Logic} instance with {@link Fuzzy.FUZZY_TRUE} value for the specified `category` * (and {@link Fuzzy.FUZZY_FALSE} for all other categories). */ Logic.fromCategory = function (category) { return new Logic(category === Category_1.UNDEF ? Fuzzy_1.FUZZY_TRUE : Fuzzy_1.FUZZY_FALSE, category === Category_1.FALSE ? Fuzzy_1.FUZZY_TRUE : Fuzzy_1.FUZZY_FALSE, category === Category_1.NEVER ? Fuzzy_1.FUZZY_TRUE : Fuzzy_1.FUZZY_FALSE, category === Category_1.MAYBE ? Fuzzy_1.FUZZY_TRUE : Fuzzy_1.FUZZY_FALSE, category === Category_1.TRUE ? Fuzzy_1.FUZZY_TRUE : Fuzzy_1.FUZZY_FALSE); }; /** * Creates new {@link Logic} instance from array of {@link Fuzzy} values. * @param fuzzy The categories order in array is: {@link Category.UNDEF}, {@link Category.FALSE}, * {@link Category.NEVER}, {@link Category.MAYBE}, {@link Category.TRUE}. */ Logic.fromArray = function (fuzzy) { return new Logic(fuzzy[0], fuzzy[1], fuzzy[2], fuzzy[3], fuzzy[4]); }; /** * Creates new {@link Logic} instance from {@link LogicValues}. */ Logic.fromValues = function (fuzzy) { return new Logic(fuzzy.UNDEF, fuzzy.FALSE, fuzzy.NEVER, fuzzy.MAYBE, fuzzy.TRUE); }; /** * Retrieves an array of {@link Fuzzy} values. * @return The categories order in array is: {@link Category.UNDEF}, {@link Category.FALSE}, * {@link Category.NEVER}, {@link Category.MAYBE}, {@link Category.TRUE}. */ Logic.prototype.asArray = function () { return [ this.values[Category_1.UNDEF], this.values[Category_1.FALSE], this.values[Category_1.NEVER], this.values[Category_1.MAYBE], this.values[Category_1.TRUE] ]; }; /** * Dominating {@link Category} or `undefined` if none of the categories * has a value greater than {@link Fuzzy.FUZZY_FALSE}. */ Logic.prototype.asCategory = function () { var result = Category_1.UNDEF; if (this.values[result] < this.values[Category_1.FALSE]) result = Category_1.FALSE; if (this.values[result] < this.values[Category_1.NEVER]) result = Category_1.NEVER; if (this.values[result] < this.values[Category_1.MAYBE]) result = Category_1.MAYBE; if (this.values[result] < this.values[Category_1.TRUE]) result = Category_1.TRUE; return this.values[result] > Fuzzy_1.FUZZY_FALSE ? result : undefined; }; /** * Retrieves a copy of {@link LogicValues}. * @return A clone, a new instance of {@link LogicValues} created from the values kept internally. */ Logic.prototype.asValues = function () { return tslib_1.__assign({}, this.values); }; Logic.prototype.getValues = function () { return this.values; }; /** * Creates a deep copy (a clone) of a current instance. */ Logic.prototype.clone = function () { return new Logic(this.values[Category_1.UNDEF], this.values[Category_1.FALSE], this.values[Category_1.NEVER], this.values[Category_1.MAYBE], this.values[Category_1.TRUE]); }; /** * String representation of five-dimensional vector of {@link Fuzzy} values. * The categories order is: {@link Category.UNDEF}, {@link Category.FALSE}, {@link Category.NEVER}, * {@link Category.MAYBE}, {@link Category.TRUE}. */ Logic.prototype.toString = function () { return "(".concat(this.asArray() .map(function (val) { return val.toFixed(2); }) .join(','), ")"); }; /** * Returns {@link Fuzzy} value of the specified category of this {@link Logic} object. */ Logic.prototype.get = function (category) { return this.values[category]; }; Logic.prototype.scalar = function () { return (this.values[Category_1.UNDEF] + this.values[Category_1.FALSE] + this.values[Category_1.NEVER] + this.values[Category_1.MAYBE] + this.values[Category_1.TRUE]); }; Logic.prototype.normalizer = function () { return this.scalar() || Fuzzy_1.FUZZY_TRUE; }; /** * Returns normalized {@link Fuzzy} value for the specified category. See {@link normalize} for details. */ Logic.prototype.getNormalized = function (category) { return this.values[category] / this.normalizer(); }; /** * If original values are not normalized, returns new Logic object with normalized {@link Logic} value, * otherwise return the same object. * * The {@link Logic} value is normalized if and only if the sum of {@link Fuzzy} values of all categories * equals to `1.0` (or `0.0` if there are no categories with {@link Fuzzy} value greater than * {@link Fuzzy.FUZZY_FALSE}). */ Logic.prototype.normalize = function () { var normalizer = this.normalizer(); return Math.abs(normalizer - Fuzzy_1.FUZZY_TRUE) < 1e-8 ? this : this.multiply(Fuzzy_1.FUZZY_TRUE / normalizer); }; /** * Checks that at least one of the categories has non-zero {@link Fuzzy} value. */ Logic.prototype.isValid = function () { return this.scalar() > Fuzzy_1.FUZZY_FALSE; }; /** * Fuzzy Common Sense Logical NOT. See [README](../index.html#fuzzy-common-sense-logic) for details. */ Logic.prototype.not = function () { return new Logic( // UNDEF: this.values[Category_1.UNDEF], // FALSE: this.values[Category_1.TRUE], // NEVER: this.values[Category_1.MAYBE], // MAYBE: this.values[Category_1.NEVER], // TRUE: this.values[Category_1.FALSE]); }; /** * Fuzzy Common Sense Logical AND. See [README](../index.html#fuzzy-common-sense-logic) for details. */ Logic.prototype.and = function (value) { if (!value || !(value instanceof Logic)) throw new TypeError('Invalid argument type'); var values = value.getValues(); var undef = (0, Fuzzy_1.or)(this.values[Category_1.UNDEF], values[Category_1.UNDEF]); var notUndef = (0, Fuzzy_1.not)(undef); return new Logic( // UNDEF: undef, // FALSE: (0, Fuzzy_1.and)(notUndef, (0, Fuzzy_1.or)(this.values[Category_1.FALSE], values[Category_1.FALSE], (0, Fuzzy_1.and)(this.values[Category_1.MAYBE], values[Category_1.NEVER]), (0, Fuzzy_1.and)(this.values[Category_1.NEVER], values[Category_1.MAYBE]))), // NEVER: (0, Fuzzy_1.and)(notUndef, (0, Fuzzy_1.or)((0, Fuzzy_1.and)(this.values[Category_1.NEVER], values[Category_1.NEVER]), (0, Fuzzy_1.and)(this.values[Category_1.NEVER], values[Category_1.TRUE]), (0, Fuzzy_1.and)(this.values[Category_1.TRUE], values[Category_1.NEVER]))), // MAYBE: (0, Fuzzy_1.and)(notUndef, (0, Fuzzy_1.or)((0, Fuzzy_1.and)(this.values[Category_1.MAYBE], values[Category_1.MAYBE]), (0, Fuzzy_1.and)(this.values[Category_1.MAYBE], values[Category_1.TRUE]), (0, Fuzzy_1.and)(this.values[Category_1.TRUE], values[Category_1.MAYBE]))), // TRUE: (0, Fuzzy_1.and)(notUndef, this.values[Category_1.TRUE], values[Category_1.TRUE])).normalize(); }; /** * Fuzzy Common Sense Logical OR. See [README](../index.html#fuzzy-common-sense-logic) for details. */ Logic.prototype.or = function (value) { if (!value || !(value instanceof Logic)) throw new TypeError('Invalid argument type'); var values = value.getValues(); var undef = (0, Fuzzy_1.or)(this.values[Category_1.UNDEF], values[Category_1.UNDEF]); var notUndef = (0, Fuzzy_1.not)(undef); return new Logic( // UNDEF: undef, // FALSE: (0, Fuzzy_1.and)(notUndef, this.values[Category_1.FALSE], values[Category_1.FALSE]), // NEVER: (0, Fuzzy_1.and)(notUndef, (0, Fuzzy_1.or)((0, Fuzzy_1.and)(this.values[Category_1.NEVER], values[Category_1.NEVER]), (0, Fuzzy_1.and)(this.values[Category_1.NEVER], values[Category_1.FALSE]), (0, Fuzzy_1.and)(this.values[Category_1.FALSE], values[Category_1.NEVER]))), // MAYBE: (0, Fuzzy_1.and)(notUndef, (0, Fuzzy_1.or)((0, Fuzzy_1.and)(this.values[Category_1.MAYBE], values[Category_1.MAYBE]), (0, Fuzzy_1.and)(this.values[Category_1.MAYBE], values[Category_1.FALSE]), (0, Fuzzy_1.and)(this.values[Category_1.FALSE], values[Category_1.MAYBE]))), // TRUE: (0, Fuzzy_1.and)(notUndef, (0, Fuzzy_1.or)(this.values[Category_1.TRUE], values[Category_1.TRUE], (0, Fuzzy_1.and)(this.values[Category_1.MAYBE], values[Category_1.NEVER]), (0, Fuzzy_1.and)(this.values[Category_1.NEVER], values[Category_1.MAYBE])))).normalize(); }; /** * Adds `value` to current value (category by category). * Useful for accumulation of fuzzy sums (usually with normalization in the end). * Mutates the current object. * @return Mutated `this` object. */ Logic.prototype.add = function (value) { if (!value || !(value instanceof Logic)) throw new TypeError('Invalid argument type'); var values = value.getValues(); this.values[Category_1.UNDEF] += values[Category_1.UNDEF]; this.values[Category_1.FALSE] += values[Category_1.FALSE]; this.values[Category_1.NEVER] += values[Category_1.NEVER]; this.values[Category_1.MAYBE] += values[Category_1.MAYBE]; this.values[Category_1.TRUE] += values[Category_1.TRUE]; return this; }; Logic.prototype.multiply = function (value) { return new Logic( // UNDEF: this.values[Category_1.UNDEF] * value, // FALSE: this.values[Category_1.FALSE] * value, // NEVER: this.values[Category_1.NEVER] * value, // MAYBE: this.values[Category_1.MAYBE] * value, // TRUE: this.values[Category_1.TRUE] * value); }; /** * Returns `true` if `category` is the dominating category of this object. */ Logic.prototype.eq = function (category) { return ((category === Category_1.UNDEF || this.values[category] > this.values[Category_1.UNDEF]) && (category === Category_1.FALSE || this.values[category] > this.values[Category_1.FALSE]) && (category === Category_1.NEVER || this.values[category] > this.values[Category_1.NEVER]) && (category === Category_1.MAYBE || this.values[category] > this.values[Category_1.MAYBE]) && (category === Category_1.TRUE || this.values[category] > this.values[Category_1.TRUE])); }; /** * Returns `true` if `category` is **not** the dominating category of this object. */ Logic.prototype.ne = function (category) { return ((category !== Category_1.UNDEF && this.values[category] <= this.values[Category_1.UNDEF]) || (category !== Category_1.FALSE && this.values[category] <= this.values[Category_1.FALSE]) || (category !== Category_1.NEVER && this.values[category] <= this.values[Category_1.NEVER]) || (category !== Category_1.MAYBE && this.values[category] <= this.values[Category_1.MAYBE]) || (category !== Category_1.TRUE && this.values[category] <= this.values[Category_1.TRUE])); }; return Logic; }()); exports.Logic = Logic; /** * Fuzzy Common Sense NOT (global function). * Allows to use different code styles, e.g.: * ```JavaScript * const valueA = value.not(); * const valueB = not(value); * ``` * See [README](../index.html#fuzzy-common-sense-logic) for details. */ function not(value) { if (value && value instanceof Logic) return value.not(); throw new TypeError('Invalid argument type'); } exports.not = not; /** * Fuzzy Common Sense AND (global function). * Allows to use different code styles, e.g.: * ```JavaScript * const valueA = value1.and(value2); * const valueB = and(value1, value2); * ``` * See [README](../index.html#fuzzy-common-sense-logic) for details. */ function and(a, b) { if (a && a instanceof Logic) return a.and(b); throw new TypeError('Invalid argument type'); } exports.and = and; /** * Fuzzy Common Sense OR (global function). * Allows to use different code styles, e.g.: * ```JavaScript * const valueA = value1.or(value2); * const valueB = or(value1, value2); * ``` * See [README](../index.html#fuzzy-common-sense-logic) for details. */ function or(a, b) { if (a && a instanceof Logic) return a.or(b); throw new TypeError('Invalid argument type'); } exports.or = or; /** * Fuzzy Common Sense logical value normalization (global function). * Allows to use different code styles, e.g.: * ```JavaScript * const valueA = value.normalize(); * const valueB = normalize(value); * ``` * See {@link Logic.normalize} for details. */ function normalize(value) { if (value && value instanceof Logic) return value.normalize(); throw new TypeError('Invalid argument type'); } exports.normalize = normalize; //# sourceMappingURL=Logic.js.map