Skip to content

Commit

Permalink
Merge pull request #51 from ProvideQ/feat/problem-graph
Browse files Browse the repository at this point in the history
Problem Graph
  • Loading branch information
koalamitice authored Sep 6, 2024
2 parents 893f999 + 74b1cbb commit f7c2f0d
Show file tree
Hide file tree
Showing 40 changed files with 2,520 additions and 1,120 deletions.
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
"format": "prettier --write .",
"test": "jest"
},
"resolutions": {
"d3-interpolate": "2.0.1"
},
"dependencies": {
"@antv/g6": "^4.7.16",
"@chakra-ui/react": "^2.3.1",
"@emotion/react": "11",
"@emotion/styled": "11",
Expand All @@ -26,7 +22,8 @@
"react-dom": "18.2.0",
"react-icons": "^4.4.0",
"react-multi-select-component": "^4.3.4",
"react-simple-code-editor": "^0.13.0"
"react-simple-code-editor": "^0.13.0",
"reactflow": "^11.10.3"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
Expand Down
131 changes: 88 additions & 43 deletions src/api/ToolboxAPI.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,111 @@
import { MetaSolverSetting } from "./data-model/MetaSolverSettings";
import { ProblemSolver } from "./data-model/ProblemSolver";
import { Solution } from "./data-model/Solution";
import { SolutionStatus } from "./data-model/SolutionStatus";
import { SolveRequest } from "./data-model/SolveRequest";
import { SubRoutineDefinition } from "./data-model/SubRoutineDefinition";
import { getInvalidProblemDto, ProblemDto } from "./data-model/ProblemDto";
import { ProblemSolverInfo } from "./data-model/ProblemSolverInfo";
import { ProblemState } from "./data-model/ProblemState";
import { SubRoutineDefinitionDto } from "./data-model/SubRoutineDefinitionDto";

/**
* Getter for the base url of the toolbox API.
*/
export const baseUrl = () => process.env.NEXT_PUBLIC_API_BASE_URL;

export async function fetchProblem<T>(
problemTypeId: string,
problemId: string
): Promise<ProblemDto<T>> {
return fetch(`${baseUrl()}/problems/${problemTypeId}/${problemId}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((json) => {
const data = json as ProblemDto<T>;

// Explicitly set solverId to undefined if it is null
if (data.solverId === null) {
data.solverId = undefined;
}

return data;
})
.catch((reason) => {
return {
...getInvalidProblemDto(),
error: `${reason}`,
};
});
}

export async function postProblem<T>(
problemType: string,
solveRequest: SolveRequest<T>
): Promise<Solution> {
return fetch(`${baseUrl()}/solve/${problemType}`, {
problemTypeId: string,
problemRequest: ProblemDto<T>
): Promise<ProblemDto<T>> {
return fetch(`${baseUrl()}/problems/${problemTypeId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(solveRequest),
body: JSON.stringify(problemRequest),
})
.then((response) => response.json())
.then((json) => json as ProblemDto<T>)
.catch((reason) => {
return {
...problemRequest,
error: `${reason}`,
};
});
}

export async function patchProblem<T>(
problemTypeId: string,
problemId: string,
updateParameters: { input?: any; solverId?: string; state?: ProblemState }
): Promise<ProblemDto<T>> {
let url = `${baseUrl()}/problems/${problemTypeId}/${problemId}`;
console.log(url);
return fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(updateParameters),
})
.then((response) => response.json())
.then((json) => json as Solution)
.then((json) => json as ProblemDto<T>)
.catch((reason) => {
return {
id: -1,
status: SolutionStatus.INVALID,
solverName: "",
executionMilliseconds: 0,
solutionData: "",
debugData: "",
metaData: "",
...getInvalidProblemDto(),
error: `${reason}`,
};
});
}

