Skip to content
This repository was archived by the owner on Jun 18, 2026. It is now read-only.

Commit 42d1355

Browse files
test: add comprehensive test suite for ChromaticPolynomialCalculator
26 tests covering: - Empty, single-vertex, and independent-set graphs (base cases) - Complete graphs K2/K3/K4 (falling factorial verification) - Tree polynomials (path and star graphs, k(k-1)^(n-1)) - Cycle polynomials (C4 even, C5 odd — 2-colorability check) - Disconnected components (polynomial product property) - Deletion-contraction on general graphs (diamond, house graph) - PolynomialResult API (degree, coefficients, evaluations, string format) - Second-coefficient = -|E| invariant - Report generation content verification
1 parent 3b0672e commit 42d1355

1 file changed

Lines changed: 345 additions & 0 deletions

File tree

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
package gvisual;
2+
3+
import edu.uci.ics.jung.graph.Graph;
4+
import edu.uci.ics.jung.graph.UndirectedSparseGraph;
5+
import org.junit.Before;
6+
import org.junit.Test;
7+
8+
import java.util.List;
9+
import java.util.Map;
10+
11+
import static org.junit.Assert.*;
12+
13+
/**
14+
* Unit tests for {@link ChromaticPolynomialCalculator}.
15+
*/
16+
public class ChromaticPolynomialCalculatorTest {
17+
18+
private Graph<String, String> graph;
19+
private int edgeId;
20+
21+
@Before
22+
public void setUp() {
23+
graph = new UndirectedSparseGraph<>();
24+
edgeId = 0;
25+
}
26+
27+
private void addEdge(String v1, String v2) {
28+
if (!graph.containsVertex(v1)) graph.addVertex(v1);
29+
if (!graph.containsVertex(v2)) graph.addVertex(v2);
30+
graph.addEdge("e" + edgeId++, v1, v2);
31+
}
32+
33+
// --- Empty / trivial graphs ---
34+
35+
@Test
36+
public void emptyGraph_polynomialIsOne() {
37+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
38+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
39+
assertEquals(1, r.evaluate(0));
40+
assertEquals(1, r.evaluate(5));
41+
assertTrue(r.isExact());
42+
}
43+
44+
@Test
45+
public void singleVertex_polynomialIsK() {
46+
graph.addVertex("A");
47+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
48+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
49+
// P(G,k) = k
50+
assertEquals(0, r.evaluate(0));
51+
assertEquals(1, r.evaluate(1));
52+
assertEquals(5, r.evaluate(5));
53+
assertEquals(1, r.getChromaticNumber());
54+
assertTrue(r.isExact());
55+
}
56+
57+
@Test
58+
public void independentSet_polynomialIsKToN() {
59+
graph.addVertex("A");
60+
graph.addVertex("B");
61+
graph.addVertex("C");
62+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
63+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
64+
// P = k^3
65+
assertEquals(0, r.evaluate(0));
66+
assertEquals(1, r.evaluate(1));
67+
assertEquals(8, r.evaluate(2));
68+
assertEquals(27, r.evaluate(3));
69+
assertEquals(1, r.getChromaticNumber());
70+
}
71+
72+
@Test(expected = NullPointerException.class)
73+
public void nullGraph_throws() {
74+
new ChromaticPolynomialCalculator(null);
75+
}
76+
77+
// --- Single edge (K2) ---
78+
79+
@Test
80+
public void singleEdge_polynomial() {
81+
addEdge("A", "B");
82+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
83+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
84+
// P(K2, k) = k(k-1)
85+
assertEquals(0, r.evaluate(0));
86+
assertEquals(0, r.evaluate(1));
87+
assertEquals(2, r.evaluate(2));
88+
assertEquals(6, r.evaluate(3));
89+
assertEquals(2, r.getChromaticNumber());
90+
}
91+
92+
// --- Complete graphs ---
93+
94+
@Test
95+
public void completeK3_polynomial() {
96+
addEdge("A", "B");
97+
addEdge("B", "C");
98+
addEdge("A", "C");
99+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
100+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
101+
// P(K3, k) = k(k-1)(k-2)
102+
assertEquals(0, r.evaluate(0));
103+
assertEquals(0, r.evaluate(1));
104+
assertEquals(0, r.evaluate(2));
105+
assertEquals(6, r.evaluate(3));
106+
assertEquals(24, r.evaluate(4));
107+
assertEquals(3, r.getChromaticNumber());
108+
assertEquals("Complete K3", r.getSpecialType());
109+
}
110+
111+
@Test
112+
public void completeK4_polynomial() {
113+
String[] vs = {"A", "B", "C", "D"};
114+
for (int i = 0; i < vs.length; i++)
115+
for (int j = i + 1; j < vs.length; j++)
116+
addEdge(vs[i], vs[j]);
117+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
118+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
119+
// P(K4, k) = k(k-1)(k-2)(k-3)
120+
assertEquals(0, r.evaluate(3));
121+
assertEquals(24, r.evaluate(4));
122+
assertEquals(120, r.evaluate(5));
123+
assertEquals(4, r.getChromaticNumber());
124+
}
125+
126+
// --- Trees ---
127+
128+
@Test
129+
public void pathGraph_isTree() {
130+
// A-B-C-D: tree on 4 vertices
131+
addEdge("A", "B");
132+
addEdge("B", "C");
133+
addEdge("C", "D");
134+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
135+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
136+
// P(T4, k) = k(k-1)^3
137+
assertEquals(0, r.evaluate(0));
138+
assertEquals(0, r.evaluate(1));
139+
assertEquals(2, r.evaluate(2)); // 2*1^3 = 2
140+
assertEquals(24, r.evaluate(3)); // 3*2^3 = 24
141+
assertEquals(2, r.getChromaticNumber());
142+
assertNotNull(r.getSpecialType());
143+
assertTrue(r.getSpecialType().startsWith("Tree"));
144+
}
145+
146+
@Test
147+
public void starGraph_isTree() {
148+
// Hub "H" connected to A,B,C,D
149+
addEdge("H", "A");
150+
addEdge("H", "B");
151+
addEdge("H", "C");
152+
addEdge("H", "D");
153+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
154+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
155+
// P(T5, k) = k(k-1)^4
156+
assertEquals(0, r.evaluate(1));
157+
assertEquals(2, r.evaluate(2)); // 2*1 = 2
158+
assertEquals(48, r.evaluate(3)); // 3*16 = 48
159+
assertEquals(2, r.getChromaticNumber());
160+
}
161+
162+
// --- Cycles ---
163+
164+
@Test
165+
public void cycle3_isTriangle() {
166+
// Same as K3, but test via cycle detection path
167+
addEdge("A", "B");
168+
addEdge("B", "C");
169+
addEdge("A", "C");
170+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
171+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
172+
// K3 is detected as Complete before Cycle, but polynomial is same
173+
assertEquals(6, r.evaluate(3));
174+
assertEquals(3, r.getChromaticNumber());
175+
}
176+
177+
@Test
178+
public void cycle4_polynomial() {
179+
addEdge("A", "B");
180+
addEdge("B", "C");
181+
addEdge("C", "D");
182+
addEdge("D", "A");
183+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
184+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
185+
// P(C4, k) = (k-1)^4 + (k-1)
186+
// k=2: 1 + 1 = 2
187+
assertEquals(2, r.evaluate(2));
188+
// k=3: 16 + 2 = 18
189+
assertEquals(18, r.evaluate(3));
190+
assertEquals(2, r.getChromaticNumber());
191+
assertEquals("Cycle C4", r.getSpecialType());
192+
}
193+
194+
@Test
195+
public void cycle5_oddCycle() {
196+
addEdge("A", "B");
197+
addEdge("B", "C");
198+
addEdge("C", "D");
199+
addEdge("D", "E");
200+
addEdge("E", "A");
201+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
202+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
203+
// P(C5, k) = (k-1)^5 - (k-1)
204+
// k=2: 1 - 1 = 0 (odd cycle is not 2-colorable)
205+
assertEquals(0, r.evaluate(2));
206+
// k=3: 32 - 2 = 30
207+
assertEquals(30, r.evaluate(3));
208+
assertEquals(3, r.getChromaticNumber());
209+
}
210+
211+
// --- Disconnected components ---
212+
213+
@Test
214+
public void disconnectedGraph_productsPolynomials() {
215+
// K2 + isolated vertex = P(K2,k) * P(v,k) = k(k-1) * k = k^2(k-1)
216+
addEdge("A", "B");
217+
graph.addVertex("C");
218+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
219+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
220+
assertEquals(0, r.evaluate(0));
221+
assertEquals(0, r.evaluate(1));
222+
// k^2*(k-1) at k=2 = 4*1 = 4
223+
assertEquals(4, r.evaluate(2));
224+
assertEquals(18, r.evaluate(3)); // 9*2 = 18
225+
}
226+
227+
@Test
228+
public void twoDisconnectedEdges() {
229+
// K2 + K2 = [k(k-1)]^2
230+
addEdge("A", "B");
231+
addEdge("C", "D");
232+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
233+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
234+
// k=2: [2*1]^2 = 4
235+
assertEquals(4, r.evaluate(2));
236+
// k=3: [3*2]^2 = 36
237+
assertEquals(36, r.evaluate(3));
238+
}
239+
240+
// --- Deletion-contraction (general graph) ---
241+
242+
@Test
243+
public void diamondGraph_deletionContraction() {
244+
// Diamond: K4 minus one edge
245+
addEdge("A", "B");
246+
addEdge("A", "C");
247+
addEdge("A", "D");
248+
addEdge("B", "C");
249+
addEdge("C", "D");
250+
// Missing B-D
251+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
252+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
253+
// Chromatic number should be 3 (triangle A-B-C exists)
254+
assertEquals(3, r.getChromaticNumber());
255+
assertEquals(0, r.evaluate(2));
256+
assertTrue(r.evaluate(3) > 0);
257+
assertTrue(r.isExact());
258+
}
259+
260+
@Test
261+
public void petersenLikeSmall_exact() {
262+
// A small non-trivial graph: house graph (square + triangle on top)
263+
// A-B-C-D-A plus B-E and C-E
264+
addEdge("A", "B");
265+
addEdge("B", "C");
266+
addEdge("C", "D");
267+
addEdge("D", "A");
268+
addEdge("B", "E");
269+
addEdge("C", "E");
270+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
271+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
272+
assertTrue(r.isExact());
273+
assertEquals(3, r.getChromaticNumber());
274+
// P(G,0) must always be 0 for non-empty graphs
275+
assertEquals(0, r.evaluate(0));
276+
}
277+
278+
// --- PolynomialResult API ---
279+
280+
@Test
281+
public void resultDegreeEqualsVertexCount() {
282+
addEdge("A", "B");
283+
addEdge("B", "C");
284+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
285+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
286+
assertEquals(r.getVertexCount(), r.getDegree());
287+
}
288+
289+
@Test
290+
public void polynomialStringNotEmpty() {
291+
addEdge("A", "B");
292+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
293+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
294+
assertFalse(r.getPolynomialString().isEmpty());
295+
}
296+
297+
@Test
298+
public void evaluationsListPopulated() {
299+
addEdge("A", "B");
300+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
301+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
302+
assertFalse(r.getEvaluations().isEmpty());
303+
// First entry k=0 should always be 0 for non-empty graph
304+
assertEquals(Integer.valueOf(0), r.getEvaluations().get(0).getKey());
305+
assertEquals(Long.valueOf(0), r.getEvaluations().get(0).getValue());
306+
}
307+
308+
@Test
309+
public void coefficientSecondTermEqualsNegativeEdgeCount() {
310+
// For any simple graph, coefficient of k^(n-1) = -|E|
311+
addEdge("A", "B");
312+
addEdge("B", "C");
313+
addEdge("A", "C");
314+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
315+
ChromaticPolynomialCalculator.PolynomialResult r = calc.compute();
316+
long[] coeffs = r.getCoefficients();
317+
// Leading: coeffs[n] = 1, second: coeffs[n-1] = -|E|
318+
assertEquals(1, coeffs[coeffs.length - 1]);
319+
assertEquals(-r.getEdgeCount(), coeffs[coeffs.length - 2]);
320+
}
321+
322+
// --- Report generation ---
323+
324+
@Test
325+
public void reportNotEmpty() {
326+
addEdge("A", "B");
327+
addEdge("B", "C");
328+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
329+
String report = calc.generateReport();
330+
assertNotNull(report);
331+
assertTrue(report.contains("CHROMATIC POLYNOMIAL"));
332+
assertTrue(report.contains("Chromatic number"));
333+
}
334+
335+
@Test
336+
public void reportIncludesSpecialType() {
337+
// K3
338+
addEdge("A", "B");
339+
addEdge("B", "C");
340+
addEdge("A", "C");
341+
ChromaticPolynomialCalculator calc = new ChromaticPolynomialCalculator(graph);
342+
String report = calc.generateReport();
343+
assertTrue(report.contains("Complete K3"));
344+
}
345+
}

0 commit comments

Comments
 (0)