feat(graph-sequencer): topological ordering will look for the longest circle (#8052)

This commit is contained in:
阿豪
2024-05-06 17:05:21 +08:00
committed by GitHub
parent 7a0536e23d
commit db1d6ffb9a
3 changed files with 34 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/deps.graph-sequencer": patch
---
Topological ordering will look for the longest circle

View File

@@ -98,11 +98,15 @@ export function graphSequencer<T> (graph: Graph<T>, includedNodes: T[] = [...gra
function findCycle (startNode: T): T[] {
const queue: Array<[T, T[]]> = [[startNode, [startNode]]]
const cycleVisited = new Set<T>()
const cycles: T[][] = []
while (queue.length) {
const [id, cycle] = queue.shift()!
for (const to of graph.get(id)!) {
if (to === startNode) {
return cycle
cycleVisited.add(to)
cycles.push([...cycle])
continue
}
if (visited.has(to) || cycleVisited.has(to)) {
continue
@@ -111,6 +115,11 @@ export function graphSequencer<T> (graph: Graph<T>, includedNodes: T[] = [...gra
queue.push([to, [...cycle, to]])
}
}
return []
if (!cycles.length) {
return []
}
cycles.sort((a, b) => b.length - a.length)
return cycles[0]
}
}

View File

@@ -350,8 +350,7 @@ test('graph with many nodes. Sequencing a subgraph', () => {
)
})
// TODO: fix this test
test.skip('graph with big cycle', () => {
test('graph with big cycle', () => {
expect(graphSequencer(new Map([
['a', ['b']],
['b', ['a', 'c']],
@@ -364,3 +363,20 @@ test.skip('graph with big cycle', () => {
}
)
})
test('graph with three cycles', () => {
expect(graphSequencer(new Map([
['a', ['b']],
['b', ['a', 'c']],
['c', ['a', 'b']],
['e', ['f']],
['f', ['e']],
['g', ['g']],
]))).toStrictEqual(
{
safe: false,
chunks: [['a', 'b', 'c', 'e', 'f', 'g']],
cycles: [['a', 'b', 'c'], ['e', 'f'], ['g']],
}
)
})