export async function fetchSolvers(
problemType: string
): Promise<ProblemSolver[]> {
return fetch(`${baseUrl()}/solvers/${problemType}`, {
problemTypeId: string
): Promise<ProblemSolverInfo[]> {
return fetch(`${baseUrl()}/solvers/${problemTypeId}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((json) => json as ProblemSolver[])
.then(async (response) => response.json())
.then((json) => json as ProblemSolverInfo[])
.catch((reason) => {
console.error(reason);
alert(`Could not retrieve solvers of type ${problemType}.`);
alert(`Could not retrieve solvers of type ${problemTypeId}.`);
return [];
});
}

export async function fetchSubRoutines(
problemType: string,
problemTypeId: string,
solverId: string
): Promise<SubRoutineDefinition[]> {
): Promise<SubRoutineDefinitionDto[]> {
return fetch(
`${baseUrl()}/sub-routines/${problemType}?${new URLSearchParams({
`${baseUrl()}/sub-routines/${problemTypeId}?${new URLSearchParams({
id: solverId,
})}`,
{
Expand All @@ -78,18 +123,18 @@ export async function fetchSubRoutines(
});
}

export async function fetchMetaSolverSettings(
problemType: string
): Promise<MetaSolverSetting[]> {
return fetch(`${baseUrl()}/meta-solver/settings/${problemType}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.catch((reason) => {
console.log(reason);
return [];
});
}
// export async function fetchMetaSolverSettings(
// problemTypeId: string
// ): Promise<MetaSolverSetting[]> {
// return fetch(`${baseUrl()}/meta-solver/settings/${problemTypeId}`, {
// method: "GET",
// headers: {
// "Content-Type": "application/json",
// },
// })
// .then((response) => response.json())
// .catch((reason) => {
// console.log(reason);
// return [];
// });
// }
34 changes: 34 additions & 0 deletions src/api/data-model/ProblemDto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ProblemState } from "./ProblemState";
import { getInvalidSolutionObject, SolutionObject } from "./SolutionObject";
import { SubRoutineReferenceDto } from "./SubRoutineReferenceDto";

export interface ProblemDto<T> {
id: string;
typeId: string;
input: T;
solution: SolutionObject;
state: ProblemState;
solverId?: string;
subProblems: SubRoutineReferenceDto[];
error: string;
}

export function getInvalidProblemDto<T>(): ProblemDto<T> {
return {
error: "",
id: "",
input: {} as T,
solution: getInvalidSolutionObject(),
solverId: "",
state: ProblemState.READY_TO_SOLVE,
subProblems: [],
typeId: "",
};
}

export function canProblemSolverBeUpdated(problem: ProblemDto<any>): boolean {
return (
problem.state === ProblemState.NEEDS_CONFIGURATION ||
problem.state === ProblemState.READY_TO_SOLVE
);
}
4 changes: 0 additions & 4 deletions src/api/data-model/ProblemSolver.ts

This file was deleted.

4 changes: 4 additions & 0 deletions src/api/data-model/ProblemSolverInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface ProblemSolverInfo {
id: string;
name: string;
}
6 changes: 6 additions & 0 deletions src/api/data-model/ProblemState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum ProblemState {
NEEDS_CONFIGURATION = "NEEDS_CONFIGURATION",
READY_TO_SOLVE = "READY_TO_SOLVE",
SOLVING = "SOLVING",
SOLVED = "SOLVED",
}
12 changes: 0 additions & 12 deletions src/api/data-model/Solution.ts

This file was deleted.

26 changes: 26 additions & 0 deletions src/api/data-model/SolutionObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { SolutionStatus } from "./SolutionStatus";

export interface SolutionObject {
/**
* UUID of the solution.
*/
id: string;
status: SolutionStatus;
metaData: string;
solutionData: any;
debugData: string;
solverName: string;
executionMilliseconds: number;
}

export function getInvalidSolutionObject(): SolutionObject {
return {
id: "",
status: SolutionStatus.INVALID,
metaData: "",
solutionData: undefined,
debugData: "",
solverName: "",
executionMilliseconds: -1,
};
}
7 changes: 4 additions & 3 deletions src/api/data-model/SolutionStatus.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum SolutionStatus {
INVALID,
COMPUTING,
SOLVED,
INVALID = "INVALID",
COMPUTING = "COMPUTING",
SOLVED = "SOLVED",
ERROR = "ERROR",
}
28 changes: 0 additions & 28 deletions src/api/data-model/SolveRequest.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
* A sub-routine definition describes which problem type needs to be solved by a
* sub-routine and why it needs to be solved.
*/
export interface SubRoutineDefinition {
export interface SubRoutineDefinitionDto {
/**
* Identifies the type of problem that needs to be solved with the described
* sub-routine.
*/
type: string;
typeId: string;
/**
* Describes why this sub-routine is required to solve a bigger problem.
*/
Expand Down
6 changes: 6 additions & 0 deletions src/api/data-model/SubRoutineReferenceDto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { SubRoutineDefinitionDto } from "./SubRoutineDefinitionDto";

export interface SubRoutineReferenceDto {
subRoutine: SubRoutineDefinitionDto;
subProblemIds: string[];
}
24 changes: 21 additions & 3 deletions src/components/landing-page/ProblemChooser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const ProblemChooser = (props: GridProps) => (
<ProblemCard
href="solve/MaxCut"
new={false}
tags={["QAOA", "simulated"]}
tags={["QAOA"]}
problemName="MaxCut"
description="For a given undirected, weighted graph, this algorithm finds a cut that is a maximum in some way or another."
/>
Expand All @@ -25,7 +25,7 @@ export const ProblemChooser = (props: GridProps) => (
<ProblemCard
href="solve/FeatureModelAnomaly"
new={false}
tags={["sub-routines"]}
tags={["sub-routines", "SAT"]}
problemName="Feature Model Anomaly"
description="Check whether a given feature model in the UVL format is void or if it has dead features."
/>
Expand All @@ -34,10 +34,28 @@ export const ProblemChooser = (props: GridProps) => (
<ProblemCard
href="solve/QUBO"
new={true}
tags={["QAOA"]}
tags={["QAOA", "Annealing"]}
problemName="QUBO"
description="For a quadratic term with binary decision variables, find the variable assignment minimizing the term."
/>
</GridItem>
<GridItem>
<ProblemCard
href="solve/VehicleRouting"
new={true}
tags={["sub-routines", "QUBO", "Clustering"]}
problemName="Vehicle Routing"
description="What is the optimal set of routes for a fleet of vehicles to traverse in order to deliver to a given set of customers?"
/>
</GridItem>
<GridItem>
<ProblemCard
href="solve/TSP"
new={true}
tags={["sub-routines", "qubo"]}
problemName="Traveling Salesperson Problem"
description="Given a list of cities and the distances between them, find the shortest possible route that visits each city exactly once and returns to the origin city."
/>
</GridItem>
</Grid>
);
Loading

0 comments on commit f7c2f0d

Please sign in to comment.