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
32 changes: 16 additions & 16 deletions Problems/P/P_SSSP/P_SSSP.cs → Problems/P/P_SPSP/P_SPSP.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
using API.Interfaces;
using API.Interfaces.Graphs;
using API.Problems.NPComplete.NPC_TSP.Verifiers;
using API.Problems.P.P_SSSP.Solvers;
using API.Problems.P.P_SSSP.Verifiers;
using API.Problems.P.P_SSSP.Visualizations;
using API.Problems.P.P_SPSP.Solvers;
using API.Problems.P.P_SPSP.Verifiers;
using API.Problems.P.P_SPSP.Visualizations;
using SPADE;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace API.Problems.P.P_SSSP;
namespace API.Problems.P.P_SPSP;

class SSSP : IGraphProblem<SSSPSolver, SSSPVerifier, SSSPVisualization, UtilCollectionGraph>
class SPSP : IGraphProblem<SPSPSolver, SPSPVerifier, SPSPVisualization, UtilCollectionGraph>
{

// --- Fields ---
public string problemName { get; } = "Single Source Shortest Path Problem";
public string problemName { get; } = "Single Pair Shortest Path Problem";
public string problemLink { get; } = "https://en.wikipedia.org/wiki/Shortest_path_problem";
public string formalDefinition { get; } = "For a weighted graph G= (V,E) with non-negative edge weights and source vertex s \u2208 V, find the shortest path distance from s to every other vertex v \u2208 V, where path length is defined as the sum of edge weights along the path.";
public string problemDefinition { get; } = "Single Source Shortest Path (SSSP) in a weighted graph is the problem of finding the shortest path from a given source vertex s in the graph, such that the sum of edge weights along each path is minimized.";
public string formalDefinition { get; } = "For a weighted graph G= (V,E) with non-negative edge weights, a source vertex s \u2208 V, and a target vertex t \u2208 V, find the shortest path from s to t, where path length is defined as the sum of edge weights along the path.";
public string problemDefinition { get; } = "Single Pair Shortest Path (SPSP) in a weighted graph is the problem of finding the shortest path from a given source vertex s and target vertex t in the graph, such that the sum of edge weights along the path is minimized.";
public string source { get; } = "N/A";
public string sourceLink { get; } = "N/A";
private static string _defaultInstance =
Expand All @@ -33,9 +33,9 @@ class SSSP : IGraphProblem<SSSPSolver, SSSPVerifier, SSSPVisualization, UtilColl
public bool isWeighted { get; private set; }
private List<string> _nodes = new List<string>();
private List<KeyValuePair<string, string>> _edges = new List<KeyValuePair<string, string>>();
public SSSPSolver defaultSolver { get; } = new SSSPSolver();
public SSSPVerifier defaultVerifier { get; } = new SSSPVerifier();
public SSSPVisualization defaultVisualization { get; } = new SSSPVisualization();
public SPSPSolver defaultSolver { get; } = new SPSPSolver();
public SPSPVerifier defaultVerifier { get; } = new SPSPVerifier();
public SPSPVisualization defaultVisualization { get; } = new SPSPVisualization();
public UtilCollectionGraph graph { get; set; }
public string[] contributors { get; } = { "Rajit Nilkar", "Scott Barfuss" };

Expand All @@ -52,9 +52,9 @@ public List<KeyValuePair<string, string>> edges
}

// --- Methods Including Constructors ---
public SSSP() : this(_defaultInstance) { }
public SPSP() : this(_defaultInstance) { }

public SSSP(string GInput)
public SPSP(string GInput)
{
instance = GInput;

Expand Down Expand Up @@ -136,7 +136,7 @@ private static GraphParseResult ParseGraph(string graphInput)
}
}

throw new InvalidOperationException("Failed to parse SSSP instance.", lastError);
throw new InvalidOperationException("Failed to parse SPSP instance.", lastError);
}

private static void ValidateInstance(
Expand Down Expand Up @@ -164,7 +164,7 @@ private static void ValidateInstance(
throw new InvalidOperationException($"Edge target '{edge.To}' is not in N.");

if (edge.Weight < 0)
throw new InvalidOperationException("SSSP using Dijkstra's algorithm does not allow negative edge weights.");
throw new InvalidOperationException("SPSP using Dijkstra's algorithm does not allow negative edge weights.");
}
}

Expand All @@ -189,7 +189,7 @@ private static ParsedEdge ParseEdge(UtilCollection rawEdge)
int weight = int.Parse(rawEdge[1].ToString());

if (weight < 0)
throw new InvalidOperationException($"SSSP using Dijkstra's algorithm does not allow negative edge weights. Found edge weight: {weight}");
throw new InvalidOperationException($"SPSP using Dijkstra's algorithm does not allow negative edge weights. Found edge weight: {weight}");

