From 3e08638aeb07808cfcf0879d0075a95485445f2b Mon Sep 17 00:00:00 2001 From: Goel Biju Date: Sat, 27 Feb 2021 15:47:32 +0000 Subject: [PATCH] Implement generation queue and add DTLZ2 script (#16) --- documents/minutes/Project Meeting - 4.docx | Bin 16465 -> 16500 bytes documents/minutes/~$oject Meeting - 4.docx | Bin 162 -> 0 bytes .../src/state/actions/action.types.tsx | 2 +- .../src/state/actions/socket.actions.tsx | 18 ++-- .../src/state/reducers/common.reducer.tsx | 26 +++-- .../frontend-common/src/state/state.types.tsx | 5 +- .../src/visualisation.component.tsx | 7 +- .../src/components/mainAppBar.component.tsx | 3 +- .../visualisationContainer.component.tsx | 90 +++++++++++++----- scripts/client.py | 3 - scripts/{sample_data.py => dtlz1.py} | 6 +- scripts/dtlz2.py | 51 ++++++++++ 12 files changed, 146 insertions(+), 65 deletions(-) delete mode 100644 documents/minutes/~$oject Meeting - 4.docx rename scripts/{sample_data.py => dtlz1.py} (87%) create mode 100644 scripts/dtlz2.py diff --git a/documents/minutes/Project Meeting - 4.docx b/documents/minutes/Project Meeting - 4.docx index 05be19664b22d3ce3de80b82509be5602d32ab8c..db53806fc7c1509db11c74c5f2e2dc12012697c9 100644 GIT binary patch delta 5601 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 delta 5556 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 diff --git a/packages/frontend-common/src/state/actions/action.types.tsx b/packages/frontend-common/src/state/actions/action.types.tsx index 7a114f8..79a8b04 100644 --- a/packages/frontend-common/src/state/actions/action.types.tsx +++ b/packages/frontend-common/src/state/actions/action.types.tsx @@ -16,12 +16,12 @@ export const FetchRunsType = `${microFrontendMessageId}:fetch_runs`; export const FetchRunsResultType = `${microFrontendMessageId}:fetch_runs_result`; export const FetchRunResultType = `${microFrontendMessageId}:fetch_run_result`; export const VisualisationNameType = `${microFrontendMessageId}:set_visualisation_name`; +export const DataRequestType = `${microFrontendMessageId}:data_request`; export const DataType = `${microFrontendMessageId}:set_data`; // Socket related actions export const InitiateSocketSuccessType = `${microFrontendMessageId}:initiate_socket_success`; export const DisconnectSocketSuccessType = `${microFrontendMessageId}:disconnect_socket_success`; -// export const RunGenerationSuccessType = `${microFrontendMessageId}:run_generation_success`; export const SubscribedType = `${microFrontendMessageId}:set_subscribed`; export interface RegisterRoutePayload { diff --git a/packages/frontend-common/src/state/actions/socket.actions.tsx b/packages/frontend-common/src/state/actions/socket.actions.tsx index 7898640..83055d0 100644 --- a/packages/frontend-common/src/state/actions/socket.actions.tsx +++ b/packages/frontend-common/src/state/actions/socket.actions.tsx @@ -2,6 +2,7 @@ import { Action } from "redux"; import ioclient from "socket.io-client"; import { ActionType, ThunkResult } from "../state.types"; import { + DataRequestType, DisconnectSocketSuccessType, InitiateSocketSuccessType, @@ -24,15 +25,6 @@ export const disconnectSocketSuccess = (): Action => ({ type: DisconnectSocketSuccessType, }); -// export const runGenerationSuccess = ( -// generation: number -// ): ActionType => ({ -// type: RunGenerationSuccessType, -// payload: { -// generation, -// }, -// }); - export const setSubscribed = ( subscribed: boolean ): ActionType => ({ @@ -90,6 +82,10 @@ export const subscribeToGenerations = ( }; }; +export const dataRequest = (): Action => ({ + type: DataRequestType, +}); + // Retrieve the data from a run given the ID and generation number export const fetchData = ( dataId: string, @@ -98,8 +94,10 @@ export const fetchData = ( return async (dispatch, getState) => { const { socket } = getState().frontend.configuration; - // socketConnected if (socket && socket.connected) { + // Dispatch the fetch data request + dispatch(dataRequest()); + // Emit the socket event socket.emit("data", { dataId, diff --git a/packages/frontend-common/src/state/reducers/common.reducer.tsx b/packages/frontend-common/src/state/reducers/common.reducer.tsx index 8571f53..c601d31 100644 --- a/packages/frontend-common/src/state/reducers/common.reducer.tsx +++ b/packages/frontend-common/src/state/reducers/common.reducer.tsx @@ -1,6 +1,7 @@ import * as log from "loglevel"; import { DataPayload, + DataRequestType, DataType, DisconnectSocketSuccessType, FetchRunResultType, @@ -33,14 +34,13 @@ export const initialState: FrontendState = { }, settingsLoaded: false, socket: null, - // socketConnected: false, subscribed: false, }, runs: [], selectedRun: null, selectedVisualisation: "", data: null, - // currentGeneration: 0, + fetchingData: false, }; const updatePlugins = ( @@ -143,7 +143,6 @@ export function handleInitiateSocket( configuration: { ...state.configuration, socket: payload.socket, - // socketConnected: true, }, }; } @@ -154,21 +153,10 @@ export function handleDisconnectSocket(state: FrontendState): FrontendState { configuration: { ...state.configuration, socket: null, - // socketConnected: false, }, }; } -// export function handleRunGeneration( -// state: FrontendState, -// payload: RunGenerationPayload -// ): FrontendState { -// return { -// ...state, -// currentGeneration: payload.generation, -// }; -// } - export function handleSubscribed( state: FrontendState, payload: SubscribedPayload @@ -182,6 +170,13 @@ export function handleSubscribed( }; } +export function handleDataRequest(state: FrontendState): FrontendState { + return { + ...state, + fetchingData: true, + }; +} + export function handleData( state: FrontendState, payload: DataPayload @@ -189,6 +184,7 @@ export function handleData( return { ...state, data: payload.data, + fetchingData: false, }; } @@ -201,9 +197,9 @@ const CommonReducer = createReducer(initialState, { [FetchRunResultType]: handleFetchRun, [InitiateSocketSuccessType]: handleInitiateSocket, [DisconnectSocketSuccessType]: handleDisconnectSocket, - // [RunGenerationSuccessType]: handleRunGeneration, [VisualisationNameType]: handleVisualisationName, [SubscribedType]: handleSubscribed, + [DataRequestType]: handleDataRequest, [DataType]: handleData, }); diff --git a/packages/frontend-common/src/state/state.types.tsx b/packages/frontend-common/src/state/state.types.tsx index e646141..098a7e4 100644 --- a/packages/frontend-common/src/state/state.types.tsx +++ b/packages/frontend-common/src/state/state.types.tsx @@ -38,16 +38,13 @@ export interface FrontendState { urls: SettingsUrls; settingsLoaded: boolean; socket: SocketIOClient.Socket | null; - // TODO: Add subscribed to state? - // TODO: Remove socketConnected - // socketConnected: boolean; subscribed: boolean; }; runs: Run[]; selectedRun: Run | null; selectedVisualisation: string; data: Data; - // currentGeneration: number; + fetchingData: boolean; } export interface StateType { diff --git a/packages/frontend-plugin/src/visualisation.component.tsx b/packages/frontend-plugin/src/visualisation.component.tsx index 3d179e0..e8638de 100644 --- a/packages/frontend-plugin/src/visualisation.component.tsx +++ b/packages/frontend-plugin/src/visualisation.component.tsx @@ -24,13 +24,14 @@ const VisualisationComponent = (props: VCProps): React.ReactElement => { const chartRef: React.RefObject = React.createRef(); const margin = { - top: 10, + top: 50, right: 30, bottom: 30, left: 60, }; + const width = 760 - margin.left - margin.right; - const height = 800 - margin.top - margin.bottom; + const height = 450 - margin.top - margin.bottom; const xScale: d3.ScaleLinear = d3 .scaleLinear() @@ -178,7 +179,7 @@ const VisualisationComponent = (props: VCProps): React.ReactElement => { .attr("cx", (d) => xScale(d[0]) as number) .attr("cy", (d) => yScale(d[1]) as number) .attr("r", 3) - .style("fill", "#69b3a2"); + .style("fill", "blue"); }, [currentChart, xScale, yScale] ); diff --git a/packages/frontend/src/components/mainAppBar.component.tsx b/packages/frontend/src/components/mainAppBar.component.tsx index 1088987..00652f9 100644 --- a/packages/frontend/src/components/mainAppBar.component.tsx +++ b/packages/frontend/src/components/mainAppBar.component.tsx @@ -1,7 +1,6 @@ import { AppBar, CssBaseline, Link, Toolbar, Typography } from '@material-ui/core'; import { createStyles, makeStyles } from '@material-ui/core/styles'; import React from 'react'; -import { Link as RouterLink } from 'react-router-dom'; const useStyles = makeStyles(() => createStyles({ @@ -20,7 +19,7 @@ const MainAppBar = (): React.ReactElement => { - + Visualising Optimisation Data diff --git a/packages/frontend/src/pages/visualisationContainer.component.tsx b/packages/frontend/src/pages/visualisationContainer.component.tsx index 619269e..d1cb86c 100644 --- a/packages/frontend/src/pages/visualisationContainer.component.tsx +++ b/packages/frontend/src/pages/visualisationContainer.component.tsx @@ -17,6 +17,8 @@ import { Action, AnyAction } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; // TODO: Use queue (in state?) +// TODO: Try to instead of having an object, store the list in the component +// then perform actions using setState on the list. // class GenerationQueue { // generations: number[]; @@ -25,13 +27,14 @@ import { ThunkDispatch } from 'redux-thunk'; // } // // Add a generation (enqueue) -// append(generation: number): void { +// push(generation: number): void { // this.generations.push(generation); // } // // Remove a generation (dequeue) // pop(): number | undefined { // if (!this.isEmpty()) { +// console.log('Returning number'); // return this.generations.shift(); // } else { // return -1; @@ -60,7 +63,6 @@ interface VCDispatchProps { initiateSocket: (runId: string) => Promise; subscribeToGenerations: (runId: string) => Promise; fetchData: (dataId: string, generation: number) => Promise; - // setCurrentGeneration: (generation: number) => Action; setSubscribed: (subscribed: boolean) => Action; setData: (data: Data) => Action; } @@ -69,9 +71,8 @@ interface VCStateProps { selectedRun: Run | null; selectedVisualisation: string; socket: SocketIOClient.Socket | null; - // socketConnected: boolean; - // currentGeneration: number; subscribed: boolean; + fetchingData: boolean; } type VCProps = VCViewProps & VCDispatchProps & VCStateProps; @@ -79,7 +80,6 @@ type VCProps = VCViewProps & VCDispatchProps & VCStateProps; const VisualisationContainer = (props: VCProps): React.ReactElement => { const { socket, - // socketConnected, initiateSocket, fetchRun, setVisualisationName, @@ -88,25 +88,52 @@ const VisualisationContainer = (props: VCProps): React.ReactElement => { selectedRun, selectedVisualisation, subscribeToGenerations, - // currentGeneration, fetchData, - // setCurrentGeneration, subscribed, setSubscribed, setData, + fetchingData, } = props; const [loadedRun, setLoadedRun] = React.useState(false); - // const [subscribed, setSubscribed] = React.useState(false); - const [currentGeneration, setCurrentGeneration] = React.useState(-1); + // Create a generation queue object in state + // const [generationQueue] = React.useState(new GenerationQueue()); + const [generationQueue, setGenerationQueue] = React.useState([]); + + const pushToGQ = (generation: number) => { + setGenerationQueue([...generationQueue, generation]); + }; + + // Remove a generation (dequeue) + const popFromGQ = (): number => { + if (!isEmpty()) { + const n = generationQueue.shift(); + console.log('Returning n: ', -1); + if (n) { + return n; + } else { + return -1; + } + } else { + console.log('Queue empty'); + return -1; + } + }; + + // Check if the queue is empty + const isEmpty = (): boolean => { + if (generationQueue.length === 0) { + return true; + } else { + return false; + } + }; + // TODO: * Be careful about where we place receiving data from sockets (prevent duplicate data) - // * Prevent multiple event handlers (subcribed to state, replace with socketConnected?) - // DONE: Remove unnecessary items from state e.g. socketConnected? (replace with socket.connected?) + // * Prevent multiple event handlers (subcribed to state) // TODO: * Wait until data has been received from server after firing request, before firing next request - // DONE: Remove/correct currentGeneration in state? - // DONE: currentGeneration should not be in state? Just in component. // Load run information React.useEffect(() => { @@ -150,12 +177,16 @@ const VisualisationContainer = (props: VCProps): React.ReactElement => { // When we receive "subscribed" from // server attach the callback function socket.on('generation', (generation: number) => { - // console.log('Generation received: ', generation); - setCurrentGeneration(generation); + // setCurrentGeneration(generation); + + // Add the generation to the queue. + // generationQueue.push(generation); + pushToGQ(generation); + console.log('Generation added to queue: ', generation); + console.log('Queue: ', generationQueue); }); // Handle the data response event - // eslint-disable-next-line @typescript-eslint/no-explicit-any socket.on('data', (data: Data) => { console.log('Data received for current generation: ', data); setData(data); @@ -169,18 +200,35 @@ const VisualisationContainer = (props: VCProps): React.ReactElement => { // TODO: Ensure this does not request multiple times // Handle fetching new data on generation changes React.useEffect(() => { + console.log('Got new update'); + // Fetch the data for the new generation if (selectedRun && socket && socket.connected) { if (currentGeneration < 0) { // Initialise current generation with current run information setCurrentGeneration(selectedRun.currentGeneration); console.log('Set current generation to: ', selectedRun.currentGeneration); + + pushToGQ(selectedRun.currentGeneration); + console.log('Queue: ', generationQueue); } else { - // console.log('Requesting data'); - fetchData(selectedRun.dataId, currentGeneration); + // Fetch data if there are currently no requests + if (!fetchingData) { + // Get the next generation to fetch + console.log(generationQueue); + const generation = popFromGQ(); + console.log('generation from queue: ', generation); + if (generation && generation !== -1) { + // TODO: Is this correct calling setCurrentGeneration here? + setCurrentGeneration(generation); + + console.log('Requesting data'); + fetchData(selectedRun.dataId, generation); + } + } } } - }, [selectedRun, socket, currentGeneration]); + }, [selectedRun, socket, currentGeneration, fetchingData, generationQueue]); return ( @@ -231,7 +279,6 @@ const mapDispatchToProps = (dispatch: ThunkDispatch) initiateSocket: (runId: string) => dispatch(initiateSocket(runId)), subscribeToGenerations: (runId: string) => dispatch(subscribeToGenerations(runId)), fetchData: (dataId: string, generation: number) => dispatch(fetchData(dataId, generation)), - // setCurrentGeneration: (generation: number) => dispatch(runGenerationSuccess(generation)), setSubscribed: (subscribed: boolean) => dispatch(setSubscribed(subscribed)), setData: (data: Data) => dispatch(setData(data)), }); @@ -239,11 +286,10 @@ const mapDispatchToProps = (dispatch: ThunkDispatch) const mapStateToProps = (state: StateType): VCStateProps => { return { socket: state.frontend.configuration.socket, - // socketConnected: state.frontend.configuration.socketConnected, selectedRun: state.frontend.selectedRun, selectedVisualisation: state.frontend.selectedVisualisation, - // currentGeneration: state.frontend.currentGeneration, subscribed: state.frontend.configuration.subscribed, + fetchingData: state.frontend.fetchingData, }; }; diff --git a/scripts/client.py b/scripts/client.py index 0d72e2d..108ee41 100644 --- a/scripts/client.py +++ b/scripts/client.py @@ -9,7 +9,6 @@ # http://opt-vis-backend.herokuapp.com/ # http://localhost:9000 BACKEND_URL = "http://localhost:9000" -# 40185 # PORT = "33585" # WEBSOCKET_URL = BACKEND_URL + ":" + PORT API_URL = BACKEND_URL + "/api" @@ -40,7 +39,6 @@ def on_disconnect(self): def on_save(self, data): # print(data) if (data['saved']): - # print("Saved data for generation: ", data['generation']) self.sending_data = False else: print("Unable to save data: ", data['message']) @@ -60,7 +58,6 @@ def process_queue(self): data = { "runId": self.run_id, "dataId": self.data_id, - # "generation": self.current_generation, "batch": batch } self.emit("data", data) diff --git a/scripts/sample_data.py b/scripts/dtlz1.py similarity index 87% rename from scripts/sample_data.py rename to scripts/dtlz1.py index f25c6c1..88062a6 100644 --- a/scripts/sample_data.py +++ b/scripts/dtlz1.py @@ -11,11 +11,7 @@ dtlz1_data = pickle.load(dtlz1_file) # Population size is 100 -# dtlz2_file = open('data/DTLZ2DataFile.pkl', 'rb') -# dtlz2_data = pickle.load(dtlz2_file) - print("Total population size: ", len(dtlz1_data)) -# print("Total population size: ", len(dtlz2_data)) populationSize = 100 totalGenerations = 282 @@ -50,7 +46,7 @@ else: # Add the data to the client queue to send # print("Sending generation: ", generation) - optimiserClient.addBatch(data_batch) # generation + optimiserClient.addBatch(data_batch) data_batch = [] # generation += 1 diff --git a/scripts/dtlz2.py b/scripts/dtlz2.py new file mode 100644 index 0000000..7cf39aa --- /dev/null +++ b/scripts/dtlz2.py @@ -0,0 +1,51 @@ +import os +import pickle +import time + +import client + +dirname = os.path.dirname(__file__) + +# Open the optimisation data file +dtlz2_file = open(os.path.join(dirname, 'data/DTLZ2DataFile.pkl'), 'rb') +dtlz2_data = pickle.load(dtlz2_file) + +# Population size is 100 +# print("Total population size: ", len(dtlz2_data)) + +populationSize = 100 +totalGenerations = 54 + +# Create an optimiser client +optimiserClient = client.OptimiserClient(populationSize) + +# Algorithm parameters +algorithmParameters = { + "Function Evaluations": 5000, + "sbxProb": 0.8, + "pmProb": 0.1 +} + +# Create the optimisation run +optimiserClient.createRun("Pareto front estimation of DTLZ2", "DTLZ2", + "NGSA-II", populationSize, totalGenerations, algorithmParameters, ["frontend-plugin"]) + +# Send generation data to the server +count = 1 +data_batch = [] +for values in dtlz2_data: + # Add the data to the batch to send + data_batch.append(values.tolist()) + + if (count < populationSize): + count += 1 + else: + # Add the data to the client queue to send + # print("Sending generation: ", generation) + optimiserClient.addBatch(data_batch) + data_batch = [] + + count = 1 + # print("Next Generation: ", generation) + +print("Completed adding items to queue, wait until queue has been processed")