You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Add plan for #438: [Model] PartialFeedbackEdgeSet
* Implement #438: [Model] PartialFeedbackEdgeSet
* chore: remove plan file for #438
* chore: fix rustfmt formatting in export_module_graph.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: deduplicate normalize_edge between model and test
Widen the feature gate to `#[cfg(any(feature = "example-db", test))]`
so the test module can reuse the parent's normalize_edge via super::.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Xiwei Pan <xiwei.pan@connect.hkust-gz.edu.cn>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@@ -4804,6 +4805,65 @@ A classical NP-complete problem from Garey and Johnson @garey1979[Ch.~3, p.~76],
4804
4805
]
4805
4806
}
4806
4807
4808
+
#{
4809
+
let x = load-model-example("PartialFeedbackEdgeSet")
4810
+
let nv = graph-num-vertices(x.instance)
4811
+
let edges = x.instance.graph.edges
4812
+
let ne = edges.len()
4813
+
let K = x.instance.budget
4814
+
let L = x.instance.max_cycle_length
4815
+
let config = x.optimal_config
4816
+
let removed-indices = config.enumerate().filter(((i, v)) => v == 1).map(((i, _)) => i)
4817
+
let removed-edges = removed-indices.map(i => edges.at(i))
4818
+
let blue = graph-colors.at(0)
4819
+
let gray = luma(180)
4820
+
[
4821
+
#problem-def("PartialFeedbackEdgeSet")[
4822
+
Given an undirected graph $G = (V, E)$, a budget $K in ZZ_(>= 0)$, and a cycle-length bound $L in ZZ_(>= 0)$, determine whether there exists a subset $E' subset.eq E$ with $|E'| <= K$ such that every simple cycle in $G$ of length at most $L$ contains at least one edge of $E'$.
4823
+
][
4824
+
Partial Feedback Edge Set is the bounded-cycle edge-deletion problem GT9 in Garey and Johnson @garey1979. Bounding the cycle length is what makes the problem hard: hitting only the short cycles is NP-complete, whereas the unrestricted undirected feedback-edge-set problem is polynomial-time solvable by reducing to a spanning forest. The implementation here uses one binary variable per edge, so brute-force search explores $O^*(2^|E|)$ candidate edge subsets.#footnote[No sharper general exact worst-case bound is claimed here.]
4825
+
4826
+
*Example.* Consider the graph $G$ with $n = #nv$ vertices, $|E| = #ne$ edges, budget $K = #K$, and length bound $L = #L$. Removing
hits the triangles $(v_0, v_1, v_2)$, $(v_0, v_2, v_3)$, $(v_2, v_3, v_4)$, and $(v_3, v_4, v_5)$, together with the 4-cycles $(v_0, v_1, v_2, v_3)$, $(v_0, v_2, v_4, v_3)$, and $(v_2, v_3, v_5, v_4)$. Hence every cycle of length at most 4 is hit. Brute-force search on this instance finds exactly five satisfying 3-edge deletions and none of size 2, so the displayed configuration certifies a YES-instance.
caption: [Partial Feedback Edge Set example with $K = 3$ and $L = 4$. Blue edges $\{v_0, v_2\}$, $\{v_2, v_3\}$, and $\{v_3, v_4\}$ form a satisfying edge set that hits every cycle of length at most 4.],
4862
+
) <fig:partial-feedback-edge-set>
4863
+
]
4864
+
]
4865
+
}
4866
+
4807
4867
#{
4808
4868
let x = load-model-example("MultipleChoiceBranching")
0 commit comments