effect 3.21.2 → 3.21.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Graph.ts CHANGED
@@ -1923,6 +1923,37 @@ export const isAcyclic = <N, E, T extends Kind = "directed">(
1923
1923
  return graph.isAcyclic.value
1924
1924
  }
1925
1925
 
1926
+ if (graph.type === "undirected") {
1927
+ const visited = new Set<NodeIndex>()
1928
+
1929
+ for (const startNode of graph.nodes.keys()) {
1930
+ if (visited.has(startNode)) {
1931
+ continue
1932
+ }
1933
+
1934
+ visited.add(startNode)
1935
+ const stack: Array<{ node: NodeIndex; parent: NodeIndex | null }> = [{ node: startNode, parent: null }]
1936
+
1937
+ while (stack.length > 0) {
1938
+ const { node, parent } = stack.pop()!
1939
+ const nodeNeighbors = getUndirectedNeighbors(graph as any, node)
1940
+
1941
+ for (const neighbor of nodeNeighbors) {
1942
+ if (!visited.has(neighbor)) {
1943
+ visited.add(neighbor)
1944
+ stack.push({ node: neighbor, parent: node })
1945
+ } else if (neighbor !== parent) {
1946
+ graph.isAcyclic = Option.some(false)
1947
+ return false
1948
+ }
1949
+ }
1950
+ }
1951
+ }
1952
+
1953
+ graph.isAcyclic = Option.some(true)
1954
+ return true
1955
+ }
1956
+
1926
1957
  // Stack-safe DFS cycle detection using iterative approach
1927
1958
  const visited = new Set<NodeIndex>()
1928
1959
  const recursionStack = new Set<NodeIndex>()
@@ -2103,6 +2134,21 @@ const getUndirectedNeighbors = <N, E>(
2103
2134
  return Array.from(neighbors)
2104
2135
  }
2105
2136
 
