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 addOns.Utility.EmailNotification; 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; import utility.StringFormat; 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(); private RunAverage avg = new RunAverage(); //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:" + stringStatFromRunValues(getRunValuesFromActualState())); 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(algoInformationToPrint()); console.println(algoInformationToPrint()); runPrinter.closeStream(); runProgressbar.start(); Individual runBest = new Individual(); runBest.fitness = Double.MAX_VALUE; this.avg = new RunAverage(); 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(value -> StringFormat.doubleFixedPlaces(2,value)).collect(Collectors.joining(", "))); RunValues val = getRunValuesFromActualState(); val.result = roundBest.fitness; val.executionTime = executionTime; avg.addRun(val); runPrinter.println("Result: " + StringFormat.doubleFixedPlaces(2,roundBest.fitness) + " ExecutionTime:" + executionTime + " " + stringStatFromRunValues(val)); 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: " + StringFormat.doubleFixedPlaces(2,startFitness)); console.println("AlgoResult: " + StringFormat.doubleFixedPlaces(2,runBest.fitness)); if(this.algoUseFlexes)calculateAndPrintFlexInfos(control.getSimManager().getActualDecorState()); runPrinter.openStream(); if(rounds > 1) { RunValues avgRun = avg.getAverage(); runPrinter.println("Average.Result: " + StringFormat.doubleFixedPlaces(2, avgRun.result) + " Average.ExecutionTime:" + avgRun.executionTime + " " + this.stringStatFromRunValues(avg.getAverage(), "Average.")); } runPrinter.println(""); runPrinter.closeStream(); } 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 RunValues getRunValuesFromActualState() { RunValues val = new RunValues(); if(dGroupNode != null) { //GetActualDecoratedGroupNode dGroupNode = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().get(dGroupNode.getModel()); val.producer = dGroupNode.getAmountOfSupplier(); val.consumer = dGroupNode.getAmountOfConsumer(); val.passiv = dGroupNode.getAmountOfPassiv(); val.objects = val.producer + val.consumer + val.passiv; val.unsupplied = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED); val.partiallySupplied = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED); val.supplied = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED); val.overSupplied = dGroupNode.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED); val.activeElements = dGroupNode.getAmountOfAktiveElemntsFromHolonObjects(); val.elements = dGroupNode.getAmountOfElemntsFromHolonObjects(); //TODO what should be printed happen when only groupNode are selected } DecoratedState state = control.getSimManager().getActualDecorState(); for(DecoratedNetwork net : state.getNetworkList()) { val.consumer += net.getAmountOfConsumer(); val.producer += net.getAmountOfSupplier(); val.passiv += net.getAmountOfPassiv(); val.unsupplied += net.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED); val.partiallySupplied += net.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED); val.supplied += net.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED); val.overSupplied += net.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED); val.elements += net.getAmountOfElements(); val.activeElements += net.getAmountOfActiveElements(); val.consumption += net.getTotalConsumption(); val.production += net.getTotalProduction(); } val.objects = val.consumer + val.producer + val.passiv; val.difference= Math.abs(val.production - val.consumption); List flexActiveList = control.getSimManager().getActualFlexManager().getAllFlexWrapperWithState(FlexState.IN_USE).stream().map(flex -> flex.getFlex()).collect(Collectors.toList()); val.essentialFlex = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Essential).count(); val.highFlex = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.High).count(); val.mediumFlex = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Medium).count(); val.lowFlex = (int)flexActiveList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Low).count(); val.flexebilities = val.essentialFlex + val.highFlex + val.mediumFlex + val.lowFlex; val.holon = state.getNetworkList().size(); val.switches = state.getDecoratedSwitches().size(); val.activeSwitches = (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(); val.partiallyMin = filterInf(partiallyStat.getMin()); val.partiallyMax = filterInf(partiallyStat.getMax()); val.partiallyAverage = filterInf(partiallyStat.getAverage()); val.overMin = filterInf(overStat.getMin()); val.overMax = filterInf(overStat.getMax()); val.overAverage = filterInf(overStat.getAverage()); return val; } private double filterInf(double value) { if(value == Double.NEGATIVE_INFINITY || value == Double.POSITIVE_INFINITY || value == Double.NaN) { return 0; }else { return value; } } private String stringStatFromRunValues(RunValues val){ return stringStatFromRunValues(val , ""); } private String stringStatFromRunValues(RunValues val, String prefix) { return prefix +"Passiv: " + percentage(val.passiv, val.objects) + " " + prefix +"Producer: " + percentage(val.producer, val.objects) + " " + prefix +"Consumer: " + percentage(val.consumer, val.objects) + " " + prefix +"Unsupplied: " + percentage(val.unsupplied, val.objects) + " " + prefix +"Partially: " + percentage(val.partiallySupplied, val.objects) + " " + prefix +"Over: " + percentage(val.overSupplied, val.objects) + " " + prefix +"Supplied: " + percentage(val.supplied, val.objects) + " " + prefix +"Partially.SupplyPercentage.Min: " + StringFormat.doubleFixedPlaces(2, val.partiallyMin) + " " + prefix +"Partially.SupplyPercentage.Max: "+ StringFormat.doubleFixedPlaces(2, val.partiallyMax) + " " + prefix +"Partially.SupplyPercentage.Average: " + StringFormat.doubleFixedPlaces(2, val.partiallyAverage) + " " + prefix +"Over.SupplyPercentage.Min: " + StringFormat.doubleFixedPlaces(2, val.overMin) + " " + prefix +"Over.SupplyPercentage.Max: "+ StringFormat.doubleFixedPlaces(2, val.overMax) + " " + prefix +"Over.SupplyPercentage.Average: " + StringFormat.doubleFixedPlaces(2, val.overAverage) + " " + prefix +"HolonElemnts.Active:" + percentage(val.activeElements, val.elements) + " " + prefix +"Flexibilities.Essential: " + percentage(val.essentialFlex, val.flexebilities) + " " + prefix +"Flexibilities.High: " + percentage(val.highFlex, val.flexebilities) + " " + prefix +"Flexibilities.Medium: " + percentage(val.mediumFlex, val.flexebilities) + " " + prefix +"Flexibilities.Low: " + percentage(val.lowFlex, val.flexebilities) + " " + prefix +"Switches.Active:" + percentage(val.activeSwitches,val.switches) + " " + prefix +"Holons: " + val.holon + " " + prefix +"TotalConsumption: " + val.consumption + " " + prefix +"TotalProduction: " + val.production + " " + prefix +"Difference: " + val.difference; } private String percentage(double numerator , double denominator) { if((int)denominator == 0) { return "-%"; } return StringFormat.doubleTwoPlaces(numerator) + "/" + StringFormat.doubleTwoPlaces(denominator) + " "+ StringFormat.doubleFixedPlaces(2,(float)numerator /(float)denominator * 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 class RunValues{ public double result; public double executionTime; public double objects; public double passiv; public double consumer; public double supplied; public double producer; public double unsupplied; public double partiallySupplied; public double overSupplied; public double partiallyMin; public double partiallyMax; public double partiallyAverage; public double overMin; public double overMax; public double overAverage; public double activeElements; public double elements; public double essentialFlex; public double highFlex; public double mediumFlex; public double lowFlex; public double flexebilities; public double switches; public double activeSwitches; public double holon; public double consumption; public double production; public double difference; } private class RunAverage{ private int runCount = 0; //Values private RunValues sum = new RunValues(); public void addRun(RunValues val) { sum.result += val.result; sum.executionTime += val.executionTime; sum.passiv += val.passiv; sum.consumer += val.consumer; sum.producer += val.producer; sum.unsupplied += val.unsupplied; sum.partiallySupplied += val.partiallySupplied; sum.overSupplied += val.overSupplied; sum.activeElements += val.activeElements; sum.elements += val.elements; sum.essentialFlex += val.essentialFlex; sum.highFlex += val.highFlex; sum.mediumFlex += val.mediumFlex; sum.lowFlex += val.lowFlex; sum.flexebilities += val.flexebilities; sum.holon += val.holon; sum.switches += val.switches; sum.activeSwitches += val.activeSwitches; sum.consumption += val.consumption; sum.production += val.production; sum.difference += val.difference; sum.objects += val.objects; sum.supplied += val.supplied; sum.partiallyMin += val.partiallyMin; sum.partiallyMax += val.partiallyMax; sum.partiallyAverage += val.partiallyAverage; sum.overMin += val.overMin; sum.overMax += val.overMax; sum.overAverage += val.overAverage; runCount++; } public RunValues getAverage() { RunValues avg = new RunValues(); if(runCount == 0) { return avg; } avg.result = sum.result / runCount; avg.executionTime = sum.executionTime / runCount; avg.passiv = sum.passiv / runCount; avg.consumer = sum.consumer / runCount; avg.producer = sum.producer / runCount; avg.unsupplied = sum.unsupplied / runCount; avg.partiallySupplied = sum.partiallySupplied / runCount; avg.overSupplied = sum.overSupplied / runCount; avg.activeElements = sum.activeElements / runCount; avg.elements = sum.elements / runCount; avg.essentialFlex = sum.essentialFlex / runCount; avg.highFlex = sum.highFlex / runCount; avg.mediumFlex = sum.mediumFlex / runCount; avg.lowFlex = sum.lowFlex / runCount; avg.flexebilities = sum.flexebilities / runCount; avg.holon = sum.holon / runCount; avg.switches = sum.switches / runCount; avg.activeSwitches = sum.activeSwitches / runCount; avg.consumption = sum.consumption / runCount; avg.production = sum.production / runCount; avg.difference = sum.difference / runCount; avg.objects = sum.objects / runCount; avg.supplied = sum.supplied / runCount; avg.supplied = sum.supplied / runCount; avg.partiallyMin = sum.partiallyMin / runCount; avg.partiallyMax = sum.partiallyMax / runCount; avg.partiallyAverage = sum.partiallyAverage / runCount; avg.overMin = sum.overMin / runCount; avg.overMax = sum.overMax / runCount; avg.overAverage = sum.overAverage / runCount; return avg; } } 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; } } }