package api; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.math.RoundingMode; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import java.util.DoubleSummaryStatistics; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Collectors; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.text.NumberFormatter; import algorithm.objectiveFunction.ObjectiveFunctionByCarlos; import algorithm.objectiveFunction.SwitchObjectiveFunction; import classes.AbstractCanvasObject; import classes.GroupNode; import classes.Flexibility; import classes.HolonElement; import classes.HolonObject; import classes.HolonSwitch; import classes.HolonElement.Priority; import ui.controller.Control; import ui.controller.FlexManager.FlexState; import ui.controller.FlexManager.FlexWrapper; import ui.model.DecoratedGroupNode; import ui.model.DecoratedState; import ui.model.Model; import ui.model.DecoratedHolonObject.HolonObjectState; import ui.model.DecoratedSwitch.SwitchState; import ui.model.DecoratedNetwork; import ui.view.Console; import utility.ImageImport; public abstract class AlgorithmFrameworkFlex implements AddOn{ //Algo protected int rounds = 1; //Panel private JPanel content = new JPanel(); protected Console console = new Console(); private JPanel borderPanel = new JPanel(); //Settings groupNode private DecoratedGroupNode dGroupNode = null; //access private ArrayList access; private HashMap accessKillSwitch = new HashMap(); LinkedList> resetChain = new LinkedList>(); boolean algoUseElements = false, algoUseSwitches = true, algoUseFlexes = true, algoUseKillSwitch = true; //time private long startTime; private RunProgressBar runProgressbar = new RunProgressBar(); //concurrency private Thread runThread = new Thread(); protected boolean cancel = false; //holeg interaction protected Control control; //printing private Printer runPrinter = new Printer(plottFileName()); protected List runList = new LinkedList(); //Parameter @SuppressWarnings("rawtypes") LinkedList parameterSteppingList= new LinkedList(); protected boolean useStepping = false; //Email private boolean useEmailNotification = false; //ObjectiveFunction enum ObjectiveFunction {Normal, Switch}; ObjectiveFunction evaluationFunction = ObjectiveFunction.Normal; public AlgorithmFrameworkFlex(){ content.setLayout(new BorderLayout()); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createOptionPanel() , console); splitPane.setResizeWeight(0.0); content.add(splitPane, BorderLayout.CENTER); content.setPreferredSize(new Dimension(1200,800)); } private JPanel createOptionPanel() { JPanel optionPanel = new JPanel(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(createParameterPanel()); scrollPane.setBorder(BorderFactory.createTitledBorder("Parameter")); optionPanel.add(scrollPane, BorderLayout.CENTER); optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END); return optionPanel; } private Component createParameterPanel() { JPanel parameterPanel = new JPanel(null); parameterPanel.setPreferredSize(new Dimension(510,300)); borderPanel.setLayout(new BoxLayout(borderPanel, BoxLayout.PAGE_AXIS)); addIntParameter("Rounds", rounds, intInput -> rounds = intInput, () -> rounds, 1); JScrollPane scrollPane = new JScrollPane(borderPanel); scrollPane.setBounds(10, 0, 850, 292); scrollPane.setBorder(BorderFactory.createEmptyBorder()); parameterPanel.add(scrollPane); JButton selectGroupNodeButton = new JButton("Select GroupNode"); selectGroupNodeButton.setBounds(900, 0, 185, 30); selectGroupNodeButton.addActionListener(actionEvent -> selectGroupNode()); parameterPanel.add(selectGroupNodeButton); JProgressBar progressBar = runProgressbar.getJProgressBar(); progressBar.setBounds(900, 35, 185, 20); progressBar.setStringPainted(true); parameterPanel.add(progressBar); JCheckBox useElements = new JCheckBox("Elements"); useElements.setSelected(algoUseElements); useElements.setBounds(900, 70, 185, 20); useElements.addActionListener(actionEvent -> algoUseElements = useElements.isSelected()); parameterPanel.add(useElements); JCheckBox useSwitches = new JCheckBox("Switches"); useSwitches.setSelected(algoUseSwitches); useSwitches.setBounds(900, 90, 185, 20); useSwitches.addActionListener(actionEvent -> algoUseSwitches = useSwitches.isSelected()); parameterPanel.add(useSwitches); JCheckBox useFlexes = new JCheckBox("Flexibilities"); useFlexes.setSelected(algoUseFlexes); useFlexes.setBounds(900, 110, 185, 20); useFlexes.addActionListener(actionEvent -> algoUseFlexes = useFlexes.isSelected()); parameterPanel.add(useFlexes); JCheckBox useKillSwitches = new JCheckBox("KillSwitch"); useKillSwitches.setSelected(algoUseFlexes); useKillSwitches.setBounds(900, 130, 185, 20); useKillSwitches.addActionListener(actionEvent -> { cancel(); reset(); algoUseKillSwitch = useKillSwitches.isSelected(); }); parameterPanel.add(useKillSwitches); String[] objectiveFunctionStrings = { "Normal", "Switch"}; JLabel fitnessLabel = new JLabel("FitnessFunction:"); fitnessLabel.setBounds(910, 160, 90, 20); parameterPanel.add(fitnessLabel); JComboBox ofBox = new JComboBox(objectiveFunctionStrings); ofBox.addActionListener(actionEvent -> { boolean pickNormal = ((String)ofBox.getSelectedItem()).equals("Normal"); evaluationFunction = pickNormal?ObjectiveFunction.Normal:ObjectiveFunction.Switch; }); ofBox.setBounds(1000, 160, 70, 20); parameterPanel.add(ofBox); JCheckBox emailNotificationCheckbox = new JCheckBox("EmailNotification"); emailNotificationCheckbox.setSelected(this.useEmailNotification); emailNotificationCheckbox.setBounds(900, 200, 130, 20); emailNotificationCheckbox.addActionListener(actionEvent -> useEmailNotification = emailNotificationCheckbox.isSelected()); parameterPanel.add(emailNotificationCheckbox); JButton emailSettingsButton = new JButton("", new ImageIcon(ImageImport.loadImage("/Images/settingsIcon.png", 16,16))); emailSettingsButton.setBounds(1030, 200, 20, 20); emailSettingsButton.addActionListener(event -> { EmailNotification.OpenEmailSettings(content); }); parameterPanel.add(emailSettingsButton); return parameterPanel; } private JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JButton resetButton = new JButton("Reset"); resetButton.setToolTipText("Resets the State to before the Algorithm has runed."); resetButton.addActionListener(actionEvent -> reset()); buttonPanel.add(resetButton); JButton cancelButton = new JButton("Cancel Run"); cancelButton.addActionListener(actionEvent -> cancel()); buttonPanel.add(cancelButton); JButton fitnessButton = new JButton("Fitness"); fitnessButton.setToolTipText("Fitness for the current state."); fitnessButton.addActionListener(actionEvent -> fitness()); buttonPanel.add(fitnessButton); JButton runButton = new JButton("Run"); runButton.addActionListener(actionEvent -> { Runnable task = () -> run(); runThread = new Thread(task); runThread.start(); }); buttonPanel.add(runButton); return buttonPanel; } //ParameterImports //int protected void addIntParameter(String parameterName, int parameterValue, Consumer setter, Supplier getter) { this.addIntParameter(parameterName, parameterValue, setter, getter, Integer.MIN_VALUE, Integer.MAX_VALUE); } protected void addIntParameter(String parameterName, int parameterValue, Consumer setter, Supplier getter, int parameterMinValue) { this.addIntParameter(parameterName, parameterValue, setter, getter, parameterMinValue, Integer.MAX_VALUE); } protected void addIntParameter(String parameterName, int parameterValue, Consumer setter, Supplier getter, int parameterMinValue, int parameterMaxValue) { JPanel singleParameterPanel = new JPanel(); singleParameterPanel.setLayout(new BoxLayout(singleParameterPanel, BoxLayout.LINE_AXIS)); singleParameterPanel.setAlignmentX(0.0f); singleParameterPanel.add(new JLabel(parameterName + ": ")); singleParameterPanel.add(Box.createHorizontalGlue()); NumberFormat format = NumberFormat.getIntegerInstance(); format.setGroupingUsed(false); format.setParseIntegerOnly(true); NumberFormatter integerFormatter = new NumberFormatter(format); integerFormatter.setMinimum(parameterMinValue); integerFormatter.setMaximum(parameterMaxValue); integerFormatter.setCommitsOnValidEdit(true); JFormattedTextField singleParameterTextField = new JFormattedTextField(integerFormatter); singleParameterTextField.setValue(parameterValue); String minValue = (parameterMinValue == Integer.MIN_VALUE)?"Integer.MIN_VALUE":String.valueOf(parameterMinValue); String maxValue = (parameterMaxValue == Integer.MAX_VALUE)?"Integer.MAX_VALUE":String.valueOf(parameterMaxValue); singleParameterTextField.setToolTipText("Only integer \u2208 [" + minValue + "," + maxValue + "]"); singleParameterTextField.addPropertyChangeListener(actionEvent -> setter.accept(Integer.parseInt(singleParameterTextField.getValue().toString()))); singleParameterTextField.setMaximumSize(new Dimension(200, 30)); singleParameterTextField.setPreferredSize(new Dimension(200, 30)); singleParameterPanel.add(singleParameterTextField); ParameterStepping intParameterStepping = new ParameterStepping(setter, getter, Integer::sum , (a,b) -> a * b, 1, 1); intParameterStepping.useThisParameter = false; parameterSteppingList.add(intParameterStepping); JCheckBox useSteppingCheckBox = new JCheckBox(); useSteppingCheckBox.setSelected(false); singleParameterPanel.add(useSteppingCheckBox); JLabel stepsLabel = new JLabel("Steps: "); stepsLabel.setEnabled(false); singleParameterPanel.add(stepsLabel); NumberFormatter stepFormatter = new NumberFormatter(format); stepFormatter.setMinimum(1); stepFormatter.setMaximum(Integer.MAX_VALUE); stepFormatter.setCommitsOnValidEdit(true); JFormattedTextField stepsTextField = new JFormattedTextField(stepFormatter); stepsTextField.setEnabled(false); stepsTextField.setValue(1); stepsTextField.setToolTipText("Only integer \u2208 [" + 1 + "," + Integer.MAX_VALUE + "]"); stepsTextField.addPropertyChangeListener(actionEvent -> intParameterStepping.stepps = Integer.parseInt(stepsTextField.getValue().toString())); stepsTextField.setMaximumSize(new Dimension(40, 30)); stepsTextField.setPreferredSize(new Dimension(40, 30)); singleParameterPanel.add(stepsTextField); JLabel stepsSizeLabel = new JLabel("StepsSize: "); stepsSizeLabel.setEnabled(false); singleParameterPanel.add(stepsSizeLabel); JFormattedTextField stepsSizeTextField = new JFormattedTextField(stepFormatter); stepsSizeTextField.setEnabled(false); stepsSizeTextField.setValue(1); stepsSizeTextField.setToolTipText("Only integer \u2208 [" + 1 + "," + Integer.MAX_VALUE + "]"); stepsSizeTextField.addPropertyChangeListener(actionEvent -> intParameterStepping.stepSize = Integer.parseInt(stepsSizeTextField.getValue().toString())); stepsSizeTextField.setMaximumSize(new Dimension(40, 30)); stepsSizeTextField.setPreferredSize(new Dimension(40, 30)); singleParameterPanel.add(stepsSizeTextField); useSteppingCheckBox.addActionListener(actionEvent -> { boolean enabled = useSteppingCheckBox.isSelected(); intParameterStepping.useThisParameter = enabled; this.useStepping = this.parameterSteppingList.stream().anyMatch(parameter -> parameter.useThisParameter); stepsLabel.setEnabled(enabled); stepsTextField.setEnabled(enabled); stepsSizeLabel.setEnabled(enabled); stepsSizeTextField.setEnabled(enabled); }); borderPanel.add(singleParameterPanel); } //double protected void addDoubleParameter(String parameterName, double parameterValue, Consumer setter, Supplier getter) { this.addDoubleParameter(parameterName, parameterValue, setter, getter, Double.MIN_VALUE, Double.MAX_VALUE); } protected void addDoubleParameter(String parameterName, double parameterValue, Consumer setter, Supplier getter, double parameterMinValue) { this.addDoubleParameter(parameterName, parameterValue, setter, getter, parameterMinValue, Double.MAX_VALUE); } protected void addDoubleParameter(String parameterName, double parameterValue, Consumer setter, Supplier getter, double parameterMinValue, double parameterMaxValue) { JPanel singleParameterPanel = new JPanel(); singleParameterPanel.setLayout(new BoxLayout(singleParameterPanel, BoxLayout.LINE_AXIS)); singleParameterPanel.setAlignmentX(0.0f); singleParameterPanel.add(new JLabel(parameterName + ": ")); singleParameterPanel.add(Box.createHorizontalGlue()); NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US); doubleFormat.setMinimumFractionDigits(1); doubleFormat.setMaximumFractionDigits(10); doubleFormat.setRoundingMode(RoundingMode.HALF_UP); NumberFormatter doubleFormatter = new NumberFormatter(doubleFormat); doubleFormatter.setMinimum(parameterMinValue); doubleFormatter.setMaximum(parameterMaxValue); doubleFormatter.setCommitsOnValidEdit(true); JFormattedTextField singleParameterTextField = new JFormattedTextField(doubleFormatter); singleParameterTextField.setValue(parameterValue); String minValue = (parameterMinValue == Double.MIN_VALUE)?"Double.MIN_VALUE":String.valueOf(parameterMinValue); String maxValue = (parameterMaxValue == Double.MAX_VALUE)?"Double.MAX_VALUE":String.valueOf(parameterMaxValue); singleParameterTextField.setToolTipText("Only double \u2208 [" + minValue + "," + maxValue + "]"); singleParameterTextField.addPropertyChangeListener(actionEvent -> setter.accept(Double.parseDouble(singleParameterTextField.getValue().toString()))); singleParameterTextField.setMaximumSize(new Dimension(200, 30)); singleParameterTextField.setPreferredSize(new Dimension(200, 30)); singleParameterPanel.add(singleParameterTextField); ParameterStepping doubleParameterStepping = new ParameterStepping(setter, getter, (a,b) -> a+b , (a,b) -> a * b, 1.0, 1); doubleParameterStepping.useThisParameter = false; parameterSteppingList.add(doubleParameterStepping); JCheckBox useSteppingCheckBox = new JCheckBox(); useSteppingCheckBox.setSelected(false); singleParameterPanel.add(useSteppingCheckBox); JLabel stepsLabel = new JLabel("Steps: "); stepsLabel.setEnabled(false); singleParameterPanel.add(stepsLabel); NumberFormat format = NumberFormat.getIntegerInstance(); format.setGroupingUsed(false); format.setParseIntegerOnly(true); NumberFormatter integerFormatter = new NumberFormatter(format); integerFormatter.setMinimum(1); integerFormatter.setMaximum(Integer.MAX_VALUE); integerFormatter.setCommitsOnValidEdit(true); JFormattedTextField stepsTextField = new JFormattedTextField(integerFormatter); stepsTextField.setEnabled(false); stepsTextField.setValue(1); stepsTextField.setToolTipText("Only integer \u2208 [" + 1 + "," + Integer.MAX_VALUE + "]"); stepsTextField.addPropertyChangeListener(actionEvent -> doubleParameterStepping.stepps = Integer.parseInt(stepsTextField.getValue().toString())); stepsTextField.setMaximumSize(new Dimension(40, 30)); stepsTextField.setPreferredSize(new Dimension(40, 30)); singleParameterPanel.add(stepsTextField); JLabel stepsSizeLabel = new JLabel("StepsSize: "); stepsSizeLabel.setEnabled(false); singleParameterPanel.add(stepsSizeLabel); NumberFormatter doubleFormatterForStepping = new NumberFormatter(doubleFormat); doubleFormatterForStepping.setCommitsOnValidEdit(true); JFormattedTextField stepsSizeTextField = new JFormattedTextField(doubleFormatterForStepping); stepsSizeTextField.setEnabled(false); stepsSizeTextField.setValue(1.0); stepsSizeTextField.setToolTipText("Only double"); stepsSizeTextField.addPropertyChangeListener(actionEvent -> doubleParameterStepping.stepSize = Double.parseDouble(stepsSizeTextField.getValue().toString())); stepsSizeTextField.setMaximumSize(new Dimension(40, 30)); stepsSizeTextField.setPreferredSize(new Dimension(40, 30)); singleParameterPanel.add(stepsSizeTextField); useSteppingCheckBox.addActionListener(actionEvent -> { boolean enabled = useSteppingCheckBox.isSelected(); doubleParameterStepping.useThisParameter = enabled; this.useStepping = this.parameterSteppingList.stream().anyMatch(parameter -> parameter.useThisParameter); stepsLabel.setEnabled(enabled); stepsTextField.setEnabled(enabled); stepsSizeLabel.setEnabled(enabled); stepsSizeTextField.setEnabled(enabled); }); borderPanel.add(singleParameterPanel); } //boolean protected void addBooleanParameter(String parameterName, boolean parameterValue, Consumer setter){ JPanel singleParameterPanel = new JPanel(); singleParameterPanel.setLayout(new BoxLayout(singleParameterPanel, BoxLayout.LINE_AXIS)); singleParameterPanel.setAlignmentX(0.0f); singleParameterPanel.add(new JLabel(parameterName + ": ")); singleParameterPanel.add(Box.createHorizontalGlue()); JCheckBox useGroupNodeCheckBox = new JCheckBox(); useGroupNodeCheckBox.setSelected(parameterValue); useGroupNodeCheckBox.addActionListener(actionEvent -> setter.accept(useGroupNodeCheckBox.isSelected())); singleParameterPanel.add(useGroupNodeCheckBox); borderPanel.add(singleParameterPanel); } private void startTimer(){ startTime = System.currentTimeMillis(); } private long printElapsedTime(){ long elapsedMilliSeconds = System.currentTimeMillis() - startTime; console.println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds); return elapsedMilliSeconds; } private void cancel() { if(runThread.isAlive()) { console.println("Cancel run."); cancel = true; runProgressbar.cancel(); } else { console.println("Nothing to cancel."); } } private void fitness() { if(runThread.isAlive()) { console.println("Run have to be cancelled First."); return; } double currentFitness = evaluatePosition(extractPositionAndAccess()); resetChain.removeLast(); console.println("Actual Fitnessvalue: " + currentFitness); } private void selectGroupNode() { Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle(aCps)).toArray(); @SuppressWarnings("unchecked") Handle selected = (Handle) JOptionPane.showInputDialog(content, "Select GroupNode:", "GroupNode?", JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, ""); if(selected != null) { console.println("Selected: " + selected); dGroupNode = selected.object; } } protected double evaluatePosition(List positionToEvaluate) { runProgressbar.step(); setState(positionToEvaluate); // execution time critical DecoratedState actualstate = control.getSimManager().getActualDecorState(); double result = evaluateState(actualstate); return result; } private double evaluateState(DecoratedState actualstate) { switch(this.evaluationFunction) { case Switch: return SwitchObjectiveFunction.getFitnessValueForState(actualstate); case Normal: default: return ObjectiveFunctionByCarlos.getFitnessValueForState(actualstate); } } private void run() { cancel = false; control.guiDisable(true); runPrinter.openStream(); runPrinter.println(""); runPrinter.println("Start:" + stringStatFromActualState()); runPrinter.closeStream(); if(this.useStepping) { initParameterStepping(); do { executeAlgoWithParameter(); if(cancel) break; resetState(); }while(updateOneParameter()); resetParameterStepping(); }else { executeAlgoWithParameter(); } updateVisual(); runProgressbar.finishedCancel(); control.guiDisable(false); if(this.useEmailNotification && !cancel) { EmailNotification.sendEmail(this.getClass().getName() + " finished", "Execution done."); } } @SuppressWarnings("rawtypes") private void initParameterStepping() { for(ParameterStepping param :this.parameterSteppingList) { param.init(); } } @SuppressWarnings("rawtypes") private void resetParameterStepping() { for(ParameterStepping param :this.parameterSteppingList) { param.reset(); } } @SuppressWarnings("rawtypes") private boolean updateOneParameter() { List parameterInUseList = this.parameterSteppingList.stream().filter(param -> param.useThisParameter).collect(Collectors.toList()); Collections.reverse(parameterInUseList); int lastParameter = parameterInUseList.size() - 1 ; int actualParameter = 0; for(ParameterStepping param : parameterInUseList) { if(param.canUpdate()) { param.update(); return true; }else { if(actualParameter == lastParameter) break; param.reset(); } actualParameter++; } //No Param can be updated return false; } private void executeAlgoWithParameter(){ double startFitness = evaluatePosition(extractPositionAndAccess()); console.println("BitLength: " + access.size()); resetChain.removeLast(); runPrinter.openStream(); runPrinter.println(""); runPrinter.println(algoInformationToPrint()); console.println(algoInformationToPrint()); runPrinter.closeStream(); runProgressbar.start(); Individual runBest = new Individual(); runBest.fitness = Double.MAX_VALUE; for(int r = 0; r < rounds; r++) { startTimer(); Individual roundBest = executeAlgo(); if(cancel)return; long executionTime = printElapsedTime(); setState(roundBest.position); runPrinter.openStream(); runPrinter.println(runList.stream().map(Object::toString).collect(Collectors.joining(", "))); runPrinter.println(stringStatFromActualState()); runPrinter.println("Result: " + roundBest.fitness + " ExecutionTime:" + executionTime); runPrinter.closeStream(); resetState(); if(roundBest.fitness < runBest.fitness) runBest = roundBest; } control.getSimManager().resetFlexManagerForTimeStep(control.getModel().getCurIteration()); this.extractPositionAndAccess(); setState(runBest.position); updateVisual(); console.println("Start: " + startFitness); console.println("AlgoResult: " + runBest.fitness); if(this.algoUseFlexes)calculateAndPrintFlexInfos(control.getSimManager().getActualDecorState()); } private void calculateAndPrintFlexInfos(DecoratedState state) { int amountOfUsedFlex = 0; int amountOfFlex = state.getFlexManager().getAllFlexWrapper().size(); float cost = 0; int consumingFlex = 0; float consumingFlexEnergy = 0.0f; int producingFlex = 0; float producingFlexEnergy = 0.0f; int maxCooldown = 0; int amountEssential = 0; int amountHigh = 0; int amountMedium = 0; int amountLow = 0; for(FlexWrapper flexWrapper :state.getFlexManager().getAllFlexWrapperWithState(FlexState.IN_USE)) { amountOfUsedFlex++; cost += flexWrapper.getFlex().cost; float energy = flexWrapper.getFlex().bringtmir(); if(energy < 0) { consumingFlex++; consumingFlexEnergy += -energy; }else { producingFlex++; producingFlexEnergy += energy; } if(flexWrapper.getFlex().getCooldown() > maxCooldown) maxCooldown = flexWrapper.getFlex().getCooldown(); switch(flexWrapper.getFlex().getElement().getPriority()) { case Essential: amountEssential++; break; case High: amountHigh++; break; case Low: amountLow++; break; case Medium: amountMedium++; break; default: break; } } //Total Flexibilities: //Used Flexibilities: console.println("Used Flex [" + amountOfUsedFlex + "/" + amountOfFlex + "]"); //Consuming Flexibilities: console.println(consumingFlex + " consuimg flexibilities that consumed " + consumingFlexEnergy + "Energy."); //Producing Flexibilities console.println(producingFlex + " producing flexibilities that produce " + producingFlexEnergy + "Energy."); console.println("Flex in use:\t" + "Low= " + amountLow + "\tMedium= " + amountMedium + "\tHigh= " + amountHigh + "\tEssential= " + amountEssential); //Total cost: console.println("Total Cost: "+ cost); //Longest Cooldown console.println("Max Cooldown: "+ maxCooldown); // } protected abstract Individual executeAlgo(); private void reset() { if(runThread.isAlive()) { console.println("Run have to be cancelled First."); return; } if(!resetChain.isEmpty()) { console.println("Resetting.."); setState(resetChain.getFirst()); resetChain.clear(); control.resetSimulation(); control.setCurIteration(0); updateVisual(); }else { console.println("No run inistialized."); } } /** * To let the User See the current state without touching the Canvas. */ private void updateVisual() { control.calculateStateAndVisualForCurrentTimeStep(); } /** * Sets the Model back to its original State before the LAST run. */ private void resetState() { setState(resetChain.getLast()); } /** * Sets the State out of the given position for calculation or to show the user. * @param position */ private void setState(List position) { control.getSimManager().resetFlexManagerForTimeStep(control.getModel().getCurIteration()); int i = 0; for(Boolean bool: position) { access.get(i++).setState(bool); } control.calculateStateOnlyForCurrentTimeStep(); } /** * Method to get the current Position alias a ListOf Booleans for aktive settings on the Objects on the Canvas. * Also initialize the Access Hashmap to swap faster positions. * @param model * @return */ protected List extractPositionAndAccess() { Model model = control.getModel(); this.accessKillSwitch = new HashMap(); access= new ArrayList(); List initialState = new ArrayList(); rollOutNodes((dGroupNode != null)? dGroupNode.getModel().getNodes() :model.getObjectsOnCanvas(), initialState, model.getCurIteration()); resetChain.add(initialState); if(algoUseFlexes) { for(FlexWrapper flex :control.getSimManager().getActualFlexManager().getAllFlexWrapperWithState(FlexState.OFFERED)){ //flex.getFlex().getElement().parentObject; AccessWrapper killSwitchAccess = this.algoUseKillSwitch ? this.accessKillSwitch.get(flex.getFlex().getElement().parentObject): null;; access.add(new AccessWrapper(flex.getFlex(), killSwitchAccess)); initialState.add(false); } for(FlexWrapper flex :control.getSimManager().getActualFlexManager().getAllFlexWrapperWithState(FlexState.IN_USE)){ AccessWrapper killSwitchAccess = this.algoUseKillSwitch ? this.accessKillSwitch.get(flex.getFlex().getElement().parentObject): null; access.add(new AccessWrapper(flex.getFlex(), killSwitchAccess)); initialState.add(true); } } //console.println(access.stream().map(Object::toString).collect(Collectors.joining(", "))); return initialState; } /** * Method to extract the Informations recursively out of the Model. * @param nodes * @param positionToInit * @param timeStep */ private void rollOutNodes(List nodes, List positionToInit, int timeStep) { for(AbstractCanvasObject aCps : nodes) { if (aCps instanceof HolonObject) { HolonObject hObject = (HolonObject) aCps; AccessWrapper killSwitchAccess = new AccessWrapper(hObject); if(this.algoUseKillSwitch) { positionToInit.add(false); access.add(killSwitchAccess); accessKillSwitch.put(hObject, killSwitchAccess); } if(this.algoUseElements) { for (HolonElement hE : hObject.getElements()) { positionToInit.add(hE.isActive()); access.add(new AccessWrapper(hE, killSwitchAccess)); } } } else if (aCps instanceof HolonSwitch&& algoUseSwitches) { HolonSwitch sw = (HolonSwitch) aCps; positionToInit.add(sw.getState(timeStep)); access.add(new AccessWrapper(sw)); } else if(aCps instanceof GroupNode) { rollOutNodes(((GroupNode)aCps).getNodes(), positionToInit ,timeStep ); } } } private String stringStatFromActualState() { if(dGroupNode != null) { //GetActualDecoratedGroupNode dGroupNode = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().get(dGroupNode.getModel()); int amountOfSupplier = dGroupNode.getAmountOfSupplier(); int amountOfConsumer = dGroupNode.getAmountOfConsumer(); int amountOfPassiv = dGroupNode.getAmountOfPassiv(); int amountOfObjects = amountOfSupplier + amountOfConsumer + amountOfPassiv; int unSuppliedConsumer = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED); int partiallySuppliedConsumer = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED); int suppliedConsumer = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED); int overSuppliedConsumer = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED); int activeElements = dGroupNode.getAmountOfAktiveElemntsFromHolonObjects(); int elements = dGroupNode.getAmountOfElemntsFromHolonObjects(); return "HolonObjects[" + " Producer: " + amountOfSupplier + "/" + amountOfObjects + "("+ (float)amountOfSupplier/(float)amountOfObjects * 100 + "%)" + " Unsupplied: " + unSuppliedConsumer + "/" + amountOfObjects + "("+ (float)unSuppliedConsumer/(float)amountOfObjects * 100 + "%)" + " PartiallySupplied: " + partiallySuppliedConsumer + "/" + amountOfObjects + "("+ (float)partiallySuppliedConsumer/(float)amountOfObjects * 100 + "%)" + " Supplied: " + suppliedConsumer + "/" + amountOfObjects + "("+ (float)suppliedConsumer/(float)amountOfObjects * 100 + "%)" + " Passiv: " + overSuppliedConsumer + "/" + amountOfObjects + "("+ (float)overSuppliedConsumer/(float)amountOfObjects * 100 + "%)" + "]" + " HolonElemnts[" + " Active: " + activeElements + "/" + elements + "("+ (float)activeElements/(float)elements * 100 + "%)" + "]"; } DecoratedState state = control.getSimManager().getActualDecorState(); int amountOfSupplier = 0, amountOfConsumer = 0, amountOfPassiv = 0, unSuppliedConsumer = 0, partiallySuppliedConsumer = 0, suppliedConsumer = 0, overSuppliedConsumer = 0; int activeElements = 0, amountOfelements = 0; int totalConsumption = 0, totalProduction = 0; for(DecoratedNetwork net : state.getNetworkList()) { amountOfConsumer += net.getAmountOfConsumer(); amountOfSupplier += net.getAmountOfSupplier(); amountOfPassiv += net.getAmountOfPassiv(); unSuppliedConsumer += net.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED); partiallySuppliedConsumer += net.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED); suppliedConsumer += net.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED); overSuppliedConsumer += net.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED); amountOfelements += net.getAmountOfElements(); activeElements += net.getAmountOfActiveElements(); totalConsumption += net.getTotalConsumption(); totalProduction += net.getTotalProduction(); } int amountOfObjects = amountOfSupplier + amountOfConsumer + amountOfPassiv; int difference = Math.abs(totalProduction - totalConsumption); List flexActiveList = control.getSimManager().getActualFlexManager().getAllFlexWrapperWithState(FlexState.IN_USE).stream().map(flex -> flex.getFlex()).collect(Collectors.toList()); int amountActiveEssential = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Essential).count(); int amountActiveHigh = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.High).count(); int amountActiveMedium = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Medium).count(); int amountActiveLow = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Low).count(); int amountActiveFlexibilities = amountActiveEssential + amountActiveHigh + amountActiveMedium + amountActiveLow; int amountHolons = state.getNetworkList().size(); int amountSwitch = state.getDecoratedSwitches().size(); int amountActiveSwitch = (int)state.getDecoratedSwitches().stream().filter(dswitch -> (dswitch.getState() == SwitchState.Closed)).count(); DoubleSummaryStatistics overStat = state.getNetworkList().stream().flatMap(net -> { return net.getConsumerList().stream().filter(con -> con.getState() == HolonObjectState.OVER_SUPPLIED); }).mapToDouble(con -> con.getSupplyBarPercentage()).summaryStatistics(); DoubleSummaryStatistics partiallyStat = state.getNetworkList().stream().flatMap(net -> { return net.getConsumerList().stream().filter(con -> con.getState() == HolonObjectState.PARTIALLY_SUPPLIED); }).mapToDouble(con -> con.getSupplyBarPercentage()).summaryStatistics(); return "HolonObjects[" + " Passiv: " + percentage(amountOfPassiv, amountOfObjects) + " Producer: " + percentage(amountOfSupplier, amountOfObjects) + " Consumer: " + percentage(amountOfConsumer, amountOfObjects) + " Unsupplied: " + percentage(unSuppliedConsumer, amountOfConsumer) + " PartiallySupplied: " + percentage(partiallySuppliedConsumer, amountOfConsumer) + " with SupplyPercentage(Min: " + partiallyStat.getMin() + " Max: "+ partiallyStat.getMax() + " Average: " +partiallyStat.getAverage() + ")" + " Supplied: " + percentage(suppliedConsumer, amountOfConsumer) + " Over: " + percentage(overSuppliedConsumer, amountOfConsumer) + " with SupplyPercentage(Min: " + overStat.getMin() + " Max: "+ overStat.getMax() + " Average: " + overStat.getAverage() + ")" + "]" + " HolonElemnts[" + " Active: " + percentage(activeElements, amountOfelements) + "]" + "Flexibilities_active[" + " Essential: " + percentage(amountActiveEssential, amountActiveFlexibilities) + " High: " + percentage(amountActiveHigh, amountActiveFlexibilities) + " Medium: " + percentage(amountActiveMedium, amountActiveFlexibilities) + " Low: " + percentage(amountActiveLow, amountActiveFlexibilities) + "]" + " activeSwitches:" + percentage(amountActiveSwitch,amountSwitch) + " Holons: " + amountHolons + " totalConsumption: " + totalConsumption + " totalProduction: " + totalProduction + " difference: " + difference; } private String percentage(int actual, int max) { return actual + "/" + max + "("+ (float)actual/(float)max * 100 + "%)"; } @Override public JPanel getPanel() { return content; } @Override public void setController(Control control) { this.control = control; } private class RunProgressBar{ //progressbar private JProgressBar progressBar = new JProgressBar(); private int count = 0; private boolean isActive = false; public void step() { if(isActive) progressBar.setValue(count++); } public void start() { progressBar.setIndeterminate(false); count = 0; isActive = true; progressBar.setValue(0); progressBar.setMaximum(getProgressBarMaxCount()); } public void cancel() { isActive = false; progressBar.setIndeterminate(true); } public void finishedCancel() { progressBar.setIndeterminate(false); progressBar.setValue(0); } public JProgressBar getJProgressBar(){ return progressBar; } } protected abstract int getProgressBarMaxCount(); protected abstract String algoInformationToPrint(); protected abstract String plottFileName(); public class Printer{ private JFileChooser fileChooser = new JFileChooser(); private BufferedWriter out; public Printer(String filename){ fileChooser.setCurrentDirectory(new File(System.getProperty("user.dir"))); fileChooser.setSelectedFile(new File(filename)); } public void openStream() { File file = fileChooser.getSelectedFile(); try { file.createNewFile(); out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file, true), "UTF-8")); } catch (IOException e) { System.out.println(e.getMessage()); } } public void println(String stringToPrint) { try { out.write(stringToPrint); out.newLine(); } catch (IOException e) { System.out.println(e.getMessage()); } } public void closeStream() { try { out.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } private enum AccessType {None, HolonElement, Switch, Flexibility, KillSwitch}; /** * A Wrapper Class for Access HolonElement and HolonSwitch in one Element and not have to split the List. */ private class AccessWrapper { private AccessType type; private List intialStatesOfElementForKilllSwitch; private HolonObject hObject; private HolonSwitch hSwitch; private HolonElement hElement; private Flexibility flex; private AccessWrapper correspondingKillSwitch; private boolean lastState; public AccessWrapper(HolonObject hObject){ type = AccessType.KillSwitch; this.hObject = hObject; intialStatesOfElementForKilllSwitch = new ArrayList(); for(HolonElement hE: hObject.getElements()) { intialStatesOfElementForKilllSwitch.add(hE.isActive()); } } public AccessWrapper(HolonSwitch hSwitch){ type = AccessType.Switch; this.hSwitch = hSwitch; } public AccessWrapper(HolonElement hElement, AccessWrapper correspondingKillSwitch){ type = AccessType.HolonElement; this.hElement = hElement; this.correspondingKillSwitch = correspondingKillSwitch; } public AccessWrapper(Flexibility flex, AccessWrapper correspondingKillSwitch){ type = AccessType.Flexibility; this.flex = flex; this.correspondingKillSwitch = correspondingKillSwitch; } public void setState(boolean state) { lastState = state; switch(type) { case HolonElement: if(!algoUseKillSwitch || (algoUseKillSwitch && !correspondingKillSwitch.getLastState())) { hElement.setActive(state); } break; case Switch: hSwitch.setManualMode(true); hSwitch.setManualState(state); break; case Flexibility: if(state && (!algoUseKillSwitch || (algoUseKillSwitch && !correspondingKillSwitch.getLastState()))) { control.getSimManager().getActualFlexManager().orderFlex(flex); } break; case KillSwitch: if(state) { for (HolonElement hE : hObject.getElements()) { hE.setActive(false); } }else { for(int i = 0; i < hObject.getElements().size(); i++) { hObject.getElements().get(i).setActive(intialStatesOfElementForKilllSwitch.get(i)); } } break; default: break; } } public boolean getLastState() { return lastState; } public String typeString() { switch(type) { case HolonElement: return "HolonElement"; case Switch: return "Switch"; case Flexibility: return "Flexibility"; case KillSwitch: return "KillSwitch"; default: return "unknown"; } } public String toString() { return "[" + typeString() + "]"; } } /** * To create Random and maybe switch the random generation in the future. */ protected static class Random{ private static java.util.Random random = new java.util.Random(); /** * True or false * @return the random boolean. */ public static boolean nextBoolean(){ return random.nextBoolean(); } /** * Between 0.0(inclusive) and 1.0 (exclusive) * @return the random double. */ public static double nextDouble() { return random.nextDouble(); } /** * Random Int in Range [min;max[ with UniformDistirbution * @param min * @param max * @return */ public static int nextIntegerInRange(int min, int max) { int result = min; try { result = min + random.nextInt(max - min); }catch(java.lang.IllegalArgumentException e){ System.err.println("min : " + min + " max : " + max); System.err.println("max should be more then min"); } return result; } } private class Handle{ public T object; Handle(T object){ this.object = object; } public String toString() { return object.toString(); } } public class Individual { public double fitness; public List position; public Individual(){}; /** * Copy Constructor */ public Individual(Individual c){ position = c.position.stream().collect(Collectors.toList()); fitness = c.fitness; } String positionToString() { return position.stream().map(bool -> (bool?"1":"0")).collect(Collectors.joining()); } } protected class ParameterStepping{ boolean useThisParameter = false; String paramaterName; private int count = 0; int stepps; T stepSize; T startValue; Consumer setter; Supplier getter; BiFunction multyply; BiFunction add; ParameterStepping(Consumer setter, Supplier getter, BiFunction add, BiFunction multyply, T stepSize, int stepps){ this.setter = setter; this.getter = getter; this.multyply = multyply; this.add = add; this.stepSize = stepSize; this.stepps = stepps; } void init() { startValue = getter.get(); } boolean canUpdate() { return count < stepps; } void update(){ if(canUpdate()) { setter.accept(add.apply(startValue, multyply.apply(count + 1, stepSize))); count ++; } } void reset() { setter.accept(startValue); count = 0; } } }