2137
+ const getTraversalNeighbors = <N, E, T extends Kind>(
2138
+ graph: Graph<N, E, T> | MutableGraph<N, E, T>,
2139
+ nodeIndex: NodeIndex,
2140
+ direction: Direction
2141
+ ): Array<NodeIndex> =>
2142
+ graph.type === "undirected"
2143
+ ? getUndirectedNeighbors(graph as any, nodeIndex)
2144
+ : neighborsDirected(graph, nodeIndex, direction)
2145
+
2146
+ const getTraversableNeighbor = <N, E, T extends Kind>(
2147
+ graph: Graph<N, E, T> | MutableGraph<N, E, T>,
2148
+ current: NodeIndex,
2149
+ edge: Edge<E>
2150
+ ): NodeIndex => graph.type === "undirected" && edge.target === current ? edge.source : edge.target
2151
+
2106
2152
  /**
2107
2153
  * Find connected components in an undirected graph.
2108
2154
  * Each component is represented as an array of node indices.
@@ -2432,7 +2478,7 @@ export const dijkstra = <N, E, T extends Kind = "directed">(
2432
2478
  for (const edgeIndex of adjacencyList) {
2433
2479
  const edge = graph.edges.get(edgeIndex)
2434
2480
  if (edge !== undefined) {
2435
- const neighbor = edge.target
2481
+ const neighbor = getTraversableNeighbor(graph, currentNode, edge)
2436
2482
  const weight = cost(edge.data)
2437
2483
 
2438
2484
  // Validate non-negative weights
@@ -2564,6 +2610,15 @@ export const floydWarshall = <N, E, T extends Kind = "directed">(
2564
2610
  next.get(i)!.set(j, j)
2565
2611
  edgeMatrix.get(i)!.set(j, edgeData.data)
2566
2612
  }
2613
+
2614
+ if (graph.type === "undirected") {
2615
+ const reverseWeight = dist.get(j)!.get(i)!
2616
+ if (weight < reverseWeight) {
2617
+ dist.get(j)!.set(i, weight)
2618
+ next.get(j)!.set(i, i)
2619
+ edgeMatrix.get(j)!.set(i, edgeData.data)
2620
+ }
2621
+ }
2567
2622
  }
2568
2623
 
2569
2624
  // Floyd-Warshall main loop
@@ -2757,7 +2812,7 @@ export const astar = <N, E, T extends Kind = "directed">(
2757
2812
  for (const edgeIndex of adjacencyList) {
2758
2813
  const edge = graph.edges.get(edgeIndex)
2759
2814
  if (edge !== undefined) {
2760
- const neighbor = edge.target
2815
+ const neighbor = getTraversableNeighbor(graph, currentNode, edge)
2761
2816
  const weight = cost(edge.data)
2762
2817
 
2763
2818
  // Validate non-negative weights
@@ -2893,6 +2948,14 @@ export const bellmanFord = <N, E, T extends Kind = "directed">(
2893
2948
  weight,
2894
2949
  edgeData: edgeData.data
2895
2950
  })
2951
+ if (graph.type === "undirected" && edgeData.source !== edgeData.target) {
2952
+ edges.push({
2953
+ source: edgeData.target,
2954
+ target: edgeData.source,
2955
+ weight,
2956
+ edgeData: edgeData.data
2957
+ })
2958
+ }
2896
2959
  }
2897
2960
 
2898
2961
  // Relax edges up to V-1 times
@@ -2934,14 +2997,8 @@ export const bellmanFord = <N, E, T extends Kind = "directed">(
2934
2997
  affectedNodes.add(node)
2935
2998
 
2936
2999
  // Add all nodes reachable from this node
2937
- const adjacencyList = graph.adjacency.get(node)
2938
- if (adjacencyList !== undefined) {
2939
- for (const edgeIndex of adjacencyList) {
2940
- const edge = graph.edges.get(edgeIndex)
2941
- if (edge !== undefined) {
2942
- queue.push(edge.target)
2943
- }
2944
- }
3000
+ for (const neighbor of getTraversalNeighbors(graph, node, "outgoing")) {
3001
+ queue.push(neighbor)
2945
3002
  }
2946
3003
  }
2947
3004
 
@@ -3259,7 +3316,7 @@ export const dfs = <N, E, T extends Kind = "directed">(
3259
3316
  continue
3260
3317
  }
3261
3318
 
3262
- const neighbors = neighborsDirected(graph, current, direction)
3319
+ const neighbors = getTraversalNeighbors(graph, current, direction)
3263
3320
  for (let i = neighbors.length - 1; i >= 0; i--) {
3264
3321
  const neighbor = neighbors[i]
3265
3322
  if (!discovered.has(neighbor)) {
@@ -3336,7 +3393,7 @@ export const bfs = <N, E, T extends Kind = "directed">(
3336
3393
  if (!discovered.has(current)) {
3337
3394
  discovered.add(current)
3338
3395
 
3339
- const neighbors = neighborsDirected(graph, current, direction)
3396
+ const neighbors = getTraversalNeighbors(graph, current, direction)
3340
3397
  for (const neighbor of neighbors) {
3341
3398
  if (!discovered.has(neighbor)) {
3342
3399
  queue.push(neighbor)
@@ -3418,6 +3475,10 @@ export const topo = <N, E, T extends Kind = "directed">(
3418
3475
  graph: Graph<N, E, T> | MutableGraph<N, E, T>,
3419
3476
  config: TopoConfig = {}
3420
3477
  ): NodeWalker<N> => {
3478
+ if (graph.type === "undirected") {
3479
+ throw new Error("Cannot perform topological sort on undirected graph")
3480
+ }
3481
+
3421
3482
  // Check if graph is acyclic first
3422
3483
  if (!isAcyclic(graph)) {
3423
3484
  throw new Error("Cannot perform topological sort on cyclic graph")
@@ -3562,7 +3623,7 @@ export const dfsPostOrder = <N, E, T extends Kind = "directed">(
3562
3623
 
3563
3624
  if (!current.visitedChildren) {
3564
3625
  current.visitedChildren = true
3565
- const neighbors = neighborsDirected(graph, current.node, direction)
3626
+ const neighbors = getTraversalNeighbors(graph, current.node, direction)
3566
3627
 
3567
3628
  for (let i = neighbors.length - 1; i >= 0; i--) {
3568
3629
  const neighbor = neighbors[i]
package/src/JSONSchema.ts CHANGED
@@ -843,7 +843,7 @@ function go(
843
843
  const parameter = is.parameter
844
844
  switch (parameter._tag) {
845
845
  case "StringKeyword": {
846
- output.additionalProperties = go(
846
+ const additionalProperties = go(
847
847
  pruned,
848
848
  $defs,
849
849
  "handle-identifier",
@@ -852,6 +852,9 @@ function go(
852
852
  "handle-annotation",
853
853
  errors
854
854
  )
855
+ output.additionalProperties = isNeverWithoutCustomAnnotations(additionalProperties)
856
+ ? false
857
+ : additionalProperties
855
858
  break
856
859
  }
857
860
  case "TemplateLiteral": {
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.21.2"
1
+ let moduleVersion = "3.21.4"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4