mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-12-19 07:00:35 +08:00
320 lines
8.8 KiB
Java
320 lines
8.8 KiB
Java
package com.thealgorithms.others;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
/**
|
|
* Test class for PageRank algorithm implementation
|
|
*
|
|
* @author Hardvan
|
|
*/
|
|
class PageRankTest {
|
|
|
|
private static final double EPSILON = 0.0001; // Tolerance for floating point comparisons
|
|
|
|
/**
|
|
* Test basic PageRank calculation with a simple 3-node graph
|
|
* Graph: 1 -> 2, 2 -> 3, 3 -> 1
|
|
*/
|
|
@Test
|
|
void testSimpleThreeNodeGraph() {
|
|
PageRank pageRank = new PageRank(3);
|
|
|
|
// Create a simple circular graph: 1 -> 2 -> 3 -> 1
|
|
int[][] adjacencyMatrix = new int[10][10];
|
|
adjacencyMatrix[1][2] = 1; // Node 1 links to Node 2
|
|
adjacencyMatrix[2][3] = 1; // Node 2 links to Node 3
|
|
adjacencyMatrix[3][1] = 1; // Node 3 links to Node 1
|
|
|
|
pageRank.setAdjacencyMatrix(adjacencyMatrix);
|
|
double[] result = pageRank.calculatePageRank(3);
|
|
|
|
// All nodes should have equal PageRank in a circular graph
|
|
assertNotNull(result);
|
|
assertEquals(result[1], result[2], EPSILON);
|
|
assertEquals(result[2], result[3], EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test PageRank with a two-node graph where one node points to another
|
|
*/
|
|
@Test
|
|
void testTwoNodeGraph() {
|
|
PageRank pageRank = new PageRank(2);
|
|
|
|
// Node 1 links to Node 2
|
|
pageRank.setEdge(1, 2, 1);
|
|
|
|
double[] result = pageRank.calculatePageRank(2);
|
|
|
|
// Node 2 should have higher PageRank than Node 1 (after 2 iterations)
|
|
assertNotNull(result);
|
|
assertEquals(0.2775, result[2], EPSILON);
|
|
assertEquals(0.15, result[1], EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test PageRank with a single node (no links)
|
|
*/
|
|
@Test
|
|
void testSingleNode() {
|
|
PageRank pageRank = new PageRank(1);
|
|
|
|
double[] result = pageRank.calculatePageRank(1);
|
|
|
|
// Single node should have (1-d) = 0.15 after applying damping
|
|
assertNotNull(result);
|
|
assertEquals(0.15, result[1], EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test PageRank with a hub-and-spoke configuration
|
|
* Node 1 is the hub, pointing to nodes 2, 3, and 4
|
|
*/
|
|
@Test
|
|
void testHubAndSpokeGraph() {
|
|
PageRank pageRank = new PageRank(4);
|
|
|
|
// Hub node (1) links to all other nodes
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.setEdge(1, 3, 1);
|
|
pageRank.setEdge(1, 4, 1);
|
|
|
|
// All spokes link back to hub
|
|
pageRank.setEdge(2, 1, 1);
|
|
pageRank.setEdge(3, 1, 1);
|
|
pageRank.setEdge(4, 1, 1);
|
|
|
|
double[] result = pageRank.calculatePageRank(4);
|
|
|
|
assertNotNull(result);
|
|
// Hub should have higher PageRank
|
|
assertEquals(result[2], result[3], EPSILON);
|
|
assertEquals(result[3], result[4], EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test PageRank with multiple iterations
|
|
*/
|
|
@Test
|
|
void testMultipleIterations() {
|
|
PageRank pageRank = new PageRank(3);
|
|
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.setEdge(2, 3, 1);
|
|
pageRank.setEdge(3, 1, 1);
|
|
|
|
double[] result2Iterations = pageRank.calculatePageRank(3, 0.85, 2, false);
|
|
double[] result5Iterations = pageRank.calculatePageRank(3, 0.85, 5, false);
|
|
|
|
assertNotNull(result2Iterations);
|
|
assertNotNull(result5Iterations);
|
|
}
|
|
|
|
/**
|
|
* Test getPageRank method for individual node
|
|
*/
|
|
@Test
|
|
void testGetPageRank() {
|
|
PageRank pageRank = new PageRank(2);
|
|
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.calculatePageRank(2);
|
|
|
|
double node1PageRank = pageRank.getPageRank(1);
|
|
double node2PageRank = pageRank.getPageRank(2);
|
|
|
|
assertEquals(0.15, node1PageRank, EPSILON);
|
|
assertEquals(0.2775, node2PageRank, EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test getAllPageRanks method
|
|
*/
|
|
@Test
|
|
void testGetAllPageRanks() {
|
|
PageRank pageRank = new PageRank(2);
|
|
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.calculatePageRank(2);
|
|
|
|
double[] allPageRanks = pageRank.getAllPageRanks();
|
|
|
|
assertNotNull(allPageRanks);
|
|
assertEquals(0.15, allPageRanks[1], EPSILON);
|
|
assertEquals(0.2775, allPageRanks[2], EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test that self-loops are not allowed
|
|
*/
|
|
@Test
|
|
void testNoSelfLoops() {
|
|
PageRank pageRank = new PageRank(2);
|
|
|
|
// Try to set a self-loop
|
|
pageRank.setEdge(1, 1, 1);
|
|
pageRank.setEdge(1, 2, 1);
|
|
|
|
double[] result = pageRank.calculatePageRank(2);
|
|
|
|
assertNotNull(result);
|
|
// Self-loop should be ignored
|
|
}
|
|
|
|
/**
|
|
* Test exception when node count is too small
|
|
*/
|
|
@Test
|
|
void testInvalidNodeCountTooSmall() {
|
|
assertThrows(IllegalArgumentException.class, () -> new PageRank(0));
|
|
}
|
|
|
|
/**
|
|
* Test exception when node count is too large
|
|
*/
|
|
@Test
|
|
void testInvalidNodeCountTooLarge() {
|
|
assertThrows(IllegalArgumentException.class, () -> new PageRank(11));
|
|
}
|
|
|
|
/**
|
|
* Test exception for invalid damping factor (negative)
|
|
*/
|
|
@Test
|
|
void testInvalidDampingFactorNegative() {
|
|
PageRank pageRank = new PageRank(2);
|
|
pageRank.setEdge(1, 2, 1);
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> pageRank.calculatePageRank(2, -0.1, 2, false));
|
|
}
|
|
|
|
/**
|
|
* Test exception for invalid damping factor (greater than 1)
|
|
*/
|
|
@Test
|
|
void testInvalidDampingFactorTooLarge() {
|
|
PageRank pageRank = new PageRank(2);
|
|
pageRank.setEdge(1, 2, 1);
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> pageRank.calculatePageRank(2, 1.5, 2, false));
|
|
}
|
|
|
|
/**
|
|
* Test exception for invalid iterations (less than 1)
|
|
*/
|
|
@Test
|
|
void testInvalidIterations() {
|
|
PageRank pageRank = new PageRank(2);
|
|
pageRank.setEdge(1, 2, 1);
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> pageRank.calculatePageRank(2, 0.85, 0, false));
|
|
}
|
|
|
|
/**
|
|
* Test exception when getting PageRank for invalid node
|
|
*/
|
|
@Test
|
|
void testGetPageRankInvalidNode() {
|
|
PageRank pageRank = new PageRank(2);
|
|
pageRank.calculatePageRank(2);
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> pageRank.getPageRank(3));
|
|
}
|
|
|
|
/**
|
|
* Test exception when getting PageRank for node less than 1
|
|
*/
|
|
@Test
|
|
void testGetPageRankNodeLessThanOne() {
|
|
PageRank pageRank = new PageRank(2);
|
|
pageRank.calculatePageRank(2);
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> pageRank.getPageRank(0));
|
|
}
|
|
|
|
/**
|
|
* Test complex graph with multiple incoming and outgoing links
|
|
*/
|
|
@Test
|
|
void testComplexGraph() {
|
|
PageRank pageRank = new PageRank(4);
|
|
|
|
// Create a more complex graph
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.setEdge(1, 3, 1);
|
|
pageRank.setEdge(2, 3, 1);
|
|
pageRank.setEdge(3, 4, 1);
|
|
pageRank.setEdge(4, 1, 1);
|
|
|
|
double[] result = pageRank.calculatePageRank(4);
|
|
|
|
assertNotNull(result);
|
|
// Node 3 should have high PageRank (receives links from nodes 1 and 2)
|
|
// After 2 iterations, the sum will not equal total nodes
|
|
double sum = result[1] + result[2] + result[3] + result[4];
|
|
assertEquals(1.8325, sum, EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test that PageRank values sum after 2 iterations
|
|
*/
|
|
@Test
|
|
void testPageRankSum() {
|
|
PageRank pageRank = new PageRank(5);
|
|
|
|
// Create arbitrary graph
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.setEdge(2, 3, 1);
|
|
pageRank.setEdge(3, 4, 1);
|
|
pageRank.setEdge(4, 5, 1);
|
|
pageRank.setEdge(5, 1, 1);
|
|
|
|
double[] result = pageRank.calculatePageRank(5);
|
|
|
|
double sum = 0;
|
|
for (int i = 1; i <= 5; i++) {
|
|
sum += result[i];
|
|
}
|
|
|
|
// Sum after 2 iterations with default damping factor
|
|
assertEquals(2.11, sum, EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test graph with isolated node (no incoming or outgoing links)
|
|
*/
|
|
@Test
|
|
void testGraphWithIsolatedNode() {
|
|
PageRank pageRank = new PageRank(3);
|
|
|
|
// Node 1 and 2 are connected, Node 3 is isolated
|
|
pageRank.setEdge(1, 2, 1);
|
|
pageRank.setEdge(2, 1, 1);
|
|
|
|
double[] result = pageRank.calculatePageRank(3);
|
|
|
|
assertNotNull(result);
|
|
// Isolated node should have some PageRank due to damping factor
|
|
assertEquals(0.15, result[3], EPSILON);
|
|
}
|
|
|
|
/**
|
|
* Test verbose mode (should not throw exception)
|
|
*/
|
|
@Test
|
|
void testVerboseMode() {
|
|
PageRank pageRank = new PageRank(2);
|
|
|
|
pageRank.setEdge(1, 2, 1);
|
|
|
|
// This should execute without throwing an exception
|
|
double[] result = pageRank.calculatePageRank(2, 0.85, 2, true);
|
|
|
|
assertNotNull(result);
|
|
}
|
|
}
|