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 #440: [Model] GroupingBySwapping
* Implement #440: [Model] GroupingBySwapping
* chore: remove plan file after implementation
---------
Co-authored-by: Xiwei Pan <90967972+isPANN@users.noreply.github.com>
Copy file name to clipboardExpand all lines: docs/paper/reductions.typ
+62Lines changed: 62 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -145,6 +145,7 @@
145
145
"IntegralFlowWithMultipliers": [Integral Flow With Multipliers],
146
146
"MinMaxMulticenter": [Min-Max Multicenter],
147
147
"FlowShopScheduling": [Flow Shop Scheduling],
148
+
"GroupingBySwapping": [Grouping by Swapping],
148
149
"MinimumCutIntoBoundedSets": [Minimum Cut Into Bounded Sets],
149
150
"MinimumDummyActivitiesPert": [Minimum Dummy Activities in PERT Networks],
150
151
"MinimumSumMulticenter": [Minimum Sum Multicenter],
@@ -4381,6 +4382,67 @@ A classical NP-complete problem from Garey and Johnson @garey1979[Ch.~3, p.~76],
4381
4382
]
4382
4383
}
4383
4384
4385
+
#{
4386
+
let x = load-model-example("GroupingBySwapping")
4387
+
let source = x.instance.string
4388
+
let alpha-size = x.instance.alphabet_size
4389
+
let budget = x.instance.budget
4390
+
let config = x.optimal_config
4391
+
let alpha-map = range(alpha-size).map(i => str.from-unicode(97 + i))
4392
+
let fmt-str(s) = s.map(c => alpha-map.at(c)).join("")
4393
+
let source-str = fmt-str(source)
4394
+
let step1 = (0, 1, 0, 2, 1, 2)
4395
+
let step2 = (0, 0, 1, 2, 1, 2)
4396
+
let step3 = (0, 0, 1, 1, 2, 2)
4397
+
let step3-str = fmt-str(step3)
4398
+
[
4399
+
#problem-def("GroupingBySwapping")[
4400
+
Given a finite alphabet $Sigma$, a string $x in Sigma^*$, and a positive integer $K$, determine whether there exists a sequence of at most $K$ adjacent symbol interchanges that transforms $x$ into a string $y in Sigma^*$ in which every symbol $a in Sigma$ appears in a single contiguous block. Equivalently, $y$ contains no subsequence $a b a$ with distinct $a, b in Sigma$.
4401
+
][
4402
+
Grouping by Swapping is the storage-and-retrieval problem SR21 in Garey and Johnson @garey1979. It asks whether a string can be locally reorganized, using only adjacent transpositions, until equal symbols coalesce into blocks. The implementation in this crate uses a fixed-length swap program with one slot per allowed operation, so the direct brute-force search explores $O(|x|^K)$ configurations.#footnote[This is the exact search bound induced by the fixed-length witness encoding implemented in the codebase; no sharper exact worst-case bound is claimed here.]
4403
+
4404
+
*Example.* Let $Sigma = {#alpha-map.join(", ")}$, $x = #source-str$, and $K = #budget$. The configuration $p = (#config.map(str).join(", "))$ performs adjacent swaps at positions $(2, 3)$, $(1, 2)$, and $(3, 4)$, then uses two trailing no-op slots. The resulting string is $y = #step3-str$, so every symbol now appears in one contiguous block and the verifier returns YES.
..step3.enumerate().map(((i, c)) => cell(alpha-map.at(c), highlight: i == 3 or i == 4)),
4435
+
),
4436
+
))
4437
+
},
4438
+
caption: [Grouping by Swapping on $x = #source-str$: three effective adjacent swaps turn the alternating string into $y = #step3-str$. The remaining two slots in $p = (#config.map(str).join(", "))$ are no-ops at position 5.],
4439
+
) <fig:grouping-by-swapping>
4440
+
4441
+
The final row has exactly one block of $a$, one block of $b$, and one block of $c$, so it satisfies the grouping constraint within the allotted budget.
4442
+
]
4443
+
]
4444
+
}
4445
+
4384
4446
#{
4385
4447
let x = load-model-example("LongestCommonSubsequence")
pred create GroupingBySwapping --string \"0,1,2,0,1,2\" --bound 5 | pred solve - --solver brute-force
334
336
pred create StringToStringCorrection --source-string \"0,1,2,3,1,0\" --target-string \"0,1,3,2,1\" --bound 2 | pred solve - --solver brute-force
335
337
pred create MIS/KingsSubgraph --positions \"0,0;1,0;1,1;0,1\"
336
338
pred create MIS/UnitDiskGraph --positions \"0,0;1,0;0.5,0.8\" --radius 1.5
@@ -551,7 +553,7 @@ pub struct CreateArgs {
551
553
/// Required edge indices for RuralPostman (comma-separated, e.g., "0,2,4")
552
554
#[arg(long)]
553
555
pubrequired_edges:Option<String>,
554
-
/// Bound parameter (lower bound for LongestCircuit; upper or length bound for BoundedComponentSpanningForest, LengthBoundedDisjointPaths, LongestCommonSubsequence, MultipleCopyFileAllocation, MultipleChoiceBranching, OptimalLinearArrangement, RootedTreeArrangement, RuralPostman, ShortestCommonSupersequence, or StringToStringCorrection)
556
+
/// Bound parameter (lower bound for LongestCircuit; upper or length bound for BoundedComponentSpanningForest, GroupingBySwapping, LengthBoundedDisjointPaths, LongestCommonSubsequence, MultipleCopyFileAllocation, MultipleChoiceBranching, OptimalLinearArrangement, RootedTreeArrangement, RuralPostman, ShortestCommonSupersequence, or StringToStringCorrection)
555
557
#[arg(long, allow_hyphen_values = true)]
556
558
pubbound:Option<i64>,
557
559
/// Upper bound on expected retrieval latency for ExpectedRetrievalCost
@@ -578,6 +580,9 @@ pub struct CreateArgs {
578
580
/// Input strings for LCS (e.g., "ABAC;BACA" or "0,1,0;1,0,1") or SCS (e.g., "0,1,2;1,2,0")
579
581
#[arg(long)]
580
582
pubstrings:Option<String>,
583
+
/// Input string for GroupingBySwapping (comma-separated symbol indices, e.g., "0,1,2,0,1,2")
584
+
#[arg(long)]
585
+
pubstring:Option<String>,
581
586
/// Task costs for SequencingToMinimizeMaximumCumulativeCost (comma-separated, e.g., "2,-1,3,-2,1,-3")
582
587
#[arg(long, allow_hyphen_values = true)]
583
588
pubcosts:Option<String>,
@@ -671,7 +676,7 @@ pub struct CreateArgs {
671
676
/// Task availability rows for TimetableDesign (semicolon-separated 0/1 rows)
672
677
#[arg(long)]
673
678
pubtask_avail:Option<String>,
674
-
/// Alphabet size for LCS, SCS, StringToStringCorrection, or TwoDimensionalConsecutiveSets (optional; inferred from the input strings if omitted)
679
+
/// Alphabet size for GroupingBySwapping, LCS, SCS, StringToStringCorrection, or TwoDimensionalConsecutiveSets (optional; inferred from the input strings if omitted)
675
680
#[arg(long)]
676
681
pubalphabet_size:Option<usize>,
677
682
@@ -736,6 +741,7 @@ Examples:
736
741
pred solve reduced.json # solve a reduction bundle
737
742
pred solve reduced.json -o solution.json # save result to file
738
743
pred create MIS --graph 0-1,1-2 | pred solve - # read from stdin when an ILP path exists
744
+
pred create GroupingBySwapping --string \"0,1,2,0,1,2\" --bound 5 | pred solve - --solver brute-force
739
745
pred create StringToStringCorrection --source-string \"0,1,2,3,1,0\" --target-string \"0,1,3,2,1\" --bound 2 | pred solve - --solver brute-force
740
746
pred create TwoDimensionalConsecutiveSets --alphabet-size 6 --sets \"0,1,2;3,4,5;1,3;2,4;0,5\" | pred solve - --solver brute-force
741
747
pred solve problem.json --timeout 10 # abort after 10 seconds
@@ -751,8 +757,9 @@ Solve via explicit reduction:
751
757
Input: a problem JSON from `pred create`, or a reduction bundle from `pred reduce`.
752
758
When given a bundle, the target is solved and the solution is mapped back to the source.
753
759
The ILP solver auto-reduces non-ILP problems before solving.
754
-
Problems without an ILP reduction path, such as `LengthBoundedDisjointPaths`,
755
-
`MinMaxMulticenter`, and `StringToStringCorrection`, currently need `--solver brute-force`.
760
+
Problems without an ILP reduction path, such as `GroupingBySwapping`,
761
+
`LengthBoundedDisjointPaths`, `MinMaxMulticenter`, and `StringToStringCorrection`,
762
+
currently need `--solver brute-force`.
756
763
757
764
ILP backend (default: HiGHS). To use a different backend:
0 commit comments