|
@ -1,6 +1,8 @@ |
|
|
import { intersect } from "./set" |
|
|
import { intersect } from "./set" |
|
|
|
|
|
|
|
|
export type Graph<V> = { |
|
|
export type Graph<V> = { |
|
|
|
|
|
numVertices: number, |
|
|
|
|
|
numEdges: number, |
|
|
vertices: { |
|
|
vertices: { |
|
|
[v: string]: V |
|
|
[v: string]: V |
|
|
}, |
|
|
}, |
|
@ -13,11 +15,12 @@ export type AddVertex = (name: string, v: V) => void |
|
|
export type AddEdge = (source: string, dest: string) => void |
|
|
export type AddEdge = (source: string, dest: string) => void |
|
|
|
|
|
|
|
|
export const createGraph = <V>(cons: (v: AddVertex<V>, e: AddEdge) => void): Graph<V> => { |
|
|
export const createGraph = <V>(cons: (v: AddVertex<V>, e: AddEdge) => void): Graph<V> => { |
|
|
const g: Graph<V> = { vertices: {}, edges: {} } |
|
|
|
|
|
|
|
|
const g: Graph<V> = { numVertices: 0, numEdges: 0, vertices: {}, edges: {} } |
|
|
|
|
|
|
|
|
const addVertex = (name: string, v: V) => { |
|
|
const addVertex = (name: string, v: V) => { |
|
|
g.vertices[name] = v |
|
|
g.vertices[name] = v |
|
|
g.edges[name] = new Set() |
|
|
g.edges[name] = new Set() |
|
|
|
|
|
g.numVertices++ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const addEdge = (source: string, dest: string) => { |
|
|
const addEdge = (source: string, dest: string) => { |
|
@ -29,6 +32,7 @@ export const createGraph = (cons: (v: AddVertex, e: AddEdge) => void): Gra |
|
|
|
|
|
|
|
|
g.edges[source].add(dest) |
|
|
g.edges[source].add(dest) |
|
|
g.edges[dest].add(source) |
|
|
g.edges[dest].add(source) |
|
|
|
|
|
g.numEdges++ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
cons(addVertex, addEdge) |
|
|
cons(addVertex, addEdge) |
|
@ -85,3 +89,47 @@ const findMaxWeight = (weights: { [s: string]: number }, W: Set): string |
|
|
|
|
|
|
|
|
return maxV |
|
|
return maxV |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export type GraphColoring = { |
|
|
|
|
|
numColors: number, |
|
|
|
|
|
colors: VertexColoring, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export type VertexColoring = { |
|
|
|
|
|
[s: string]: number, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const colorGreedy = <V>(g: Graph<V>, vertexOrdering: Array<string>): GraphColoring => { |
|
|
|
|
|
if (vertexOrdering.length !== g.numVertices) { |
|
|
|
|
|
throw new Error("ordering does not cover all vertices") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const coloring: GraphColoring = { numColors: 0, colors: {} } |
|
|
|
|
|
const usedColors = {} |
|
|
|
|
|
|
|
|
|
|
|
vertexOrdering.forEach(v => { |
|
|
|
|
|
const ns = neighbors(g, v) |
|
|
|
|
|
|
|
|
|
|
|
let color = 0 |
|
|
|
|
|
while (!colorAvailable(color, ns, coloring.colors)) { |
|
|
|
|
|
color++ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
coloring.colors[v] = color |
|
|
|
|
|
usedColors[color] = true |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
coloring.numColors = Object.keys(usedColors).length |
|
|
|
|
|
return coloring |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const colorAvailable = (color: number, neighbors: Set<string>, colors: VertexColoring): boolean => { |
|
|
|
|
|
// TODO: Why can't I just iterate over neighbors directly...?
|
|
|
|
|
|
for (const nbor of Array.from(neighbors)) { |
|
|
|
|
|
if (colors[nbor] === color) { |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true |
|
|
|
|
|
} |