Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem Graph #51

Merged
merged 92 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
892fac0
Replace g6 with reactflow
Elscrux Jan 29, 2024
037e35d
Add test problem graph using reactflow
Elscrux Jan 29, 2024
382fded
Run prettier
Elscrux Jan 29, 2024
766cec1
Add some comments
Elscrux Feb 6, 2024
621689a
Remove border around the graph
Elscrux Feb 6, 2024
28f7e26
Add color function
Elscrux Feb 6, 2024
61256db
FIrst pass
Elscrux Jul 23, 2024
7b5aec2
Rename DecisionNode to SolverNode
Elscrux Jul 23, 2024
6e5e814
Define KIT green as theme color
Elscrux Jul 23, 2024
7a41af0
Initial second pass on problem graph
Elscrux Jul 23, 2024
a5d8870
refactor: Replace problemType with problemTypeId
Elscrux Jul 30, 2024
2b26dab
fix: Remove unused variable
Elscrux Jul 30, 2024
a66aceb
feat: Further updates
Elscrux Jul 30, 2024
5fcd327
fix: Warning with value nested in textarea
Elscrux Aug 10, 2024
20a9552
fix: Account for multiple subproblems in x coordinate calculation
Elscrux Aug 10, 2024
4f77587
fix: Disable solver dropdown when solving process has started
Elscrux Aug 10, 2024
e8e7114
fix: Remove subproblem nodes that are no longer used
Elscrux Aug 10, 2024
704d7a4
fix: Update nodes directly if no parent node can be found
Elscrux Aug 10, 2024
e8c192a
refactor: Remove unused node update mapper parameter
Elscrux Aug 10, 2024
bae6e48
fix: Fetch up to date node data when updating node itself
Elscrux Aug 10, 2024
c3fa6c4
feat: Add spinner for solving button
Elscrux Aug 10, 2024
afc8e6d
feat: Add disconnect buttons
Elscrux Aug 10, 2024
272fa3e
fix: Positioning of dropdown button
Elscrux Aug 10, 2024
892b401
chore: Remove old todo
Elscrux Aug 10, 2024
4574352
refactor: Remove code duplicates for disconnect buttons
Elscrux Aug 10, 2024
d111976
fix: Don't show disconnect button when solver can't be changed
Elscrux Aug 10, 2024
f047438
refactor: add utility canProblemSolverBeUpdated function
Elscrux Aug 10, 2024
4651e2f
fix: Bad problem header scaling
Elscrux Aug 10, 2024
5ddc438
fix: Missing empty space when dropdown is hidden
Elscrux Aug 10, 2024
cb334e1
chore: Better variable naming
Elscrux Aug 10, 2024
d842ca7
fix: edges not being connected due to missing handles
Elscrux Aug 10, 2024
8ad09cc
refactor: Replace solve callback with native implementation using upd…
Elscrux Aug 10, 2024
7e2fa3f
chore: remove redundant state patches - only setting to solving is a …
Elscrux Aug 10, 2024
4e10b95
fix: Replace arbitrary high width with 100%
Elscrux Aug 10, 2024
376e44b
chore: improve parameter name
Elscrux Aug 10, 2024
d7bb0a4
chore: remove old code
Elscrux Aug 10, 2024
4fe9ba9
feat: Change ready to solve icon to play button that can start a solver
Elscrux Aug 10, 2024
b8bdd2a
docs: Explain SolverContext
Elscrux Aug 13, 2024
802f02e
fix: Add key to accordion item
Elscrux Aug 13, 2024
734b53f
feat: update parent problem after subproblem was fully solved
Elscrux Aug 13, 2024
608af5b
fix: Bottom handle appearing for solved problem nodes
Elscrux Aug 13, 2024
a9ab6d3
refactor: Save multiProblem value
Elscrux Aug 13, 2024
c37aecb
feat: Improve styling
Elscrux Aug 13, 2024
d562a5f
fix: Html error
Elscrux Aug 13, 2024
6ff3a60
feat: Update nodes when starting to solve
Elscrux Aug 13, 2024
1fe87a8
fix: Only schedule update for unique node once
Elscrux Aug 13, 2024
44af463
refactor: Use node state to track state of the problem node globally
Elscrux Aug 13, 2024
51b08ae
feat: Set node state to solving when solve button is pressed for imme…
Elscrux Aug 13, 2024
746ed82
feat: Show solution when main problem is solved
Elscrux Aug 17, 2024
69e5092
refactor: Add SolverNodeContent to merge code from SolverNode and Pro…
Elscrux Aug 17, 2024
e72b751
feat: Add accordion to hide preview of MaxCut initially
Elscrux Aug 17, 2024
1ed1fa4
refactor: Streamline state keeping for text input to one place and re…
Elscrux Aug 17, 2024
f77b00e
feat: Add reset button
Elscrux Aug 17, 2024
72fd8d4
feat: Add SolverConfiguration
Elscrux Aug 17, 2024
c5125b5
chore: Remove old GoButton
Elscrux Aug 17, 2024
dcb9052
chore: Remove TestGraphDisplay
Elscrux Aug 17, 2024
01692d0
fix: ProblemNode state not updating when problems update
Elscrux Aug 17, 2024
8dabdfe
chore: Remove old function
Elscrux Aug 17, 2024
20494fd
chore: Remove old update loop
Elscrux Aug 17, 2024
e50a409
fix: Add missing dependencies
Elscrux Aug 17, 2024
285df46
fix: Add additional condition
Elscrux Aug 17, 2024
b1ed879
feat: Fit view only when nodes are added or removed
Elscrux Aug 17, 2024
7883756
refactor: Simplify code
Elscrux Aug 17, 2024
ef44cc1
refactor: Make TextArea generic
Elscrux Aug 17, 2024
0129c20
feat: Add restart button
Elscrux Aug 17, 2024
7380fe8
refactor: Streamline SAT
Elscrux Aug 17, 2024
67076cc
fix: Add missing type annotation
Elscrux Aug 18, 2024
47bc880
fix: Use placeholder property
Elscrux Aug 20, 2024
e988761
fix: SonarLint issues
Elscrux Aug 20, 2024
9b17407
feat: Show all anomalies by default
Elscrux Aug 20, 2024
b582b52
fix: When starting to solve a problem, update problem node only after…
Elscrux Aug 27, 2024
960fe34
fix: Solver selection in ProblemList not updating properly
Elscrux Aug 27, 2024
9d3a155
fix: Add missing dependency removeSolverNodes to updateSolverNodes
Elscrux Aug 27, 2024
a527841
fix: Only update node data to prevent reverting the position
Elscrux Aug 27, 2024
cafbf31
feat: Add timeout for updating base node
Elscrux Aug 27, 2024
fb17ac8
feat: Allow toggling accordion sections
Elscrux Aug 27, 2024
3bdb492
feat: Scroll window when scrolling on problem graph
Elscrux Aug 27, 2024
1ead9a8
feat: Scroll to solution once the base problem is solved
Elscrux Aug 27, 2024
5abb689
chore: Simplify QUBO mask
Elscrux Aug 27, 2024
b2d038b
fix: Only scroll to solution view when it appears
Elscrux Aug 28, 2024
2fc020a
feat: Scroll to problem graph view when it appears
Elscrux Aug 28, 2024
a3aafd3
feat: Add VRP mask
Elscrux Aug 28, 2024
aca2a58
feat: Add TSP mask
Elscrux Sep 3, 2024
2d0b753
fix: Use problemId, not node id for update
Elscrux Sep 3, 2024
0b35e24
feat: Decrease timeout to 500ms
Elscrux Sep 3, 2024
f6668c1
fix: Update all parent problems when subroutines finish not just the …
Elscrux Sep 3, 2024
7ad983b
feat: Add links to problem examples
Elscrux Sep 3, 2024
238af3e
feat: Update problem tags
Elscrux Sep 3, 2024
09cd0e7
fix: Handle lists of problems with subroutines properly by working wi…
Elscrux Sep 3, 2024
199e0bd
chore: Remove unnecessary line
Elscrux Sep 6, 2024
e2d9a33
chore: Remove unnecessary VStack
Elscrux Sep 6, 2024
74b1cbb
fix: Add more space for solver name
Elscrux Sep 6, 2024
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
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
Loading