export type Graph = { vertices: { [v: string]: V }, edges: { [v: string]: Set } } export type AddVertex = (name: string, v: V) => void export type AddEdge = (source: string, dest: string) => void export const createGraph = (cons: (v: AddVertex, e: AddEdge) => void): Graph => { const g: Graph = { vertices: {}, edges: {} } const addVertex = (name: string, v: V) => { g.vertices[name] = v g.edges[name] = new Set() } const addEdge = (source: string, dest: string) => { if (typeof g.vertices[source] === "undefined") { throw new Error(`vertex \`${source}' does not exist in graph`) } else if (typeof g.vertices[dest] === "undefined") { throw new Error(`vertex \`${dest}' does not exist in graph`) } g.edges[source].add(dest) g.edges[dest].add(source) } cons(addVertex, addEdge) return g } export const neighbors = (g: Graph, name: string): Set => { if (typeof g.vertices[name] === "undefined") { throw new Error(`vertex \`${name}' does not exist in graph`) } return g.edges[name] } export const vertices = (g: Graph): Set => new Set(Object.keys(g.vertices)) export const maxCardinalitySearch = (g: Graph): Array => { const weights: { [s: string]: number } = {} const ordering: Array = [] let W = vertices(g) const numVertices = W.size for (let i = 0; i < numVertices; ++i) { const v = findMaxWeight(weights, W) ordering.push(v) setIntersect(W, neighbors(g, v)).forEach(x => weights[x] = (weights[x] || 0) + 1 ) W.delete(v) } return ordering } const findMaxWeight = (weights: { [s: string]: number }, W: Set): string => { let maxV = null let maxWeight = -Infinity W.forEach(v => { const vWeight = weights[v] || 0 if (vWeight > maxWeight) { maxV = v maxWeight = vWeight } }) if (maxV === null) { throw new Error(`remaining vertex set is empty`) } return maxV } const setIntersect = (xs: Set, ys: Set): Set => { const intersection: Set = new Set() xs.forEach(x => { if (ys.has(x)) { intersection.add(x) } }) return intersection }