return new ParsedEdge(GetFrom(endpoints), GetTo(endpoints), weight);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
using API.Interfaces.Graphs;
using SPADE;

namespace API.Problems.P.P_SSSP.Solvers;
namespace API.Problems.P.P_SPSP.Solvers;

class SSSPSolver : ISolver<SSSP>
class SPSPSolver : ISolver<SPSP>
{
// ----- Fields ----- //
public string solverName { get; } = "Dijkstra's Algorithm";
Expand All @@ -16,7 +16,7 @@ class SSSPSolver : ISolver<SSSP>
public bool timerHasExpired { get; set; }
PriorityQueue<string, int>? pq;

public string solve(SSSP problem)
public string solve(SPSP problem)
{
UtilCollectionGraph graph = problem.graph;
List<string> nodes = graph.Nodes.ToList().Select(n => n.ToString()).ToList();
Expand Down Expand Up @@ -207,7 +207,7 @@ private static bool LooksLikeCollection(UtilCollection u)
}

// GetSteps: The steps are returned as a list of strings, where each string representing a path in the certificate format
public List<Object> GetSteps(SSSP problem)
public List<Object> GetSteps(SPSP problem)
{
var steps = new List<Object>();
UtilCollectionGraph graph = problem.graph;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
using System.Linq;
using API.Interfaces;
using API.Interfaces.Graphs.GraphParser;
using API.Problems.P.P_SSSP.Solvers;
using API.Problems.P.P_SPSP.Solvers;

namespace API.Problems.P.P_SSSP.Verifiers;
namespace API.Problems.P.P_SPSP.Verifiers;

class SSSPVerifier : IVerifier<SSSP>
class SPSPVerifier : IVerifier<SPSP>
{
public string verifierName { get; } = "Single Source Shortest Path Verifier";
public string verifierDefinition { get; } = "Verifies the solution for the Single Source Shortest Path problem";
public string verifierName { get; } = "Single Pair Shortest Path Verifier";
public string verifierDefinition { get; } = "Verifies the solution for the Single Pair Shortest Path problem";
public string source { get; } = "";
public string[] contributors { get; } = { "Rajit Nilkar", "Scott Barfuss" };
private string _certificate = "";
public string certificate => _certificate;

public SSSPVerifier() { }
public SPSPVerifier() { }

// verify: takes a problem instance and a solution certificate,
// and returns true if the certificate is a valid solution to the problem instance,
// false otherwise
public bool verify(SSSP problem, string solution)
public bool verify(SPSP problem, string solution)
{
_certificate = solution ?? ""; // Reset certificate before verification

Expand All @@ -33,7 +33,7 @@ public bool verify(SSSP problem, string solution)
string sourceNode = problem.sourceNode;
string targetNode = problem.targetNode;

var adjacency = SSSPSolver.BuildAdjacencyList(problem.graph);
var adjacency = SPSPSolver.BuildAdjacencyList(problem.graph);

// Compute true shortest distance using Dijkstra's algorithm
int? shortest = ShortestDistance(adjacency, nodes, sourceNode, targetNode);
Expand Down Expand Up @@ -113,7 +113,7 @@ public bool verify(SSSP problem, string solution)
foreach (var (next, weight) in neighbors)
{
if (weight < 0)
throw new InvalidOperationException("SSSP does not allow negative edge weights.");
throw new InvalidOperationException("SPSP does not allow negative edge weights.");

if (visited.Contains(next))
continue; // Skip visited neighbors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@
using API.Interfaces.Graphs.GraphParser;
using API.Interfaces.JSON_Objects;
using API.Interfaces.JSON_Objects.Graphs;
using API.Problems.P.P_SSSP.Solvers;
using API.Problems.P.P_SPSP.Solvers;

namespace API.Problems.P.P_SSSP.Visualizations;
namespace API.Problems.P.P_SPSP.Visualizations;

class SSSPVisualization : IVisualization<SSSP>
class SPSPVisualization : IVisualization<SPSP>
{
public string visualizationName { get; } = "Single Source Shortest Path Visualization";
public string visualizationDefinition { get; } = "Visualizes the Single Source Shortest Path problem for non-negative weighted directed cyclic graphs using Dijkstra's algorithm";
public string visualizationName { get; } = "Single Pair Shortest Path Visualization";
public string visualizationDefinition { get; } = "Visualizes the Single Pair Shortest Path problem for non-negative weighted directed cyclic graphs using Dijkstra's algorithm";
public string source { get; } = "";
public string[] contributors { get; } = { "Rajit Nilkar", "Scott Barfuss", "Tiger Sant", "Malaya Witt" };
public string visualizationType => "Graph D3";
public ISolver solver { get; } = new SSSPSolver();
public ISolver solver { get; } = new SPSPSolver();

public SSSPVisualization() { }
public SPSPVisualization() { }

public API_JSON visualize(SSSP problem)
public API_JSON visualize(SPSP problem)
{
// For simplicity, we will just return a JSON representation of the graph
// In a real implementation, this would be more complex and would include visual elements
Expand All @@ -26,7 +26,7 @@ public API_JSON visualize(SSSP problem)

// SolvedVisualization: takes a problem instance and a solution certificate,
// and returns a visualization of the problem instance with the solution highlighted
public API_JSON SolvedVisualization(SSSP problem, string solution)
public API_JSON SolvedVisualization(SPSP problem, string solution)
{
if (string.IsNullOrWhiteSpace(solution) || solution.Trim() == "{}")
// No path found, return graph with no highlights
Expand Down Expand Up @@ -69,7 +69,7 @@ public API_JSON SolvedVisualization(SSSP problem, string solution)
return graph;
}

public List<API_JSON> StepsVisualization(SSSP problem, List<Object> steps)
public List<API_JSON> StepsVisualization(SPSP problem, List<Object> steps)
{
var result = new List<API_JSON>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,47 @@
using System.Linq;
using Xunit;
using API.Interfaces.JSON_Objects.Graphs;
using API.Problems.P.P_SSSP;
using API.Problems.P.P_SSSP.Solvers;
using API.Problems.P.P_SSSP.Verifiers;
using API.Problems.P.P_SSSP.Visualizations;
using API.Problems.P.P_SPSP;
using API.Problems.P.P_SPSP.Solvers;
using API.Problems.P.P_SPSP.Verifiers;
using API.Problems.P.P_SPSP.Visualizations;

namespace redux_tests;
#pragma warning disable CS1591

public class SSSP_Tests
public class SPSP_Tests
{
[Fact]
public void SSSP_Default_Instantiation()
public void SPSP_Default_Instantiation()
{
SSSP problem = new SSSP();
SPSP problem = new SPSP();
Assert.Equal("({1,2,3,4,5},{((1,2),4),((1,3),2),((2,3),1),((3,5),7),((2,4),3),((4,5),9)},1,5)", problem.instance);
Assert.Equal(problem.defaultInstance, problem.instance);
}

[Fact]
public void SSSP_Custom_Instantiation()
public void SPSP_Custom_Instantiation()
{
string instance = "({1,2,3,4,5,6},{((1,2),8),((1,3),4),((2,3),6),((3,5),5),((2,4),3),((4,5),9),((3,6),1),((4,6),12),((5,6),5)},1,6)";
var problem = new SSSP(instance);
var problem = new SPSP(instance);
Assert.Equal(instance, problem.instance);
}

[Theory]
[InlineData("({1,2}, {((1,2),-1)}),1,2")]
[InlineData("(({1,2}, {((1,2),-1)}),1,2")]
public void SSSP_Rejects_Negative_Edge_Weights(string instance)
public void SPSP_Rejects_Negative_Edge_Weights(string instance)
{
// Dijkstra's algorithm correctness depends on non-negative weights
// The SSSP problem must reject problem instances with negative-weights during parse time
Assert.Throws<InvalidOperationException>(() => new SSSP(instance));
Assert.Throws<InvalidOperationException>(() => new SPSP(instance));
}

[Fact]
public void SHORTESTPATH_Rejects_Source_Outside_Node_Set()
public void SPSP_Rejects_Source_Outside_Node_Set()
{
string instance = "(({1,2,3},{((1,2),1),((2,3),1)}),4,3)";
Assert.Throws<InvalidOperationException>(() => new SSSP(instance));
Assert.Throws<InvalidOperationException>(() => new SPSP(instance));
}

// ----- Solver ----- //
Expand All @@ -51,10 +51,10 @@ public void SHORTESTPATH_Rejects_Source_Outside_Node_Set()
[InlineData("({1,2,3,4,5},{((1,2),4),((1,3),2),((2,3),1),((3,5),7),((2,4),3),((4,5),9)},1,5)", "{1,3,5}")]
[InlineData("(({A,B,C,D},{((A,B),2),((B,D),2),((A,C),1),((C,D),1)}),A,D)", "{A,C,D}")]
[InlineData("(({1,2,3},((1,2))),1,3)", "{}")]
public void SSSP_Solver(string instance, string certificate)
public void SPSP_Solver(string instance, string certificate)
{
SSSP problem = new SSSP(instance);
SSSPSolver solver = new SSSPSolver();
SPSP problem = new SPSP(instance);
SPSPSolver solver = new SPSPSolver();
string solution = solver.solve(problem);
Assert.Equal(certificate, solution);
}
Expand All @@ -64,11 +64,11 @@ public void SSSP_Solver(string instance, string certificate)
[InlineData("({1,2,3,4,5,6},{((1,2),8),((1,3),4),((2,3),6),((3,5),5),((2,4),3),((4,5),9),((3,6),1),((4,6),12),((5,6),5)},1,6)", 5)]
[InlineData("(({1,2,3,4},{((1,2),1),((2,3),1),((3,4),1),((1,4),10)}),2,4)", 2)]
[InlineData("(({A,B,C,D},{((A,B),2),((B,D),2),((A,C),1),((C,D),1)}),A,D)", 2)]
public void SSSP_Solver_Returns_Valid_Minimum_Cost_Path(string instance, int expectedMinCost)
public void SPSP_Solver_Returns_Valid_Minimum_Cost_Path(string instance, int expectedMinCost)
{
SSSP problem = new SSSP(instance);
SSSPSolver solver = new SSSPSolver();
SSSPVerifier verifier = new SSSPVerifier();
SPSP problem = new SPSP(instance);
SPSPSolver solver = new SPSPSolver();
SPSPVerifier verifier = new SPSPVerifier();

string solution = solver.solve(problem);

Expand All @@ -80,8 +80,8 @@ public void SSSP_Solver_Returns_Valid_Minimum_Cost_Path(string instance, int exp
public void SSSP_Solver_Handles_Equal_Weights()
{
string instance = "(({1,2,3},{((1,2),1),((2,3),1)}),1,1)";
SSSP problem = new SSSP(instance);
SSSPSolver solver = new SSSPSolver();
SPSP problem = new SPSP(instance);
SPSPSolver solver = new SPSPSolver();

string solution = solver.solve(problem);

Expand All @@ -101,8 +101,8 @@ public void SSSP_Solver_Handles_Equal_Weights()
[InlineData("(({A,B,C,D},{((A,B),2),((B,D),2),((A,C),1),((C,D),1)}),A,D)", "{A,C,D}", true)]
public void SSSP_Verifier(string instance, string certificate, bool expected)
{
SSSP problem = new SSSP(instance);
SSSPVerifier verifier = new SSSPVerifier();
SPSP problem = new SPSP(instance);
SPSPVerifier verifier = new SPSPVerifier();
bool result = verifier.verify(problem, certificate);
Assert.Equal(expected, result);
}
Expand All @@ -111,8 +111,8 @@ public void SSSP_Verifier(string instance, string certificate, bool expected)
public void SSSP_Verifier_Rejects_Empty_Certificates_When_Path_Exists()
{
string instance = "({1,2,3,4,5},{((1,2),4),((1,3),2),((2,3),1),((3,5),7),((2,4),3),((4,5),9)},1,5)";
SSSP problem = new SSSP(instance);
SSSPVerifier verifier = new SSSPVerifier();
SPSP problem = new SPSP(instance);
SPSPVerifier verifier = new SPSPVerifier();
Assert.False(verifier.verify(problem, "{}"));
}

Expand All @@ -121,8 +121,8 @@ public void SSSP_Verifier_Rejects_Empty_Certificates_When_Path_Exists()
public void StepsVisualization_Highlights_Final_Path_Nodes_As_Solution()
{
string instance = "({1,2,3,4,5},{((1,2),4),((1,3),2),((2,3),1),((3,5),7),((2,4),3),((4,5),9)},1,5)";
SSSP problem = new SSSP(instance);
SSSPVisualization visualization = new SSSPVisualization();
SPSP problem = new SPSP(instance);
SPSPVisualization visualization = new SPSPVisualization();

var steps = new List<object> { "{1,3,5}" };
var frames = visualization.StepsVisualization(problem, steps);
Expand All @@ -134,10 +134,10 @@ public void StepsVisualization_Highlights_Final_Path_Nodes_As_Solution()

// ----- Helper ----- //
// The purpose of this helper function is to parse a certificate like "{1,3,5}" and sums the edge weights along the path
private static int TotalPathWeight(SSSP problem, string certificate)
private static int TotalPathWeight(SPSP problem, string certificate)
{
var nodes = certificate.Trim('{', '}').Split(',').ToList();
var adjacency = SSSPSolver.BuildAdjacencyList(problem.graph);
var adjacency = SPSPSolver.BuildAdjacencyList(problem.graph);

int total = 0;
for (int i = 0; i < nodes.Count - 1; i++)
Expand Down