UNPKG

metagraph

Version:

A framework for building higher-order graph data structures

127 lines (122 loc) 4.75 kB
/*! * metagraph.js <%= conf.pkg.version %> * http://gordonwoodhull.github.io/metagraph.js/ * Copyright 2019 AT&T Intellectual Property * * Licensed under the MIT License * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ import { as_array } from './core.js'; import { topological_sort } from './topological_sort.js'; import { graph_detect } from './graph.js'; import { pattern } from './pattern.js'; /** * Composes multiple graph patterns into a single unified pattern. * Resolves dependencies between patterns and creates a combined interface. * * @param composition - A graph where nodes are patterns and edges define dependencies * @returns A composed pattern that combines all input patterns * * @example * ```typescript * const comp = compose(graph_detect({ * nodes: { * graph: graph_pattern(), * subgraph: subgraph_pattern() * }, * edges: { * dependency: {source: 'graph', target: 'subgraph', input: 'parent'} * } * })); * ``` */ const compose = (composition) => { const sorted = topological_sort(composition); const built = {}; const flowspecs = {}; const input_edge = (patnode, name) => patnode.ins().find((pe) => pe.value().input === name); // resolve dependencies and build patterns sorted.forEach(patnode => { const flowspec = graph_detect(patnode.value().dataflow); const fnodes = flowspec.nodes().map(fn => { const v2 = Object.assign({}, fn.value()); v2.refs = as_array(v2.refs).map((ref) => { const parts = ref.split('.'); if (parts.length > 1) { const patedge = input_edge(patnode, parts[0]); return patedge.source().key() + '.' + parts[1]; } else return patnode.key() + '.' + parts[0]; }); return { key: fn.key(), value: v2 }; }); const fedges = flowspec.edges().map(e => ({ key: e.key(), value: e.value() })); flowspecs[patnode.key()] = graph_detect({ nodes: fnodes, edges: fedges }); const interf = patnode.value().interface; built[patnode.key()] = graph_detect({ nodes: interf.nodes, edges: interf.edges }); }); // unite patterns const nodes = []; const edges = []; const mappings = {}; const lookup = (key) => mappings[key] || key; sorted.forEach(patnode => { const pattern = built[patnode.key()]; pattern.nodes().forEach(inode => { const key = patnode.key() + '.' + inode.key(); const ref = as_array(inode.value()).find((spec) => typeof spec === 'string'); if (ref) { const parts = ref.split('.'); const patedge = input_edge(patnode, parts[0]); const key2 = lookup(patedge.source().key() + '.' + parts[1]); mappings[key] = key2; } else nodes.push({ key: key, value: inode.value() }); }); pattern.edges().forEach(iedge => { const val2 = Object.assign({}, iedge.value()); val2.source = lookup(patnode.key() + '.' + iedge.source().key()); val2.target = lookup(patnode.key() + '.' + iedge.target().key()); edges.push({ key: patnode.key() + '.' + iedge.key(), value: val2 }); }); }); return pattern({ interface: { nodes, edges } }, flowspecs); }; export { compose }; //# sourceMappingURL=compose.js.map