fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
180 lines • 14.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NFA = exports.emptyCode = void 0;
const DFA_1 = require("../DFA");
exports.emptyCode = "et";
/**
* A class to represent non-deterministic finite automata and their operations
*/
class NFA {
/**
* Creates a new nfa according to the given specification
* @param template The nfa template
*/
constructor(template) {
this.initialize(template);
}
/**
* Retrieves the character code of a given transition
* @param transition The transition to get a code for the transition character for
* @returns The character code
*/
getCharacterCode(transition) {
return transition.type == "character" && transition.character
? transition.character
: transition.type == "empty"
? exports.emptyCode
: DFA_1.remainingCode;
}
/**
* Initializes the NFA structure
* @param template The NFA template
*/
initialize(template) {
// Map each node to an index, since node IDs can be very long and therefore inefficient
const nodeMap = new Map(template.map((node, i) => [node.ID, i]));
this.nodes = template;
this.transitions = template.map((node, i) => Object.fromEntries(node.transitions.reduce((cur, trans) => {
const char = this.getCharacterCode(trans);
const group = cur.find(([i]) => i == char);
const node = nodeMap.get(trans.to);
if (group) {
group[1].push(node);
return cur;
}
else {
return [...cur, [char, [node]]];
}
}, [])));
// Extra data to perform a faster traced search
this.traceTransitions = template.map((node, i) => Object.fromEntries(node.transitions.reduce((cur, trans) => {
const char = this.getCharacterCode(trans);
const group = cur.find(([i]) => i == char);
const node = nodeMap.get(trans.to);
if (group) {
group[1].push({ state: node, metadata: trans.metadata });
return cur;
}
else {
return [
...cur,
[char, [{ state: node, metadata: trans.metadata }]],
];
}
}, [])));
// Get all the initial states, following empty transitions
const initial = template
.filter(node => node.initial)
.map(node => nodeMap.get(node.ID))
.filter((node) => node !== undefined);
if (initial.length == 0)
throw Error("Initial state can't be found");
this.initial = initial;
}
/**
* 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) {
let state = this.followEmptyTransitions(this.initial);
// Step through all characters
for (let i = 0; i < input.length; i++) {
const char = input[i];
const newState = [];
state.forEach(s => {
const transitions = this.transitions[s];
const charTrans = transitions[char];
let trans;
if (charTrans)
trans = charTrans;
else
trans = transitions[DFA_1.remainingCode] || [];
trans.forEach(t => {
if (!newState.includes(t))
newState.push(t);
});
});
state = this.followEmptyTransitions(newState);
}
// Return the result
return state.map(s => this.nodes[s].metadata);
}
/**
* Follows empty transitions from a node, and adds
* @param nodes The indices of the nodes for which to follow the empty transitions
* @returns The indices of all nodes reachable in 0 steps
*/
followEmptyTransitions(nodes) {
var _a;
const reachable = [...nodes];
for (let i = 0; i < reachable.length; i++) {
const node = reachable[i];
((_a = this.transitions[node][exports.emptyCode]) !== null && _a !== void 0 ? _a : []).forEach(nextNode => {
if (!reachable.includes(nextNode))
reachable.push(nextNode);
});
}
return reachable;
}
/**
* 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) {
let state = this.initial.map(node => ({ node, path: [] }));
// Step through all characters
for (let i = 0; i < input.length; i++) {
const char = input[i];
const newState = [];
state.forEach(({ node, path }) => {
const transitions = this.traceTransitions[node];
const charTrans = transitions[char];
let trans;
if (charTrans)
trans = charTrans;
else
trans = transitions[DFA_1.remainingCode] || [];
trans.forEach(({ state, metadata }) => {
newState.push({
node: state,
path: [...path, { node, transition: metadata }],
});
});
});
state = this.followEmptyTransitionsTraced(newState);
}
// Return the result
return state.map(({ node, path }) => ({
final: this.nodes[node].metadata,
path: path.map(({ node, transition }) => ({
fromNode: this.nodes[node].metadata,
transition,
})),
}));
}
/**
* Follows empty transitions from a node, and adds
* @param nodes The indices of the nodes for which to follow the empty transitions
* @returns The indices of all nodes reachable in 0 steps
*/
followEmptyTransitionsTraced(nodes) {
var _a;
const reachable = [...nodes];
for (let i = 0; i < reachable.length; i++) {
const { node, path } = reachable[i];
((_a = this.traceTransitions[node][exports.emptyCode]) !== null && _a !== void 0 ? _a : []).forEach(({ state, metadata }) => {
if (!reachable.find(({ node }) => node == state))
reachable.push({
node: state,
path: [...path, { node, transition: metadata }],
});
});
}
return reachable;
}
}
exports.NFA = NFA;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTkZBLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL05GQS9ORkEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsZ0NBQXFDO0FBRXhCLFFBQUEsU0FBUyxHQUFHLElBQUksQ0FBQztBQUU5Qjs7R0FFRztBQUNILE1BQWEsR0FBRztJQU9aOzs7T0FHRztJQUNILFlBQW1CLFFBQXNDO1FBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxnQkFBZ0IsQ0FBQyxVQUF1QztRQUM5RCxPQUFPLFVBQVUsQ0FBQyxJQUFJLElBQUksV0FBVyxJQUFJLFVBQVUsQ0FBQyxTQUFTO1lBQ3pELENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUztZQUN0QixDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksSUFBSSxPQUFPO2dCQUM1QixDQUFDLENBQUMsaUJBQVM7Z0JBQ1gsQ0FBQyxDQUFDLG1CQUFhLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7T0FHRztJQUNPLFVBQVUsQ0FBQyxRQUFzQztRQUN2RCx1RkFBdUY7UUFDdkYsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFakUsSUFBSSxDQUFDLEtBQUssR0FBRyxRQUFRLENBQUM7UUFDdEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQ3hDLE1BQU0sQ0FBQyxXQUFXLENBQ2QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDbkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGdC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