Browse Source

Add function for coloring graphs

master
Forest Belton 3 years ago
parent
commit
7454efddee
2 changed files with 68 additions and 2 deletions
  1. +49
    -1
      lib/data/graph.ts
  2. +19
    -1
      test/data/graph.spec.ts

+ 49
- 1
lib/data/graph.ts View File

@ -1,6 +1,8 @@
import { intersect } from "./set"
export type Graph<V> = {
numVertices: number,
numEdges: number,
vertices: {
[v: string]: V
},
@ -13,11 +15,12 @@ export type AddVertex = (name: string, v: V) => void
export type AddEdge = (source: string, dest: string) => void
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) => {
g.vertices[name] = v
g.edges[name] = new Set()
g.numVertices++
}
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[dest].add(source)
g.numEdges++
}
cons(addVertex, addEdge)
@ -85,3 +89,47 @@ const findMaxWeight = (weights: { [s: string]: number }, W: Set): string
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
}

+ 19
- 1
test/data/graph.spec.ts View File

@ -1,6 +1,6 @@
import { expect } from "chai"
import { createGraph, neighbors, vertices } from "../../lib/data/graph"
import { colorGreedy, createGraph, neighbors, vertices } from "../../lib/data/graph"
const g = createGraph((v, e) => {
v("a", true)
@ -37,4 +37,22 @@ describe("graph", () => {
expect(vs).to.deep.equal(new Set(["a", "b", "c", "d"]))
})
})
describe("colorGreedy", () => {
it("colors graph", () => {
const g = createGraph((v, e) => {
[0, 1, 2, 3, 4].forEach(i => v("x" + i, true))
e("x0", "x1")
e("x1", "x2")
e("x2", "x3")
})
const coloring1 = colorGreedy(g, ["x0", "x1", "x2", "x3", "x4"])
expect(coloring1.numColors).to.equal(2)
const coloring2 = colorGreedy(g, ["x0", "x3", "x1", "x2", "x4"])
expect(coloring2.numColors).to.equal(3)
})
})
})

Loading…
Cancel
Save