fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
128 lines • 12 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NFADFA = void 0;
const DFA_1 = require("../DFA");
const convertNFATemplateToDFATemplate_1 = require("./convertNFATemplateToDFATemplate");
const merge_1 = require("../../utils/merge");
/**
* A deterministic finite automata that emulates a non-deterministic finite automata.
* Note that depending on the input NFA, the setup time and automata size may be exponential.
* Execution time is always linear
*/
class NFADFA {
/**
* Creates a DFA equivalent to a given NFA template
* @param template The NFA template to create an DFA automata from
* @param getMeta Functions to add extra meta to the DFA nodes and transitions
*/
constructor(template, getMeta) {
this.initialize(template, getMeta);
}
/**
* Initializes the NFA structure
* @param template The NFA template
* @param getMeta Functions to add extra meta to the DFA nodes and transitions
*/
initialize(template, getMeta) {
const dfaTemplate = convertNFATemplateToDFATemplate_1.convertNFATemplateToDFATemplate(template, getMeta);
this.initNode = dfaTemplate.initial;
this.nodes = Object.fromEntries(template.map(v => [v.ID, v]));
this.DFA = new DFA_1.DFA(dfaTemplate);
}
/**
* Executes the NFA on the given input, and returns the metadata of the final node, if any
* @param input The input to execute the NFA on
* @returns The metadata of the states teh automaton finished in
*/
execute(input) {
const result = this.DFA.execute(input);
if (result)
return result.sources.map(s => s.metadata);
return [];
}
/**
* Executes the NFA on the given input, and returns the metadata of the DFA trace.
* @param input The input to execute the NFA on
* @returns The metadata of the states teh automaton finished in
*/
executeDFATraced(input) {
return this.DFA.executeTraced(input);
}
/**
* Executes the NFA on the given input, and returns the metadata of the trace.
* If multiple paths to the same final state exist, only a single path is returned
* @param input The input to execute the NFA on
* @returns The metadata of the states teh automaton finished in
*/
executeTraced(input) {
const result = this.DFA.executeTraced(input);
return result.final.sources.map(s => ({
final: s.metadata,
getPath: (getTransitionChooser = () => (to, transitions) => transitions.find(transition => transition.to == to.ID)) => {
const chooseTransition = getTransitionChooser(result);
const data = result.path.reduceRight(({ last, trace }, item, i) => {
if (!last)
return {};
// Get all transitions that lead to the correct next node
const sourceTransition = chooseTransition(last, item.transition.sources, i, this.nodes);
// Follow any empty transitions until a character transition was used
const transitionData = [];
let initTransition = sourceTransition;
while ((initTransition === null || initTransition === void 0 ? void 0 : initTransition.type) == "empty") {
transitionData.push({
fromNode: this.nodes[initTransition.from].metadata,
transition: initTransition.metadata,
});
initTransition = item.transition.sources.find(transition => transition.to == (initTransition === null || initTransition === void 0 ? void 0 : initTransition.from));
}
// Obtain a combination of previous node and transition leading to the next node
const source = item.fromNode.sources.find(s => s.ID == (initTransition === null || initTransition === void 0 ? void 0 : initTransition.from), null);
if (source && initTransition)
transitionData.push({
fromNode: source.metadata,
transition: initTransition.metadata,
});
// Store the proper data of the transition, and store the previous node
if (!source)
return {};
return {
trace: merge_1.merge(trace, transitionData),
last: source,
};
}, { trace: [], last: s });
if (data.trace) {
const trace = data.trace;
// We might have finished at one of the nodes reachable in 0 steps from the initial node, instead of the initial node itself
const last = data.last;
if (!last.initial) {
const transitions = [].concat(...result.path[0].fromNode.sources.map(source => source.transitions.map(transition => ({
...transition,
from: source.ID,
}))));
const sourceTransition = chooseTransition(last, transitions, -1, this.nodes);
// Follow any empty transitions until a character transition was used
const transitionData = [];
let initTransition = sourceTransition;
while ((initTransition === null || initTransition === void 0 ? void 0 : initTransition.type) == "empty") {
transitionData.push({
fromNode: this.nodes[initTransition.from].metadata,
transition: initTransition.metadata,
});
initTransition = transitions.find(transition => transition.to == (initTransition === null || initTransition === void 0 ? void 0 : initTransition.from));
}
trace.push(...transitionData);
}
// Map the transition metadata to the correct format
return trace.reverse();
}
else {
// I don't think this can occur, but I'm not positive, so this is a safe-ish failure case
console.error("Didn't manage to find a path", input, s);
return [];
}
},
}));
}
}
exports.NFADFA = NFADFA;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTkZBREZBLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL0RGQS9ORkFERkEvTkZBREZBLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUtBLGdDQUEyQjtBQUUzQix1RkFBa0Y7QUFJbEYsNkNBQXdDO0FBRXhDOzs7O0dBSUc7QUFDSCxNQUFhLE1BQU07SUFLZjs7OztPQUlHO0lBQ0gsWUFDSSxRQUFzQyxFQUN0QyxPQUEwQztRQUUxQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNPLFVBQVUsQ0FDaEIsUUFBc0MsRUFDdEMsT0FBMEM7UUFFMUMsTUFBTSxXQUFXLEdBQUcsaUVBQStCLENBQy9DLFFBQVEsRUFDUixPQUEyQyxDQUM5QyxDQUFDO1FBQ0YsSUFBSSxDQUFDLFFBQVEsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksU0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksT0FBTyxDQUFDLEtBQWE7UUFDeEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkMsSUFBSSxNQUFNO1lBQUUsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2RCxPQUFPLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksZ0JB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