|
| 1 | +// # Independent Set to Clique Reduction |
| 2 | +// |
| 3 | +// ## Mathematical Equivalence |
| 4 | +// S is an independent set in G iff S is a clique in the complement graph Ḡ. |
| 5 | +// The reduction builds Ḡ by taking edges not in G. Solution extraction is |
| 6 | +// identity: the same vertex set works for both problems. |
| 7 | +// |
| 8 | +// ## This Example |
| 9 | +// - Instance: Path graph P5 (5 vertices, 4 edges) |
| 10 | +// - Source MIS: max size 3 (e.g., {0, 2, 4}) |
| 11 | +// - Target MaxClique on complement: max clique size 3 |
| 12 | +// |
| 13 | +// ## Output |
| 14 | +// Exports `docs/paper/examples/maximumindependentset_to_maximumclique.json` and `.result.json`. |
| 15 | + |
| 16 | +use problemreductions::export::*; |
| 17 | +use problemreductions::prelude::*; |
| 18 | +use problemreductions::topology::{Graph, SimpleGraph}; |
| 19 | + |
| 20 | +pub fn run() { |
| 21 | + // Path graph: 0-1-2-3-4 |
| 22 | + let source = MaximumIndependentSet::new( |
| 23 | + SimpleGraph::new(5, vec![(0, 1), (1, 2), (2, 3), (3, 4)]), |
| 24 | + vec![1i32; 5], |
| 25 | + ); |
| 26 | + |
| 27 | + let reduction = ReduceTo::<MaximumClique<SimpleGraph, i32>>::reduce_to(&source); |
| 28 | + let target = reduction.target_problem(); |
| 29 | + |
| 30 | + println!("\n=== Problem Transformation ==="); |
| 31 | + println!( |
| 32 | + "Source: MaximumIndependentSet with {} vertices, {} edges", |
| 33 | + source.graph().num_vertices(), |
| 34 | + source.graph().num_edges() |
| 35 | + ); |
| 36 | + println!( |
| 37 | + "Target: MaximumClique with {} vertices, {} edges (complement graph)", |
| 38 | + target.num_vertices(), |
| 39 | + target.num_edges() |
| 40 | + ); |
| 41 | + |
| 42 | + let solver = BruteForce::new(); |
| 43 | + let target_solutions = solver.find_all_best(target); |
| 44 | + println!("\n=== Solution ==="); |
| 45 | + println!("Target solutions found: {}", target_solutions.len()); |
| 46 | + |
| 47 | + let mut solutions = Vec::new(); |
| 48 | + for target_sol in &target_solutions { |
| 49 | + let source_sol = reduction.extract_solution(target_sol); |
| 50 | + let size = source.evaluate(&source_sol); |
| 51 | + assert!(size.is_valid()); |
| 52 | + solutions.push(SolutionPair { |
| 53 | + source_config: source_sol.clone(), |
| 54 | + target_config: target_sol.clone(), |
| 55 | + }); |
| 56 | + } |
| 57 | + |
| 58 | + let source_sol = reduction.extract_solution(&target_solutions[0]); |
| 59 | + println!("Source IS solution: {:?}", source_sol); |
| 60 | + let size = source.evaluate(&source_sol); |
| 61 | + println!("Solution size: {:?}", size); |
| 62 | + assert!(size.is_valid()); |
| 63 | + println!("\nReduction verified successfully"); |
| 64 | + |
| 65 | + // Export JSON |
| 66 | + let source_edges = source.graph().edges(); |
| 67 | + let target_edges = target.graph().edges(); |
| 68 | + let source_variant = variant_to_map(MaximumIndependentSet::<SimpleGraph, i32>::variant()); |
| 69 | + let target_variant = variant_to_map(MaximumClique::<SimpleGraph, i32>::variant()); |
| 70 | + let overhead = lookup_overhead( |
| 71 | + "MaximumIndependentSet", |
| 72 | + &source_variant, |
| 73 | + "MaximumClique", |
| 74 | + &target_variant, |
| 75 | + ) |
| 76 | + .expect("MaximumIndependentSet -> MaximumClique overhead not found"); |
| 77 | + |
| 78 | + let data = ReductionData { |
| 79 | + source: ProblemSide { |
| 80 | + problem: MaximumIndependentSet::<SimpleGraph, i32>::NAME.to_string(), |
| 81 | + variant: source_variant, |
| 82 | + instance: serde_json::json!({ |
| 83 | + "num_vertices": source.graph().num_vertices(), |
| 84 | + "num_edges": source.graph().num_edges(), |
| 85 | + "edges": source_edges, |
| 86 | + }), |
| 87 | + }, |
| 88 | + target: ProblemSide { |
| 89 | + problem: MaximumClique::<SimpleGraph, i32>::NAME.to_string(), |
| 90 | + variant: target_variant, |
| 91 | + instance: serde_json::json!({ |
| 92 | + "num_vertices": target.num_vertices(), |
| 93 | + "num_edges": target.num_edges(), |
| 94 | + "edges": target_edges, |
| 95 | + }), |
| 96 | + }, |
| 97 | + overhead: overhead_to_json(&overhead), |
| 98 | + }; |
| 99 | + |
| 100 | + let results = ResultData { solutions }; |
| 101 | + let name = "maximumindependentset_to_maximumclique"; |
| 102 | + write_example(name, &data, &results); |
| 103 | +} |
| 104 | + |
| 105 | +fn main() { |
| 106 | + run() |
| 107 | +} |
0 commit comments