Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/unit_tests/models/graph/kcoloring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_sat, jl_best, "KColoring satisfying solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Path graph: 0-1-2, 3-coloring
let problem = KColoring::<K3, _>::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]));
// Valid: neighbors have different colors
assert!(problem.is_valid_solution(&[0, 1, 0]));
// Invalid: adjacent vertices 0 and 1 have same color
assert!(!problem.is_valid_solution(&[0, 0, 1]));
}
9 changes: 9 additions & 0 deletions src/unit_tests/models/graph/max_cut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,12 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "MaxCut best solutions mismatch");
}
}

#[test]
fn test_cut_size_method() {
let problem = MaxCut::new(SimpleGraph::new(3, vec![(0, 1), (1, 2), (0, 2)]), vec![1, 2, 3]);
// Partition {0} vs {1, 2}: cuts edges (0,1)=1 and (0,2)=3
assert_eq!(problem.cut_size(&[0, 1, 1]), 4);
// All same partition: no edges cut
assert_eq!(problem.cut_size(&[0, 0, 0]), 0);
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/graph/maximal_is.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "MaximalIS best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Path graph: 0-1-2
let problem = MaximalIS::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i32; 3]);
// Valid: {0, 2} is maximal (independent and no vertex can be added)
assert!(problem.is_valid_solution(&[1, 0, 1]));
// Invalid: {0} is independent but not maximal (vertex 2 can be added)
assert!(!problem.is_valid_solution(&[1, 0, 0]));
}
15 changes: 15 additions & 0 deletions src/unit_tests/models/graph/maximum_clique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,18 @@ fn test_clique_problem() {
assert_eq!(p.evaluate(&[1, 0, 0]), SolutionSize::Valid(1));
assert_eq!(p.direction(), Direction::Maximize);
}

#[test]
fn test_is_valid_solution() {
// Triangle: 0-1-2 all connected
let problem = MaximumClique::new(
SimpleGraph::new(3, vec![(0, 1), (1, 2), (0, 2)]),
vec![1i32; 3],
);
// Valid: all three form a clique
assert!(problem.is_valid_solution(&[1, 1, 1]));
// Now path graph: 0-1-2 (no 0-2 edge)
let problem2 = MaximumClique::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i32; 3]);
// Invalid: {0, 2} not adjacent
assert!(!problem2.is_valid_solution(&[1, 0, 1]));
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/graph/maximum_independent_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "IS best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Path graph: 0-1-2
let problem = MaximumIndependentSet::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i32; 3]);
// Valid: {0, 2} is independent
assert!(problem.is_valid_solution(&[1, 0, 1]));
// Invalid: {0, 1} are adjacent
assert!(!problem.is_valid_solution(&[1, 1, 0]));
}
13 changes: 13 additions & 0 deletions src/unit_tests/models/graph/maximum_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,16 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "Matching best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Triangle: edges (0,1), (1,2), (0,2) — config is per edge
let problem = MaximumMatching::new(
SimpleGraph::new(3, vec![(0, 1), (1, 2), (0, 2)]),
vec![1i32; 3],
);
// Valid: select edge (0,1) only — no shared vertices
assert!(problem.is_valid_solution(&[1, 0, 0]));
// Invalid: select edges (0,1) and (1,2) — vertex 1 shared
assert!(!problem.is_valid_solution(&[1, 1, 0]));
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/graph/minimum_dominating_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "DS best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Path graph: 0-1-2
let problem = MinimumDominatingSet::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i32; 3]);
// Valid: {1} dominates all vertices (0 and 2 are neighbors of 1)
assert!(problem.is_valid_solution(&[0, 1, 0]));
// Invalid: {0} doesn't dominate vertex 2
assert!(!problem.is_valid_solution(&[1, 0, 0]));
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/graph/minimum_vertex_cover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "VC best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Path graph: 0-1-2
let problem = MinimumVertexCover::new(SimpleGraph::new(3, vec![(0, 1), (1, 2)]), vec![1i32; 3]);
// Valid: {1} covers both edges
assert!(problem.is_valid_solution(&[0, 1, 0]));
// Invalid: {0} doesn't cover edge (1,2)
assert!(!problem.is_valid_solution(&[1, 0, 0]));
}
13 changes: 13 additions & 0 deletions src/unit_tests/models/graph/traveling_salesman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,16 @@ fn test_brute_force_triangle_weighted() {
assert_eq!(solutions[0], vec![1, 1, 1]);
assert_eq!(problem.evaluate(&solutions[0]), SolutionSize::Valid(30));
}

#[test]
fn test_is_valid_solution() {
// K3 triangle: edges (0,1), (0,2), (1,2) — config is per edge
let problem = TravelingSalesman::new(
SimpleGraph::new(3, vec![(0, 1), (0, 2), (1, 2)]),
vec![1, 2, 3],
);
// Valid: select all 3 edges forms Hamiltonian cycle 0-1-2-0
assert!(problem.is_valid_solution(&[1, 1, 1]));
// Invalid: select only 2 edges — not a cycle
assert!(!problem.is_valid_solution(&[1, 1, 0]));
}
13 changes: 13 additions & 0 deletions src/unit_tests/models/satisfiability/sat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,16 @@ fn test_jl_parity_evaluation() {
}
}
}

