fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
159 lines • 12.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNodesFromIDs = exports.createID = exports.getReachableNodes = exports.getAvailableTransitionCharacter = exports.getRemainingTransition = exports.getCharacterTransition = exports.convertNFATemplateToDFATemplate = void 0;
/**
* Converts the nfa input to a dfa input
* @param nodes The nodes for a nfa automaton
* @returns The dfa equivalent automaton template
*/
function convertNFATemplateToDFATemplate(nodes) {
const nodeMap = new Map(nodes.map(node => [node.ID, node]));
const outMap = new Map();
// Get the initial nodes
const initNodes = getReachableNodes(nodeMap, nodes.filter(({ initial }) => initial));
const initState = createID(initNodes);
// Iteratively keep adding nodes and their transitions
const stack = [initNodes];
let set;
while ((set = stack.shift())) {
const nodes = set;
// First make sure the node doesn't exist yet
const ID = createID(nodes);
if (outMap.has(ID))
continue;
// Figure out all transitions
const transitionChars = getAvailableTransitionCharacter(nodes);
const characterTransitions = transitionChars.map(char => {
const { transition, to } = getCharacterTransition(nodeMap, nodes, char);
stack.push(to);
return transition;
});
const { transition: remainingTransition, to } = getRemainingTransition(nodeMap, nodes);
stack.push(to);
// Create and store the node
const node = {
ID,
transitions: [...characterTransitions, remainingTransition],
metadata: { sources: nodes },
};
outMap.set(ID, node);
}
// Return the dfa template
return { nodes: Array.from(outMap.values()), initial: initState };
}
exports.convertNFATemplateToDFATemplate = convertNFATemplateToDFATemplate;
/**
* Creates a transition, given a character and the node sets to transition from
* @param template All the nfa input nodes
* @param nodes The current state
* @param char The character to transition on
* @returns The transition for this character
*/
function getCharacterTransition(template, nodes, char) {
const transitions = [];
// Obtain the transitions for each node for this character
nodes.forEach(node => {
const charTransitions = node.transitions.filter(({ type, character }) => type == "character" && character == char);
if (charTransitions.length > 0) {
transitions.push(...charTransitions);
}
else {
const otherTransitions = node.transitions.filter(({ type }) => type == "remaining");
transitions.push(...otherTransitions);
}
});
// Get the ID of the end of the transition
const toNodesDirect = transitions.map(transition => transition.to);
const toNodes = getReachableNodes(template, getNodesFromIDs(template, toNodesDirect));
const to = createID(toNodes);
// Construct the transition
return {
transition: {
to,
type: "character",
character: char,
metadata: { sources: transitions },
},
to: toNodes,
};
}
exports.getCharacterTransition = getCharacterTransition;
/**
* Retrieves the transition for all characters for which no specific transition exists
* @param template All the nfa input nodes
* @param nodes The current state
* @returns The transition for the remaining characters
*/
function getRemainingTransition(template, nodes) {
const transitions = [];
// Obtain the transitions for each node for this character
nodes.forEach(node => {
const remainingTransitions = node.transitions.filter(({ type }) => type == "remaining");
transitions.push(...remainingTransitions);
});
// Get the ID of the end of the transition
const toNodesDirect = transitions.map(transition => transition.to);
const toNodes = getReachableNodes(template, getNodesFromIDs(template, toNodesDirect));
const to = createID(toNodes);
// Construct the transition
return {
transition: {
to,
type: "remaining",
metadata: { sources: transitions },
},
to: toNodes,
};
}
exports.getRemainingTransition = getRemainingTransition;
/**
* Retrieves the transition characters found in the given set of nodes
* @param nodes The nodes in which to look for transition characters
* @returns The transition character set
*/
function getAvailableTransitionCharacter(nodes) {
return Array.from(new Set(nodes
.flatMap(({ transitions }) => transitions)
.filter(({ type }) => type == "character")
.map(({ character }) => character)
.filter((char) => !!char)));
}
exports.getAvailableTransitionCharacter = getAvailableTransitionCharacter;
/**
* Checks what nodes are reachable with the given set, by using empty transitions
* @param template All the nfa input nodes
* @param nodes The nodes to get the closure of, (may include duplicates, which will be removed)
* @returns The reach of these nodes
*/
function getReachableNodes(template, nodes) {
const reachableNodes = new Set(nodes);
for (let node of reachableNodes) {
const emptyTransitions = node.transitions.filter(({ type }) => type == "empty");
const transitionNodes = getNodesFromIDs(template, emptyTransitions.map(({ to }) => to));
transitionNodes.forEach(node => reachableNodes.add(node));
}
return Array.from(reachableNodes);
}
exports.getReachableNodes = getReachableNodes;
/**
* Creates an ID to uniquely define a set of nodes, no matter what the order is
* @param nodes The nodes to create the ID for
* @returns The created ID
*/
function createID(nodes) {
const IDs = nodes.map(node => (typeof node == "string" ? node : node.ID));
const sorted = IDs.sort();
return `{${sorted.join(",")}}`;
}
exports.createID = createID;
/**
* Retrieves nodes given the list of IDs
* @param map The map of items that the nodes are in
* @param IDs The IDs of the nodes to retrieve
* @returns The nodes
*/
function getNodesFromIDs(map, IDs) {
return IDs.map(ID => map.get(ID)).filter((n) => !!n);
}
exports.getNodesFromIDs = getNodesFromIDs;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVydE5GQVRlbXBsYXRlVG9ERkFUZW1wbGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ERkEvY29udmVydE5GQVRlbXBsYXRlVG9ERkFUZW1wbGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFPQTs7OztHQUlHO0FBQ0gsU0FBZ0IsK0JBQStCLENBQzNDLEtBQW1DO0lBRW5DLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxDQUNuQixLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQ3JDLENBQUM7SUFDRixNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBNkIsQ0FBQztJQUVwRCx3QkFBd0I7SUFDeEIsTUFBTSxTQUFTLEdBQUcsaUJBQWlCLENBQy9CLE9BQU8sRUFDUCxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBQyxPQUFPLEVBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQ3ZDLENBQUM7SUFDRixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFdEMsc0RBQXNEO0lBQ3RELE1BQU0sS0FBSyxHQUFpQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3hELElBQUksR0FBMkMsQ0FBQztJQUNoRCxPQUFPLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFO1FBQzFCLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQztRQUVsQiw2Q0FBNkM7UUFDN0MsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNCLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFBRSxTQUFTO1FBRTdCLDZCQUE2QjtRQUM3QixNQUFNLGVBQWUsR0FBRywrQkFBK0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUvRCxNQUFNLG9C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