#[test]
fn test_is_valid_solution() {
// (x1 OR x2) AND (NOT x1 OR x3)
let problem = Satisfiability::new(
3,
vec![CNFClause::new(vec![1, 2]), CNFClause::new(vec![-1, 3])],
);
// Valid: x1=F, x2=T, x3=T → (T) AND (T) = T
assert!(problem.is_valid_solution(&[0, 1, 1]));
// Invalid: x1=T, x2=F, x3=F → (T) AND (F) = F
assert!(!problem.is_valid_solution(&[1, 0, 0]));
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/set/maximum_set_packing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "SetPacking best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Sets: {0,1}, {1,2}, {3,4}
let problem = MaximumSetPacking::<i32>::new(vec![vec![0, 1], vec![1, 2], vec![3, 4]]);
// Valid: select sets 0 and 2 (disjoint: {0,1} and {3,4})
assert!(problem.is_valid_solution(&[1, 0, 1]));
// Invalid: select sets 0 and 1 (share element 1)
assert!(!problem.is_valid_solution(&[1, 1, 0]));
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/set/minimum_set_covering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "SetCovering best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Universe: {0,1,2,3}, Sets: {0,1}, {1,2}, {2,3}
let problem = MinimumSetCovering::<i32>::new(4, vec![vec![0, 1], vec![1, 2], vec![2, 3]]);
// Valid: all sets selected covers {0,1,2,3}
assert!(problem.is_valid_solution(&[1, 1, 1]));
// Invalid: only set 1 ({1,2}) doesn't cover 0 and 3
assert!(!problem.is_valid_solution(&[0, 1, 0]));
}
13 changes: 13 additions & 0 deletions src/unit_tests/models/specialized/biclique_cover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,16 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "BicliqueCover best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
use crate::topology::BipartiteGraph;
// Single edge (0,0) with 1 biclique
let graph = BipartiteGraph::new(1, 1, vec![(0, 0)]);
let problem = BicliqueCover::new(graph, 1);
// 2 vertices (left_0, right_0), 1 biclique → config length = 2
// Valid: both vertices in biclique 0 → covers edge (0,0)
assert!(problem.is_valid_solution(&[1, 1]));
// Invalid: only left vertex in biclique → doesn't form complete bipartite subgraph covering edge
assert!(!problem.is_valid_solution(&[1, 0]));
}
15 changes: 15 additions & 0 deletions src/unit_tests/models/specialized/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,18 @@ fn test_circuit_sat_problem() {
// c=1, x=1, y=0: c = 1 AND 0 = 0 != 1 => not satisfied
assert!(!p.evaluate(&[1, 1, 0]));
}

#[test]
fn test_is_valid_solution() {
// c = x AND y
let circuit = Circuit::new(vec![Assignment::new(
vec!["c".to_string()],
BooleanExpr::and(vec![BooleanExpr::var("x"), BooleanExpr::var("y")]),
)]);
let problem = CircuitSAT::new(circuit);
// Variables sorted: c, x, y
// Valid: c=1, x=1, y=1 (c = 1 AND 1 = 1)
assert!(problem.is_valid_solution(&[1, 1, 1]));
// Invalid: c=1, x=1, y=0 (c = 1 AND 0 = 0, but c=1)
assert!(!problem.is_valid_solution(&[1, 1, 0]));
}
10 changes: 10 additions & 0 deletions src/unit_tests/models/specialized/factoring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,13 @@ fn test_jl_parity_evaluation() {
assert_eq!(rust_best, jl_best, "Factoring best solutions mismatch");
}
}

#[test]
fn test_is_valid_solution() {
// Factor 15 = 3 × 5, 3 bits each
let problem = Factoring::new(3, 3, 15);
// Valid: 3 = [1,1,0], 5 = [1,0,1] → config = [1,1,0,1,0,1]
assert!(problem.is_valid_solution(&[1, 1, 0, 1, 0, 1]));
// Invalid: 2 = [0,1,0], 3 = [1,1,0] → 2*3=6 ≠ 15
assert!(!problem.is_valid_solution(&[0, 1, 0, 1, 1, 0]));
}
16 changes: 15 additions & 1 deletion src/unit_tests/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ fn test_kvalue_kn() {
// --- Graph type VariantParam tests ---

use crate::topology::HyperGraph;
use crate::topology::{Graph, SimpleGraph, UnitDiskGraph};
use crate::topology::{BipartiteGraph, Graph, PlanarGraph, SimpleGraph, UnitDiskGraph};

#[test]
fn test_simple_graph_variant_param() {
Expand All @@ -266,6 +266,20 @@ fn test_hyper_graph_variant_param() {
assert_eq!(HyperGraph::PARENT_VALUE, None);
}

#[test]
fn test_planar_graph_variant_param() {
assert_eq!(PlanarGraph::CATEGORY, "graph");
assert_eq!(PlanarGraph::VALUE, "PlanarGraph");
assert_eq!(PlanarGraph::PARENT_VALUE, Some("SimpleGraph"));
}

#[test]
fn test_bipartite_graph_variant_param() {
assert_eq!(BipartiteGraph::CATEGORY, "graph");
assert_eq!(BipartiteGraph::VALUE, "BipartiteGraph");
assert_eq!(BipartiteGraph::PARENT_VALUE, Some("SimpleGraph"));
}

#[test]
fn test_simple_graph_cast_to_parent() {
let sg = SimpleGraph::new(3, vec![(0, 1), (1, 2)]);
Expand Down
4 changes: 2 additions & 2 deletions tests/suites/reductions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ mod topology_tests {
}
}

// TruthTable integration tests moved to src/unit_tests/truth_table.rs
// (truth_table module is now pub(crate))
// TruthTable integration tests removed (module is now pub(crate));
// equivalent coverage exists in src/unit_tests/truth_table.rs

/// Tests for QUBO reductions against ground truth JSON.
mod qubo_reductions {
Expand Down