|
@@ -1,810 +1,812 @@
|
|
|
-package psoAlgoCode;
|
|
|
-
|
|
|
-import classes.*;
|
|
|
-import classes.comparator.EnergyMinToMaxComparator;
|
|
|
-import classes.comparator.MinEnergyComparator;
|
|
|
-import classes.comparator.WeakestBattery;
|
|
|
-import ui.model.Model;
|
|
|
-
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.HashMap;
|
|
|
-
|
|
|
-/**
|
|
|
- * Controller for Simulation.
|
|
|
- *
|
|
|
- * @author Gruppe14
|
|
|
- */
|
|
|
-public class SimulateSimulator {
|
|
|
- int global = 0;
|
|
|
- private Model model;
|
|
|
- private ArrayList<AbstractCpsObject> objectsToHandle;
|
|
|
- private ArrayList<SubNet> subNets;
|
|
|
- private ArrayList<CpsEdge> brokenEdges;
|
|
|
- private int timeStep;
|
|
|
- private HashMap<Integer, Float> tagTable = new HashMap<>();
|
|
|
-
|
|
|
- private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
|
|
|
-
|
|
|
- /**
|
|
|
- * One Element of each HolonObject will be powered first, starting with the
|
|
|
- * smallest Demand. If ale HolonObjects have an active Element, the simulation
|
|
|
- * will try to fully supply as many HolonObjects as possible.
|
|
|
- */
|
|
|
- public static final short fairnessMininumDemandFirst = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * All HolonObjects will receive the same amount of energy.
|
|
|
- */
|
|
|
- public static final short fairnessAllEqual = 1;
|
|
|
-
|
|
|
- /**
|
|
|
- * Constructor.
|
|
|
- *
|
|
|
- * @param m
|
|
|
- * Model
|
|
|
- */
|
|
|
- SimulateSimulator(Model m) {
|
|
|
- model = m;
|
|
|
- subNets = new ArrayList<>();
|
|
|
- brokenEdges = new ArrayList<>();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * calculates the flow of the edges and the supply for objects.
|
|
|
- *
|
|
|
- * @param x
|
|
|
- * current Iteration
|
|
|
- */
|
|
|
- void calculateStateForTimeStep(int x) {
|
|
|
- reset();
|
|
|
- timeStep = x;
|
|
|
- searchForSubNets();
|
|
|
-
|
|
|
- /**
|
|
|
- * Some state reset stuff, seems to be very unnecessary....
|
|
|
- */
|
|
|
- for (SubNet singleSubNet : subNets) {
|
|
|
- if (singleSubNet.getObjects().size() == 0) {
|
|
|
- resetConnections(singleSubNet.getBatteries().get(0), new ArrayList<>(), new ArrayList<>());
|
|
|
- } else {
|
|
|
- resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- for (SubNet singleSubNet : subNets) {
|
|
|
- float production = calculateEnergyWithoutFlexDevices("prod", singleSubNet, timeStep);
|
|
|
- float consumption = calculateEnergyWithoutFlexDevices("cons", singleSubNet, timeStep);
|
|
|
- // surplus of energy is computed by sum, since consumption is a
|
|
|
- // negative value
|
|
|
- float energySurplus = production + consumption;
|
|
|
-
|
|
|
- // --------------- use flexible devices ---------------
|
|
|
- if (energySurplus != 0 && model.useFlexibleDevices()) {
|
|
|
- turnOnFlexibleDevices(singleSubNet, energySurplus, x);
|
|
|
-
|
|
|
- // recompute after having examined/turned on all flexible
|
|
|
- // devices
|
|
|
- production = calculateEnergyWithFlexDevices("prod", singleSubNet, timeStep);
|
|
|
- consumption = calculateEnergyWithFlexDevices("cons", singleSubNet, timeStep);
|
|
|
- energySurplus = production + consumption;
|
|
|
- }
|
|
|
-
|
|
|
- // --------------- set flow simulation ---------------
|
|
|
- setFlowSimulation(singleSubNet);
|
|
|
-
|
|
|
- // --------------- visualise graph ---------------
|
|
|
-
|
|
|
- /**
|
|
|
- * production of subnets, that might be partially turned on/off
|
|
|
- */
|
|
|
- float currentProduction = production;
|
|
|
-
|
|
|
- /**
|
|
|
- * energy each HolonObject receives in AlleEqualModus
|
|
|
- */
|
|
|
-
|
|
|
- if (energySurplus >= 0) {
|
|
|
- // Supply all consumer
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
- float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
|
|
|
- if (neededEnergy < 0) {
|
|
|
- hO.setCurrentSupply(-neededEnergy);
|
|
|
- currentProduction -= -neededEnergy; // Subtract the Energy from the Production
|
|
|
- }
|
|
|
- }
|
|
|
- // Supply all Batterys with the left currentProduction
|
|
|
- singleSubNet.getBatteries().sort(new WeakestBattery(x));// Sort all batteries by the Value of ther
|
|
|
- // StateOfCharge/Capasity
|
|
|
- for (HolonBattery hB : singleSubNet.getBatteries()) {
|
|
|
- float energyToCollect = hB.getInAtTimeStep(x - 1);
|
|
|
- if (currentProduction >= energyToCollect) {
|
|
|
- // change StateofCharge soc = soc + energyToCollect
|
|
|
- hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + energyToCollect, x);
|
|
|
- currentProduction -= energyToCollect;
|
|
|
- } else {
|
|
|
- // change StateofCharge soc = soc + currentProduction
|
|
|
- hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + currentProduction, x);
|
|
|
- currentProduction = 0;
|
|
|
- // no break must be calculatet for all break; //because no more energy
|
|
|
- }
|
|
|
- }
|
|
|
- // Over_Supply all consumer equal
|
|
|
- long nOConsumer = singleSubNet.getObjects().stream()
|
|
|
- .filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
|
|
|
- if (nOConsumer != 0) {
|
|
|
- // energy to seperated equal
|
|
|
- float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer;
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
- float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
|
|
|
- if (neededEnergy < 0) {
|
|
|
- hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject);
|
|
|
- }
|
|
|
- }
|
|
|
- currentProduction = 0;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Check all Battries what they can provide
|
|
|
- if (energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0) {
|
|
|
- singleSubNet.getBatteries().sort(new WeakestBattery(x));// .reverse();
|
|
|
- Collections.reverse(singleSubNet.getBatteries()); // most supplyed first
|
|
|
- // Get the NEEDED energy
|
|
|
- for (HolonBattery hB : singleSubNet.getBatteries()) {
|
|
|
- float neededEnergyFromBattery = currentProduction + consumption; // Energy is negativ
|
|
|
- float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
|
|
|
- if (maxEnergyAvailable >= -neededEnergyFromBattery) {
|
|
|
- // change StateofCharge soc = soc - -neededEnergyFromBattery
|
|
|
- hB.setStateOfChargeAtTimeStep(
|
|
|
- hB.getStateOfChargeAtTimeStep(x - 1) - -neededEnergyFromBattery, x);
|
|
|
- currentProduction += -neededEnergyFromBattery;
|
|
|
- // no break must be calculatet for all beabreak; //When a energy can supply the
|
|
|
- // last needed energy break;
|
|
|
- } else {
|
|
|
- // change StateofCharge soc = soc - maxEnergyAvailable
|
|
|
- hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
|
|
|
- currentProduction += maxEnergyAvailable;
|
|
|
- }
|
|
|
- }
|
|
|
- // Supply all consumer all ar in state Supplied no one is oversupplied because
|
|
|
- // just the energy that is needed is gained from the batteries
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
- float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
|
|
|
- if (neededEnergy < 0) {
|
|
|
- hO.setCurrentSupply(-neededEnergy);
|
|
|
- currentProduction -= -neededEnergy; // Subtract the Energy from the Production
|
|
|
- }
|
|
|
- }
|
|
|
- } else // Objects have to be partially supplied
|
|
|
- {
|
|
|
- // Get all Energy out of battries as possible
|
|
|
- for (HolonBattery hB : singleSubNet.getBatteries()) {
|
|
|
- float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
|
|
|
- // change StateofCharge soc = soc - maxEnergyAvailable
|
|
|
- hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
|
|
|
- currentProduction += maxEnergyAvailable;
|
|
|
- }
|
|
|
- // Calc
|
|
|
- singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0));
|
|
|
- if (model.getFairnessModel() == fairnessAllEqual) {
|
|
|
- long nOConsumer = singleSubNet.getObjects().stream()
|
|
|
- .filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
|
|
|
- float energyPerHolonObject = 0;
|
|
|
- if (nOConsumer != 0)
|
|
|
- energyPerHolonObject = currentProduction / nOConsumer;
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
- if (hO.getCurrentEnergyAtTimeStep(x) < 0) // Just Consumer need Energy
|
|
|
- {
|
|
|
- hO.setCurrentSupply(energyPerHolonObject);
|
|
|
- currentProduction -= energyPerHolonObject; // Subtract the Energy from the Production
|
|
|
- }
|
|
|
- }
|
|
|
- } else // (model.getFairnessModel() == fairnessMininumDemandFirst)
|
|
|
- {
|
|
|
- singleSubNet.getObjects().sort(new MinEnergyComparator(x));
|
|
|
- // SupplyAllMinimumEnergy
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
- if (hO.checkIfPartiallySupplied(x))
|
|
|
- continue;
|
|
|
- if (hO.getCurrentEnergyAtTimeStep(x) > 0)
|
|
|
- continue;
|
|
|
- float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); // Energy from getMinEnergy is negative -> convert to
|
|
|
- // positive
|
|
|
- if (minEnergy <= currentProduction) {
|
|
|
- hO.setCurrentSupply(minEnergy);
|
|
|
- currentProduction -= minEnergy;
|
|
|
- } else {
|
|
|
- hO.setCurrentSupply(currentProduction);
|
|
|
- currentProduction = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x));
|
|
|
- // supplyFullytillEnd ... because its cant be fully supplied
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
-
|
|
|
- float actualSupplyEnergy = hO.getCurrentSupply();
|
|
|
- float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy;
|
|
|
- if (neededEnergy <= 0)
|
|
|
- continue; // Producer or No EnergyNeeded
|
|
|
- if (neededEnergy <= currentProduction) {
|
|
|
- hO.setCurrentSupply(neededEnergy + actualSupplyEnergy);
|
|
|
- currentProduction -= neededEnergy;
|
|
|
- } else {
|
|
|
- hO.setCurrentSupply(currentProduction + actualSupplyEnergy);
|
|
|
- currentProduction = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- // Visualize the Color
|
|
|
- for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
- float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for
|
|
|
- // calculations
|
|
|
- if (neededEnergy < 0) {
|
|
|
- hO.setState(HolonObject.PRODUCER);
|
|
|
- } else if (neededEnergy > 0) {
|
|
|
- float currentSupply = hO.getCurrentSupply();
|
|
|
- if (currentSupply > neededEnergy) {
|
|
|
- hO.setState(HolonObject.OVER_SUPPLIED);
|
|
|
- } else if (currentSupply == neededEnergy) {
|
|
|
- hO.setState(HolonObject.SUPPLIED);
|
|
|
- } else if (currentSupply < neededEnergy) {
|
|
|
- float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x);
|
|
|
- if (currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy) {
|
|
|
- hO.setState(HolonObject.PARTIALLY_SUPPLIED);
|
|
|
- } else {
|
|
|
- hO.setState(HolonObject.NOT_SUPPLIED);
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (neededEnergy == 0) {
|
|
|
- hO.setState(HolonObject.NO_ENERGY);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * add all battries.getOut() from a list of battries and return them
|
|
|
- *
|
|
|
- * @param aL
|
|
|
- * a List of HolonBattries likely from subnet.getBatteries()
|
|
|
- * @param x
|
|
|
- * TimeStep
|
|
|
- * @return
|
|
|
- *
|
|
|
- */
|
|
|
- private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x) {
|
|
|
- float OutEnergy = 0;
|
|
|
- for (HolonBattery hB : aL) {
|
|
|
- OutEnergy += hB.getOutAtTimeStep(x - 1);
|
|
|
- }
|
|
|
- return OutEnergy;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * search for all flexible devices in the network and turn them on, until energy
|
|
|
- * surplus = 0 or all devices have been examined.
|
|
|
- *
|
|
|
- * This code could be compressed (cases inside over- and underproduction are the
|
|
|
- * same), but we decided that it is better readable this way
|
|
|
- *
|
|
|
- * @param subNet
|
|
|
- * the subnet
|
|
|
- * @param energySurplus
|
|
|
- * the current surplus of energy
|
|
|
- */
|
|
|
- private void turnOnFlexibleDevices(SubNet subNet, float energySurplus, int timestep) {
|
|
|
- for (HolonObject holonOb : subNet.getObjects()) {
|
|
|
- for (HolonElement holonEl : holonOb.getElements()) {
|
|
|
-
|
|
|
- // if this element is flexible and active (can be considered for
|
|
|
- // calculations)
|
|
|
- if (holonEl.isFlexible() && holonEl.isActive()) {
|
|
|
- float energyAvailableSingle = holonEl.getAvailableEnergyAt(timestep);
|
|
|
- float energyAvailableMultiple = energyAvailableSingle * holonEl.getAmount();
|
|
|
-
|
|
|
- // ------------- flexible consumer / OVERPRODUCTION
|
|
|
- // -------------
|
|
|
- if (energyAvailableMultiple < 0 && energySurplus > 0) {
|
|
|
-
|
|
|
- // if there is more wasted energy than energy that this
|
|
|
- // device can give, give all energy available
|
|
|
- if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
|
|
|
- energySurplus += energyAvailableMultiple;
|
|
|
- // set the new energy consumption to the maximum
|
|
|
- holonEl.setEnergyPerElement(energyAvailableSingle);
|
|
|
- flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
|
|
|
- }
|
|
|
- // else: we just need to turn on part of the flexible
|
|
|
- // energy available
|
|
|
- else {
|
|
|
- float energyNeeded = -energySurplus;
|
|
|
- energySurplus += energyNeeded; // should give 0, but
|
|
|
- // was kept this was
|
|
|
- // for consistency
|
|
|
- // the energy needed divided through the amount of
|
|
|
- // elements
|
|
|
- holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
|
|
|
- flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // ------------- flexible producer / UNDERPRODUCTION
|
|
|
- // -------------
|
|
|
- else if (energyAvailableMultiple > 0 && energySurplus < 0) {
|
|
|
-
|
|
|
- // if there is more energy needed than this device can
|
|
|
- // give, give all the energy available
|
|
|
- if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
|
|
|
- energySurplus += energyAvailableMultiple;
|
|
|
- // set the new energy consumption to the maximum
|
|
|
- holonEl.setEnergyPerElement(energyAvailableSingle);
|
|
|
- flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
|
|
|
- }
|
|
|
- // else: we just need to turn on part of the flexible
|
|
|
- // energy available
|
|
|
- else {
|
|
|
- float energyNeeded = -energySurplus;
|
|
|
- int i = 0;
|
|
|
- energySurplus += energyNeeded; // should give 0, but
|
|
|
- // was kept this was
|
|
|
- // for consistency
|
|
|
- // the energy needed divided through the amount of
|
|
|
- // elements
|
|
|
- holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
|
|
|
- flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (energySurplus == 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (energySurplus == 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Set Flow Simulation.
|
|
|
- *
|
|
|
- * @param sN
|
|
|
- * Subnet
|
|
|
- */
|
|
|
- private void setFlowSimulation(SubNet sN) {
|
|
|
- ArrayList<AbstractCpsObject> producers = new ArrayList<>();
|
|
|
- AbstractCpsObject tmp = null;
|
|
|
- tagTable = new HashMap<>();
|
|
|
- // traverse all objects in this subnet
|
|
|
- for (HolonObject hl : sN.getObjects()) {
|
|
|
- float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
|
|
|
- // if their production is higher than their consumption
|
|
|
- if (energy > 0) {
|
|
|
- tagTable.put(hl.getId(), energy);
|
|
|
- hl.addTag(hl.getId());
|
|
|
- for (CpsEdge edge : hl.getConnections()) {
|
|
|
- if (edge.isWorking()) {
|
|
|
- // set other end of edge as tmp-object
|
|
|
- // and add this end to the other end's tag-list
|
|
|
- AbstractCpsObject a = edge.getA();
|
|
|
- AbstractCpsObject b = edge.getB();
|
|
|
- if (a.getId() == hl.getId()) {
|
|
|
- b.addTag(hl.getId());
|
|
|
- tmp = b;
|
|
|
- }
|
|
|
- if (b.getId() == hl.getId()) {
|
|
|
- a.addTag(hl.getId());
|
|
|
- tmp = a;
|
|
|
- }
|
|
|
-
|
|
|
- edge.setFlow(edge.getFlow() + energy);
|
|
|
- edge.calculateState();
|
|
|
- edge.addTag(hl.getId());
|
|
|
- if (edge.isWorking() && !producers.contains(tmp)) {
|
|
|
- if (tmp instanceof HolonSwitch) {
|
|
|
- if (((HolonSwitch) tmp).getState(timeStep)) {
|
|
|
- producers.add(tmp);
|
|
|
- }
|
|
|
- } else if (!(tmp instanceof CpsUpperNode)) {
|
|
|
- producers.add(tmp);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- setFlowSimRec(producers, 0);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Set Flow Simulation Rec.
|
|
|
- *
|
|
|
- * @param nodes
|
|
|
- * the nodes
|
|
|
- * @param iter
|
|
|
- * the Iteration
|
|
|
- */
|
|
|
- private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
|
|
|
- ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
|
|
|
- ArrayList<CpsEdge> changedEdges = new ArrayList<>();
|
|
|
- AbstractCpsObject tmp;
|
|
|
- if (nodes.size() != 0) {
|
|
|
- for (AbstractCpsObject cps : nodes) {
|
|
|
- // check whether the cps is in a legit state if it is a switch
|
|
|
- if (legitState(cps)) {
|
|
|
- for (CpsEdge edge : cps.getConnections()) {
|
|
|
- // is edge working
|
|
|
- // and does the edge's tag-list not (yet) contain all
|
|
|
- // tags of the cps
|
|
|
- if (edge.isWorking() && (!(edge.containsTags(edge.getTags(), cps.getTag())))) {
|
|
|
- if (edge.getA().getId() == cps.getId()) {
|
|
|
- tmp = edge.getB();
|
|
|
- } else {
|
|
|
- tmp = edge.getA();
|
|
|
- }
|
|
|
- for (Integer tag : cps.getTag()) {
|
|
|
- if (!(edge.getTags().contains(tag)) && !(edge.getPseudoTags().contains(tag))) {
|
|
|
- edge.setFlow(edge.getFlow() + tagTable.get(tag));
|
|
|
- edge.addTag(tag);
|
|
|
- }
|
|
|
- }
|
|
|
- // uppernodes do not spread energy
|
|
|
- if (!(tmp instanceof CpsUpperNode)) {
|
|
|
- for (Integer tag : tmp.getTag()) {
|
|
|
- if (!(edge.getTags().contains(tag)) && tagTable.get(tag) != null
|
|
|
- && !(edge.getPseudoTags().contains(tag))) {
|
|
|
- edge.setFlow(edge.getFlow() + tagTable.get(tag));
|
|
|
- edge.addPseudoTag(tag);
|
|
|
- changedEdges.add(edge);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- edge.calculateState();
|
|
|
- if (edge.isWorking() && !(tmp instanceof CpsUpperNode)) {
|
|
|
- tmp.addAllPseudoTags(cps.getTag());
|
|
|
- if (!newNodes.contains(tmp)) {
|
|
|
- newNodes.add(tmp);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- setPseudoTags(newNodes, changedEdges);
|
|
|
- setFlowSimRec(newNodes, iter + 1);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Set the Pseudo Tags.
|
|
|
- *
|
|
|
- * @param nodes
|
|
|
- * Array of AbstractCpsObjects
|
|
|
- */
|
|
|
- private void setPseudoTags(ArrayList<AbstractCpsObject> nodes, ArrayList<CpsEdge> edges) {
|
|
|
- for (AbstractCpsObject node : nodes) {
|
|
|
- node.recalculateTags();
|
|
|
- node.setPseudoTags(new ArrayList<>());
|
|
|
- }
|
|
|
- for (CpsEdge edge : edges) {
|
|
|
- edge.recalculateTags();
|
|
|
- edge.setPseudoTag(new ArrayList<>());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Reset the Connection.
|
|
|
- *
|
|
|
- * @param cps
|
|
|
- * CpsObject
|
|
|
- * @param visitedObj
|
|
|
- * the visited Objects
|
|
|
- * @param visitedEdges
|
|
|
- * the visited Edges
|
|
|
- */
|
|
|
- private void resetConnections(AbstractCpsObject cps, ArrayList<Integer> visitedObj,
|
|
|
- ArrayList<CpsEdge> visitedEdges) {
|
|
|
- visitedObj.add(cps.getId());
|
|
|
- cps.resetTags();
|
|
|
- for (CpsEdge e : cps.getConnections()) {
|
|
|
- if (!(visitedEdges.contains(e))) {
|
|
|
- e.setFlow(0);
|
|
|
- e.calculateState();
|
|
|
- e.setTags(new ArrayList<>());
|
|
|
- visitedEdges.add(e);
|
|
|
- if (!(visitedObj.contains(e.getA().getId()))) {
|
|
|
- resetConnections(e.getA(), visitedObj, visitedEdges);
|
|
|
- e.getA().resetTags();
|
|
|
- }
|
|
|
- if (!(visitedObj.contains(e.getB().getId()))) {
|
|
|
- resetConnections(e.getB(), visitedObj, visitedEdges);
|
|
|
- e.getB().resetTags();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * calculates the energy of either all producers or consumers. Flexible devices
|
|
|
- * are filtered out
|
|
|
- *
|
|
|
- * @param type
|
|
|
- * Type
|
|
|
- * @param sN
|
|
|
- * Subnet
|
|
|
- * @param x
|
|
|
- * Integer
|
|
|
- * @return The Energy
|
|
|
- */
|
|
|
- private float calculateEnergyWithoutFlexDevices(String type, SubNet sN, int x) {
|
|
|
- float energy = 0;
|
|
|
- for (HolonObject hl : sN.getObjects()) {
|
|
|
- float currentEnergyWithoutFlexibles = hl.getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
|
|
|
-
|
|
|
- if (type.equals("prod")) {
|
|
|
- if (currentEnergyWithoutFlexibles > 0) {
|
|
|
- energy += currentEnergyWithoutFlexibles;
|
|
|
- hl.setState(HolonObject.PRODUCER);
|
|
|
- }
|
|
|
- }
|
|
|
- if (type.equals("cons")) {
|
|
|
- if (currentEnergyWithoutFlexibles < 0) {
|
|
|
- energy += currentEnergyWithoutFlexibles;
|
|
|
- hl.setState(HolonObject.NOT_SUPPLIED);
|
|
|
- }
|
|
|
- }
|
|
|
- if (currentEnergyWithoutFlexibles == 0) {
|
|
|
- hl.setState(HolonObject.NO_ENERGY);
|
|
|
- }
|
|
|
- }
|
|
|
- return energy;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * calculates the energy of either all producers or consumers. Flexible devices
|
|
|
- * are filtered out
|
|
|
- *
|
|
|
- * @param type
|
|
|
- * Type
|
|
|
- * @param sN
|
|
|
- * Subnet
|
|
|
- * @param x
|
|
|
- * Integer
|
|
|
- * @return The Energy
|
|
|
- */
|
|
|
- private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
|
|
|
- float energy = 0;
|
|
|
- for (HolonObject hl : sN.getObjects()) {
|
|
|
- float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
|
|
|
-
|
|
|
- if (type.equals("prod")) {
|
|
|
- if (currentEnergy > 0) {
|
|
|
- energy += currentEnergy;
|
|
|
- hl.setState(HolonObject.PRODUCER);
|
|
|
- }
|
|
|
- }
|
|
|
- if (type.equals("cons")) {
|
|
|
- if (currentEnergy < 0) {
|
|
|
- energy = energy + currentEnergy;
|
|
|
- hl.setState(HolonObject.NOT_SUPPLIED);
|
|
|
- }
|
|
|
- }
|
|
|
- if (currentEnergy == 0) {
|
|
|
- hl.setState(HolonObject.NO_ENERGY);
|
|
|
- }
|
|
|
- }
|
|
|
- return energy;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * generates all subNets from all objectsToHandle.
|
|
|
- */
|
|
|
- private void searchForSubNets() {
|
|
|
- subNets = new ArrayList<>();
|
|
|
- brokenEdges.clear();
|
|
|
- boolean end = false;
|
|
|
- int i = 0;
|
|
|
- AbstractCpsObject cps;
|
|
|
- if (objectsToHandle.size() > 0) {
|
|
|
- while (!end) {
|
|
|
- cps = objectsToHandle.get(i);
|
|
|
- SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),
|
|
|
- new ArrayList<>());
|
|
|
- singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
|
|
|
- if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0) {
|
|
|
- subNets.add(singleSubNet);
|
|
|
- }
|
|
|
- if (0 == objectsToHandle.size()) {
|
|
|
- end = true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * recursivly generates a subnet of all objects, that one specific object is
|
|
|
- * connected to.
|
|
|
- *
|
|
|
- * @param cps
|
|
|
- * AbstractCpsObject
|
|
|
- * @param visited
|
|
|
- * visited Array of Integer
|
|
|
- * @param sN
|
|
|
- * Subnets
|
|
|
- * @return Subnet
|
|
|
- */
|
|
|
- private SubNet buildSubNet(AbstractCpsObject cps, ArrayList<Integer> visited, SubNet sN) {
|
|
|
- visited.add(cps.getId());
|
|
|
- if (cps instanceof HolonObject) {
|
|
|
- sN.getObjects().add((HolonObject) cps);
|
|
|
- }
|
|
|
- if (cps instanceof HolonSwitch) {
|
|
|
- sN.getSwitches().add((HolonSwitch) cps);
|
|
|
- }
|
|
|
- if (cps instanceof HolonBattery) {
|
|
|
- sN.getBatteries().add((HolonBattery) cps);
|
|
|
- }
|
|
|
- removeFromToHandle(cps.getId());
|
|
|
- AbstractCpsObject a;
|
|
|
- AbstractCpsObject b;
|
|
|
- for (CpsEdge edge : cps.getConnections()) {
|
|
|
- if (edge.isWorking()) {
|
|
|
- a = edge.getA();
|
|
|
- b = edge.getB();
|
|
|
- if (!(cps instanceof HolonSwitch)) {
|
|
|
- if (!(sN.getEdges().contains(edge))) {
|
|
|
- sN.getEdges().add(edge);
|
|
|
- }
|
|
|
- }
|
|
|
- if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) {
|
|
|
- if (!(sN.getEdges().contains(edge))) {
|
|
|
- sN.getEdges().add(edge);
|
|
|
- }
|
|
|
- }
|
|
|
- if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) {
|
|
|
- sN = buildSubNet(a, visited, sN);
|
|
|
- }
|
|
|
- if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) {
|
|
|
- sN = buildSubNet(b, visited, sN);
|
|
|
- }
|
|
|
- if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
|
|
|
- edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
|
|
|
- checkForConnectedStates(b, (CpsUpperNode) a, edge);
|
|
|
- }
|
|
|
- if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
|
|
|
- edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
|
|
|
- checkForConnectedStates(a, (CpsUpperNode) b, edge);
|
|
|
- }
|
|
|
- } else {
|
|
|
- brokenEdges.add(edge);
|
|
|
- }
|
|
|
- }
|
|
|
- return sN;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * is the Switch in a legitimate State.
|
|
|
- *
|
|
|
- * @param current
|
|
|
- * AbstractCpsObject
|
|
|
- * @return boolean
|
|
|
- */
|
|
|
- private boolean legitState(AbstractCpsObject current) {
|
|
|
- return !(current instanceof HolonSwitch) || ((HolonSwitch) current).getState(timeStep);
|
|
|
- }
|
|
|
-
|
|
|
- // /**
|
|
|
- // * ensures that objectsToHandle only contains HolonObjects.
|
|
|
- // */
|
|
|
- // public void cleanObjectsToHandle() {
|
|
|
- // for (int i = 0; i < objectsToHandle.size(); i++) {
|
|
|
- // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
|
|
|
- // objectsToHandle.remove(i);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- /**
|
|
|
- * removes an Object that already has been handled.
|
|
|
- *
|
|
|
- * @param id
|
|
|
- * the Object ID
|
|
|
- */
|
|
|
- private void removeFromToHandle(int id) {
|
|
|
- for (int i = 0; i < objectsToHandle.size(); i++) {
|
|
|
- if (objectsToHandle.get(i).getId() == id) {
|
|
|
- objectsToHandle.remove(i);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * copies the data of an array of Objects.
|
|
|
- *
|
|
|
- * @param toCopy
|
|
|
- * the ArrayList of CpsObjects co Copy
|
|
|
- */
|
|
|
- private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
|
|
|
- for (AbstractCpsObject cps : toCopy) {
|
|
|
- if (cps instanceof CpsUpperNode) {
|
|
|
- copyObjects(((CpsUpperNode) cps).getNodes());
|
|
|
- } else {
|
|
|
- objectsToHandle.add(cps);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Reset all Data to the current state of the Model.
|
|
|
- */
|
|
|
- public void reset() {
|
|
|
- objectsToHandle = new ArrayList<>();
|
|
|
- copyObjects(model.getObjectsOnCanvas());
|
|
|
- flexDevicesTurnedOnThisTurn = new HashMap<>();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Resets the State of all Edges
|
|
|
- */
|
|
|
- private void resetEdges() {
|
|
|
- for (CpsEdge e : brokenEdges) {
|
|
|
- e.setWorkingState(true);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Resets the State for the whole Simulation Model
|
|
|
- */
|
|
|
- void resetSimulation() {
|
|
|
- reset();
|
|
|
- resetEdges();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Get all Subnets.
|
|
|
- *
|
|
|
- * @return all Subnets
|
|
|
- */
|
|
|
- public ArrayList<SubNet> getSubNets() {
|
|
|
- return subNets;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Get broken Edges
|
|
|
- */
|
|
|
- // public ArrayList<CpsEdge> getBrokenEdges() {
|
|
|
- // return brokenEdges;
|
|
|
- // }
|
|
|
-
|
|
|
- /**
|
|
|
- * checks whether a given object is connected to an object inside the upperNode.
|
|
|
- * if yes, the state for the edge is changed in "connected" or "not connected"
|
|
|
- */
|
|
|
- private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) {
|
|
|
- AbstractCpsObject tmp;
|
|
|
- for (CpsEdge edge : cps.getConnections()) {
|
|
|
- if (edge.getA().getId() == cps.getId()) {
|
|
|
- tmp = edge.getB();
|
|
|
- } else {
|
|
|
- tmp = edge.getA();
|
|
|
- }
|
|
|
- if (cUNode.getNodes().contains(tmp)) {
|
|
|
- if (tmp instanceof CpsUpperNode) {
|
|
|
- checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
|
|
|
- } else {
|
|
|
- theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
+package psoAlgoCode;
|
|
|
+
|
|
|
+import classes.*;
|
|
|
+import classes.comparator.EnergyMinToMaxComparator;
|
|
|
+import classes.comparator.MinEnergyComparator;
|
|
|
+import classes.comparator.WeakestBattery;
|
|
|
+import ui.model.Model;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Controller for Simulation.
|
|
|
+ *
|
|
|
+ * @author Gruppe14
|
|
|
+ */
|
|
|
+public class SimulateSimulator {
|
|
|
+ int global = 0;
|
|
|
+ private Model model;
|
|
|
+ private ArrayList<AbstractCpsObject> objectsToHandle;
|
|
|
+ private ArrayList<SubNet> subNets;
|
|
|
+ private ArrayList<CpsEdge> brokenEdges;
|
|
|
+ private int timeStep;
|
|
|
+ private HashMap<Integer, Float> tagTable = new HashMap<>();
|
|
|
+
|
|
|
+ private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * One Element of each HolonObject will be powered first, starting with the
|
|
|
+ * smallest Demand. If ale HolonObjects have an active Element, the simulation
|
|
|
+ * will try to fully supply as many HolonObjects as possible.
|
|
|
+ */
|
|
|
+ public static final short fairnessMininumDemandFirst = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * All HolonObjects will receive the same amount of energy.
|
|
|
+ */
|
|
|
+ public static final short fairnessAllEqual = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Constructor.
|
|
|
+ *
|
|
|
+ * @param m
|
|
|
+ * Model
|
|
|
+ */
|
|
|
+ SimulateSimulator(Model m) {
|
|
|
+ model = m;
|
|
|
+ subNets = new ArrayList<>();
|
|
|
+ brokenEdges = new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * calculates the flow of the edges and the supply for objects.
|
|
|
+ *
|
|
|
+ * @param x
|
|
|
+ * current Iteration
|
|
|
+ */
|
|
|
+ void calculateStateForTimeStep(int x) {
|
|
|
+ reset();
|
|
|
+ timeStep = x;
|
|
|
+ searchForSubNets();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Some state reset stuff, seems to be very unnecessary.... COMMENT THIS IN IF STRANGE CALCULATION STUFF HAPPENS
|
|
|
+ */
|
|
|
+ /*for (SubNet singleSubNet : subNets) {
|
|
|
+ if (singleSubNet.getObjects().size() == 0) {
|
|
|
+ resetConnections(singleSubNet.getBatteries().get(0), new ArrayList<>(), new ArrayList<>());
|
|
|
+ } else {
|
|
|
+ resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
|
|
|
+ }
|
|
|
+
|
|
|
+ }*/
|
|
|
+ for (SubNet singleSubNet : subNets) {
|
|
|
+ float production = calculateEnergyWithoutFlexDevices("prod", singleSubNet, timeStep);
|
|
|
+ float consumption = calculateEnergyWithoutFlexDevices("cons", singleSubNet, timeStep);
|
|
|
+ // surplus of energy is computed by sum, since consumption is a
|
|
|
+ // negative value
|
|
|
+ float energySurplus = production + consumption;
|
|
|
+
|
|
|
+ // --------------- use flexible devices ---------------
|
|
|
+ /*if (energySurplus != 0 && model.useFlexibleDevices()) {
|
|
|
+ turnOnFlexibleDevices(singleSubNet, energySurplus, x);
|
|
|
+
|
|
|
+ // recompute after having examined/turned on all flexible
|
|
|
+ // devices
|
|
|
+ production = calculateEnergyWithFlexDevices("prod", singleSubNet, timeStep);
|
|
|
+ consumption = calculateEnergyWithFlexDevices("cons", singleSubNet, timeStep);
|
|
|
+ energySurplus = production + consumption;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ // --------------- set flow simulation ---------------
|
|
|
+ setFlowSimulation(singleSubNet);
|
|
|
+
|
|
|
+ // --------------- visualise graph ---------------
|
|
|
+
|
|
|
+ /**
|
|
|
+ * production of subnets, that might be partially turned on/off
|
|
|
+ */
|
|
|
+ float currentProduction = production;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * energy each HolonObject receives in AlleEqualModus
|
|
|
+ */
|
|
|
+
|
|
|
+ if (energySurplus >= 0) {
|
|
|
+ // Supply all consumer
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+ float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
|
|
|
+ if (neededEnergy < 0) {
|
|
|
+ hO.setCurrentSupply(-neededEnergy);
|
|
|
+ currentProduction -= -neededEnergy; // Subtract the Energy from the Production
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Supply all Batterys with the left currentProduction
|
|
|
+ singleSubNet.getBatteries().sort(new WeakestBattery(x));// Sort all batteries by the Value of ther
|
|
|
+ // StateOfCharge/Capasity
|
|
|
+ for (HolonBattery hB : singleSubNet.getBatteries()) {
|
|
|
+ float energyToCollect = hB.getInAtTimeStep(x - 1);
|
|
|
+ if (currentProduction >= energyToCollect) {
|
|
|
+ // change StateofCharge soc = soc + energyToCollect
|
|
|
+ hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + energyToCollect, x);
|
|
|
+ currentProduction -= energyToCollect;
|
|
|
+ } else {
|
|
|
+ // change StateofCharge soc = soc + currentProduction
|
|
|
+ hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + currentProduction, x);
|
|
|
+ currentProduction = 0;
|
|
|
+ // no break must be calculatet for all break; //because no more energy
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Over_Supply all consumer equal
|
|
|
+ long nOConsumer = singleSubNet.getObjects().stream()
|
|
|
+ .filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
|
|
|
+ if (nOConsumer != 0) {
|
|
|
+ // energy to seperated equal
|
|
|
+ float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer;
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+ float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
|
|
|
+ if (neededEnergy < 0) {
|
|
|
+ hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ currentProduction = 0;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // Check all Battries what they can provide
|
|
|
+ if (energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0) {
|
|
|
+ singleSubNet.getBatteries().sort(new WeakestBattery(x));// .reverse();
|
|
|
+ Collections.reverse(singleSubNet.getBatteries()); // most supplyed first
|
|
|
+ // Get the NEEDED energy
|
|
|
+ for (HolonBattery hB : singleSubNet.getBatteries()) {
|
|
|
+ float neededEnergyFromBattery = currentProduction + consumption; // Energy is negativ
|
|
|
+ float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
|
|
|
+ if (maxEnergyAvailable >= -neededEnergyFromBattery) {
|
|
|
+ // change StateofCharge soc = soc - -neededEnergyFromBattery
|
|
|
+ hB.setStateOfChargeAtTimeStep(
|
|
|
+ hB.getStateOfChargeAtTimeStep(x - 1) - -neededEnergyFromBattery, x);
|
|
|
+ currentProduction += -neededEnergyFromBattery;
|
|
|
+ // no break must be calculatet for all beabreak; //When a energy can supply the
|
|
|
+ // last needed energy break;
|
|
|
+ } else {
|
|
|
+ // change StateofCharge soc = soc - maxEnergyAvailable
|
|
|
+ hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
|
|
|
+ currentProduction += maxEnergyAvailable;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Supply all consumer all ar in state Supplied no one is oversupplied because
|
|
|
+ // just the energy that is needed is gained from the batteries
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+ float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
|
|
|
+ if (neededEnergy < 0) {
|
|
|
+ hO.setCurrentSupply(-neededEnergy);
|
|
|
+ currentProduction -= -neededEnergy; // Subtract the Energy from the Production
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else // Objects have to be partially supplied
|
|
|
+ {
|
|
|
+ // Get all Energy out of battries as possible
|
|
|
+ for (HolonBattery hB : singleSubNet.getBatteries()) {
|
|
|
+ float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
|
|
|
+ // change StateofCharge soc = soc - maxEnergyAvailable
|
|
|
+ hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
|
|
|
+ currentProduction += maxEnergyAvailable;
|
|
|
+ }
|
|
|
+ // Calc
|
|
|
+ singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0));
|
|
|
+ if (model.getFairnessModel() == fairnessAllEqual) {
|
|
|
+ long nOConsumer = singleSubNet.getObjects().stream()
|
|
|
+ .filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
|
|
|
+ float energyPerHolonObject = 0;
|
|
|
+ if (nOConsumer != 0)
|
|
|
+ energyPerHolonObject = currentProduction / nOConsumer;
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+ if (hO.getCurrentEnergyAtTimeStep(x) < 0) // Just Consumer need Energy
|
|
|
+ {
|
|
|
+ hO.setCurrentSupply(energyPerHolonObject);
|
|
|
+ currentProduction -= energyPerHolonObject; // Subtract the Energy from the Production
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else // (model.getFairnessModel() == fairnessMininumDemandFirst)
|
|
|
+ {
|
|
|
+ singleSubNet.getObjects().sort(new MinEnergyComparator(x));
|
|
|
+ // SupplyAllMinimumEnergy
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+ if (hO.checkIfPartiallySupplied(x))
|
|
|
+ continue;
|
|
|
+ if (hO.getCurrentEnergyAtTimeStep(x) > 0)
|
|
|
+ continue;
|
|
|
+ float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); // Energy from getMinEnergy is negative -> convert to
|
|
|
+ // positive
|
|
|
+ if (minEnergy <= currentProduction) {
|
|
|
+ hO.setCurrentSupply(minEnergy);
|
|
|
+ currentProduction -= minEnergy;
|
|
|
+ } else {
|
|
|
+ hO.setCurrentSupply(currentProduction);
|
|
|
+ currentProduction = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x));
|
|
|
+ // supplyFullytillEnd ... because its cant be fully supplied
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+
|
|
|
+ float actualSupplyEnergy = hO.getCurrentSupply();
|
|
|
+ float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy;
|
|
|
+ if (neededEnergy <= 0)
|
|
|
+ continue; // Producer or No EnergyNeeded
|
|
|
+ if (neededEnergy <= currentProduction) {
|
|
|
+ hO.setCurrentSupply(neededEnergy + actualSupplyEnergy);
|
|
|
+ currentProduction -= neededEnergy;
|
|
|
+ } else {
|
|
|
+ hO.setCurrentSupply(currentProduction + actualSupplyEnergy);
|
|
|
+ currentProduction = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // Visualize the Color
|
|
|
+ for (HolonObject hO : singleSubNet.getObjects()) {
|
|
|
+ float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for
|
|
|
+ // calculations
|
|
|
+ if (neededEnergy < 0) {
|
|
|
+ hO.setState(HolonObject.PRODUCER);
|
|
|
+ } else if (neededEnergy > 0) {
|
|
|
+ float currentSupply = hO.getCurrentSupply();
|
|
|
+ if (currentSupply > neededEnergy) {
|
|
|
+ hO.setState(HolonObject.OVER_SUPPLIED);
|
|
|
+ } else if (currentSupply == neededEnergy) {
|
|
|
+ hO.setState(HolonObject.SUPPLIED);
|
|
|
+ } else if (currentSupply < neededEnergy) {
|
|
|
+ float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x);
|
|
|
+ if (currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy) {
|
|
|
+ hO.setState(HolonObject.PARTIALLY_SUPPLIED);
|
|
|
+ } else {
|
|
|
+ hO.setState(HolonObject.NOT_SUPPLIED);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (neededEnergy == 0) {
|
|
|
+ hO.setState(HolonObject.NO_ENERGY);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * add all battries.getOut() from a list of battries and return them
|
|
|
+ *
|
|
|
+ * @param aL
|
|
|
+ * a List of HolonBattries likely from subnet.getBatteries()
|
|
|
+ * @param x
|
|
|
+ * TimeStep
|
|
|
+ * @return
|
|
|
+ *
|
|
|
+ */
|
|
|
+ private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x) {
|
|
|
+ float OutEnergy = 0;
|
|
|
+ for (HolonBattery hB : aL) {
|
|
|
+ OutEnergy += hB.getOutAtTimeStep(x - 1);
|
|
|
+ }
|
|
|
+ return OutEnergy;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * search for all flexible devices in the network and turn them on, until energy
|
|
|
+ * surplus = 0 or all devices have been examined.
|
|
|
+ *
|
|
|
+ * This code could be compressed (cases inside over- and underproduction are the
|
|
|
+ * same), but we decided that it is better readable this way
|
|
|
+ *
|
|
|
+ * @param subNet
|
|
|
+ * the subnet
|
|
|
+ * @param energySurplus
|
|
|
+ * the current surplus of energy
|
|
|
+ */
|
|
|
+ private void turnOnFlexibleDevices(SubNet subNet, float energySurplus, int timestep) {
|
|
|
+ for (HolonObject holonOb : subNet.getObjects()) {
|
|
|
+ for (HolonElement holonEl : holonOb.getElements()) {
|
|
|
+
|
|
|
+ // if this element is flexible and active (can be considered for
|
|
|
+ // calculations)
|
|
|
+ if (holonEl.isFlexible() && holonEl.isActive()) {
|
|
|
+ float energyAvailableSingle = holonEl.getAvailableEnergyAt(timestep);
|
|
|
+ float energyAvailableMultiple = energyAvailableSingle * holonEl.getAmount();
|
|
|
+
|
|
|
+ // ------------- flexible consumer / OVERPRODUCTION
|
|
|
+ // -------------
|
|
|
+ if (energyAvailableMultiple < 0 && energySurplus > 0) {
|
|
|
+
|
|
|
+ // if there is more wasted energy than energy that this
|
|
|
+ // device can give, give all energy available
|
|
|
+ if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
|
|
|
+ energySurplus += energyAvailableMultiple;
|
|
|
+ // set the new energy consumption to the maximum
|
|
|
+ holonEl.setEnergyPerElement(energyAvailableSingle);
|
|
|
+ flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
|
|
|
+ }
|
|
|
+ // else: we just need to turn on part of the flexible
|
|
|
+ // energy available
|
|
|
+ else {
|
|
|
+ float energyNeeded = -energySurplus;
|
|
|
+ energySurplus += energyNeeded; // should give 0, but
|
|
|
+ // was kept this was
|
|
|
+ // for consistency
|
|
|
+ // the energy needed divided through the amount of
|
|
|
+ // elements
|
|
|
+ holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
|
|
|
+ flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------- flexible producer / UNDERPRODUCTION
|
|
|
+ // -------------
|
|
|
+ else if (energyAvailableMultiple > 0 && energySurplus < 0) {
|
|
|
+
|
|
|
+ // if there is more energy needed than this device can
|
|
|
+ // give, give all the energy available
|
|
|
+ if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
|
|
|
+ energySurplus += energyAvailableMultiple;
|
|
|
+ // set the new energy consumption to the maximum
|
|
|
+ holonEl.setEnergyPerElement(energyAvailableSingle);
|
|
|
+ flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
|
|
|
+ }
|
|
|
+ // else: we just need to turn on part of the flexible
|
|
|
+ // energy available
|
|
|
+ else {
|
|
|
+ float energyNeeded = -energySurplus;
|
|
|
+ int i = 0;
|
|
|
+ energySurplus += energyNeeded; // should give 0, but
|
|
|
+ // was kept this was
|
|
|
+ // for consistency
|
|
|
+ // the energy needed divided through the amount of
|
|
|
+ // elements
|
|
|
+ holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
|
|
|
+ flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (energySurplus == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (energySurplus == 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set Flow Simulation.
|
|
|
+ *
|
|
|
+ * @param sN
|
|
|
+ * Subnet
|
|
|
+ */
|
|
|
+ private void setFlowSimulation(SubNet sN) {
|
|
|
+ ArrayList<AbstractCpsObject> producers = new ArrayList<>();
|
|
|
+ AbstractCpsObject tmp = null;
|
|
|
+ tagTable = new HashMap<>();
|
|
|
+ // traverse all objects in this subnet
|
|
|
+ for (HolonObject hl : sN.getObjects()) {
|
|
|
+ float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
|
|
|
+ // if their production is higher than their consumption
|
|
|
+ if (energy > 0) {
|
|
|
+ tagTable.put(hl.getId(), energy);
|
|
|
+ hl.addTag(hl.getId());
|
|
|
+ for (CpsEdge edge : hl.getConnections()) {
|
|
|
+ if (edge.isWorking()) {
|
|
|
+ // set other end of edge as tmp-object
|
|
|
+ // and add this end to the other end's tag-list
|
|
|
+ AbstractCpsObject a = edge.getA();
|
|
|
+ AbstractCpsObject b = edge.getB();
|
|
|
+ if (a.getId() == hl.getId()) {
|
|
|
+ b.addTag(hl.getId());
|
|
|
+ tmp = b;
|
|
|
+ }
|
|
|
+ if (b.getId() == hl.getId()) {
|
|
|
+ a.addTag(hl.getId());
|
|
|
+ tmp = a;
|
|
|
+ }
|
|
|
+
|
|
|
+ edge.setFlow(edge.getFlow() + energy);
|
|
|
+ edge.calculateState();
|
|
|
+ edge.addTag(hl.getId());
|
|
|
+ if (edge.isWorking() && !producers.contains(tmp)) {
|
|
|
+ if (tmp instanceof HolonSwitch) {
|
|
|
+ if (((HolonSwitch) tmp).getState(timeStep)) {
|
|
|
+ producers.add(tmp);
|
|
|
+ }
|
|
|
+ } else if (!(tmp instanceof CpsUpperNode)) {
|
|
|
+ producers.add(tmp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setFlowSimRec(producers, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set Flow Simulation Rec.
|
|
|
+ *
|
|
|
+ * @param nodes
|
|
|
+ * the nodes
|
|
|
+ * @param iter
|
|
|
+ * the Iteration
|
|
|
+ */
|
|
|
+ private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
|
|
|
+ ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
|
|
|
+ ArrayList<CpsEdge> changedEdges = new ArrayList<>();
|
|
|
+ AbstractCpsObject tmp;
|
|
|
+ if (nodes.size() != 0) {
|
|
|
+ for (AbstractCpsObject cps : nodes) {
|
|
|
+ // check whether the cps is in a legit state if it is a switch
|
|
|
+ if (legitState(cps)) {
|
|
|
+ for (CpsEdge edge : cps.getConnections()) {
|
|
|
+ // is edge working
|
|
|
+ // and does the edge's tag-list not (yet) contain all
|
|
|
+ // tags of the cps
|
|
|
+ if (edge.isWorking() && (!(edge.containsTags(edge.getTags(), cps.getTag())))) {
|
|
|
+ if (edge.getA().getId() == cps.getId()) {
|
|
|
+ tmp = edge.getB();
|
|
|
+ } else {
|
|
|
+ tmp = edge.getA();
|
|
|
+ }
|
|
|
+ for (Integer tag : cps.getTag()) {
|
|
|
+ if (!(edge.getTags().contains(tag)) && !(edge.getPseudoTags().contains(tag))) {
|
|
|
+ edge.setFlow(edge.getFlow() + tagTable.get(tag));
|
|
|
+ edge.addTag(tag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // uppernodes do not spread energy
|
|
|
+ if (!(tmp instanceof CpsUpperNode)) {
|
|
|
+ for (Integer tag : tmp.getTag()) {
|
|
|
+ if (!(edge.getTags().contains(tag)) && tagTable.get(tag) != null
|
|
|
+ && !(edge.getPseudoTags().contains(tag))) {
|
|
|
+ edge.setFlow(edge.getFlow() + tagTable.get(tag));
|
|
|
+ edge.addPseudoTag(tag);
|
|
|
+ changedEdges.add(edge);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ edge.calculateState();
|
|
|
+ if (edge.isWorking() && !(tmp instanceof CpsUpperNode)) {
|
|
|
+ tmp.addAllPseudoTags(cps.getTag());
|
|
|
+ if (!newNodes.contains(tmp)) {
|
|
|
+ newNodes.add(tmp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setPseudoTags(newNodes, changedEdges);
|
|
|
+ setFlowSimRec(newNodes, iter + 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set the Pseudo Tags.
|
|
|
+ *
|
|
|
+ * @param nodes
|
|
|
+ * Array of AbstractCpsObjects
|
|
|
+ */
|
|
|
+ private void setPseudoTags(ArrayList<AbstractCpsObject> nodes, ArrayList<CpsEdge> edges) {
|
|
|
+ for (AbstractCpsObject node : nodes) {
|
|
|
+ node.recalculateTags();
|
|
|
+ node.setPseudoTags(new ArrayList<>());
|
|
|
+ }
|
|
|
+ for (CpsEdge edge : edges) {
|
|
|
+ edge.recalculateTags();
|
|
|
+ edge.setPseudoTag(new ArrayList<>());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reset the Connection.
|
|
|
+ *
|
|
|
+ * @param cps
|
|
|
+ * CpsObject
|
|
|
+ * @param visitedObj
|
|
|
+ * the visited Objects
|
|
|
+ * @param visitedEdges
|
|
|
+ * the visited Edges
|
|
|
+ */
|
|
|
+ private void resetConnections(AbstractCpsObject cps, ArrayList<Integer> visitedObj,
|
|
|
+ ArrayList<CpsEdge> visitedEdges) {
|
|
|
+ visitedObj.add(cps.getId());
|
|
|
+ cps.resetTags();
|
|
|
+ for (CpsEdge e : cps.getConnections()) {
|
|
|
+ if (!(visitedEdges.contains(e))) {
|
|
|
+ e.setFlow(0);
|
|
|
+ e.calculateState();
|
|
|
+ e.setTags(new ArrayList<>());
|
|
|
+ visitedEdges.add(e);
|
|
|
+ if (!(visitedObj.contains(e.getA().getId()))) {
|
|
|
+ resetConnections(e.getA(), visitedObj, visitedEdges);
|
|
|
+ e.getA().resetTags();
|
|
|
+ }
|
|
|
+ if (!(visitedObj.contains(e.getB().getId()))) {
|
|
|
+ resetConnections(e.getB(), visitedObj, visitedEdges);
|
|
|
+ e.getB().resetTags();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * calculates the energy of either all producers or consumers. Flexible devices
|
|
|
+ * are filtered out
|
|
|
+ *
|
|
|
+ * @param type
|
|
|
+ * Type
|
|
|
+ * @param sN
|
|
|
+ * Subnet
|
|
|
+ * @param x
|
|
|
+ * Integer
|
|
|
+ * @return The Energy
|
|
|
+ */
|
|
|
+ private float calculateEnergyWithoutFlexDevices(String type, SubNet sN, int x) {
|
|
|
+ float energy = 0;
|
|
|
+ for (HolonObject hl : sN.getObjects()) {
|
|
|
+ float currentEnergyWithoutFlexibles = hl.getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
|
|
|
+
|
|
|
+ if (type.equals("prod")) {
|
|
|
+ if (currentEnergyWithoutFlexibles > 0) {
|
|
|
+ energy += currentEnergyWithoutFlexibles;
|
|
|
+ hl.setState(HolonObject.PRODUCER);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type.equals("cons")) {
|
|
|
+ if (currentEnergyWithoutFlexibles < 0) {
|
|
|
+ energy += currentEnergyWithoutFlexibles;
|
|
|
+ hl.setState(HolonObject.NOT_SUPPLIED);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (currentEnergyWithoutFlexibles == 0) {
|
|
|
+ hl.setState(HolonObject.NO_ENERGY);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return energy;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * calculates the energy of either all producers or consumers. Flexible devices
|
|
|
+ * are filtered out
|
|
|
+ *
|
|
|
+ * @param type
|
|
|
+ * Type
|
|
|
+ * @param sN
|
|
|
+ * Subnet
|
|
|
+ * @param x
|
|
|
+ * Integer
|
|
|
+ * @return The Energy
|
|
|
+ */
|
|
|
+ private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
|
|
|
+ float energy = 0;
|
|
|
+ for (HolonObject hl : sN.getObjects()) {
|
|
|
+ float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
|
|
|
+
|
|
|
+ if (type.equals("prod")) {
|
|
|
+ if (currentEnergy > 0) {
|
|
|
+ energy += currentEnergy;
|
|
|
+ hl.setState(HolonObject.PRODUCER);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type.equals("cons")) {
|
|
|
+ if (currentEnergy < 0) {
|
|
|
+ energy = energy + currentEnergy;
|
|
|
+ hl.setState(HolonObject.NOT_SUPPLIED);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (currentEnergy == 0) {
|
|
|
+ hl.setState(HolonObject.NO_ENERGY);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return energy;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * generates all subNets from all objectsToHandle.
|
|
|
+ */
|
|
|
+ private void searchForSubNets() {
|
|
|
+ subNets = new ArrayList<>();
|
|
|
+ brokenEdges.clear();
|
|
|
+ boolean end = false;
|
|
|
+ int i = 0;
|
|
|
+ AbstractCpsObject cps;
|
|
|
+ if (objectsToHandle.size() > 0) {
|
|
|
+ while (!end) {
|
|
|
+ cps = objectsToHandle.get(i);
|
|
|
+ //SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),
|
|
|
+ // new ArrayList<>());
|
|
|
+ SubNet singleSubNet = buildSubNet(cps, new ArrayList<>());
|
|
|
+ if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0) {
|
|
|
+ subNets.add(singleSubNet);
|
|
|
+ }
|
|
|
+ if (0 == objectsToHandle.size()) {
|
|
|
+ end = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * recursivly generates a subnet of all objects, that one specific object is
|
|
|
+ * connected to.
|
|
|
+ *
|
|
|
+ * @param cps
|
|
|
+ * AbstractCpsObject
|
|
|
+ * @param visited
|
|
|
+ * visited Array of Integer
|
|
|
+ * @param sN
|
|
|
+ * Subnets
|
|
|
+ * @return Subnet
|
|
|
+ */
|
|
|
+ private SubNet buildSubNet(AbstractCpsObject cps, ArrayList<Integer> visited) {
|
|
|
+ SubNet sN = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
|
|
|
+
|
|
|
+ visited.add(cps.getId());
|
|
|
+ if (cps instanceof HolonObject) {
|
|
|
+ sN.getObjects().add((HolonObject) cps);
|
|
|
+ }
|
|
|
+ if (cps instanceof HolonSwitch) {
|
|
|
+ sN.getSwitches().add((HolonSwitch) cps);
|
|
|
+ }
|
|
|
+ if (cps instanceof HolonBattery) {
|
|
|
+ sN.getBatteries().add((HolonBattery) cps);
|
|
|
+ }
|
|
|
+ removeFromToHandle(cps.getId());
|
|
|
+ AbstractCpsObject a;
|
|
|
+ AbstractCpsObject b;
|
|
|
+ for (CpsEdge edge : cps.getConnections()) {
|
|
|
+ if (edge.isWorking()) {
|
|
|
+ a = edge.getA();
|
|
|
+ b = edge.getB();
|
|
|
+ if (!(cps instanceof HolonSwitch)) {
|
|
|
+ if (!(sN.getEdges().contains(edge))) {
|
|
|
+ sN.getEdges().add(edge);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) {
|
|
|
+ if (!(sN.getEdges().contains(edge))) {
|
|
|
+ sN.getEdges().add(edge);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) {
|
|
|
+ sN = buildSubNet(a, visited);
|
|
|
+ }
|
|
|
+ if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) {
|
|
|
+ sN = buildSubNet(b, visited);
|
|
|
+ }
|
|
|
+ if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
|
|
|
+ edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
|
|
|
+ checkForConnectedStates(b, (CpsUpperNode) a, edge);
|
|
|
+ }
|
|
|
+ if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
|
|
|
+ edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
|
|
|
+ checkForConnectedStates(a, (CpsUpperNode) b, edge);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ brokenEdges.add(edge);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return sN;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * is the Switch in a legitimate State.
|
|
|
+ *
|
|
|
+ * @param current
|
|
|
+ * AbstractCpsObject
|
|
|
+ * @return boolean
|
|
|
+ */
|
|
|
+ private boolean legitState(AbstractCpsObject current) {
|
|
|
+ return !(current instanceof HolonSwitch) || ((HolonSwitch) current).getState(timeStep);
|
|
|
+ }
|
|
|
+
|
|
|
+ // /**
|
|
|
+ // * ensures that objectsToHandle only contains HolonObjects.
|
|
|
+ // */
|
|
|
+ // public void cleanObjectsToHandle() {
|
|
|
+ // for (int i = 0; i < objectsToHandle.size(); i++) {
|
|
|
+ // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
|
|
|
+ // objectsToHandle.remove(i);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * removes an Object that already has been handled.
|
|
|
+ *
|
|
|
+ * @param id
|
|
|
+ * the Object ID
|
|
|
+ */
|
|
|
+ private void removeFromToHandle(int id) {
|
|
|
+ for (int i = 0; i < objectsToHandle.size(); i++) {
|
|
|
+ if (objectsToHandle.get(i).getId() == id) {
|
|
|
+ objectsToHandle.remove(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * copies the data of an array of Objects.
|
|
|
+ *
|
|
|
+ * @param toCopy
|
|
|
+ * the ArrayList of CpsObjects co Copy
|
|
|
+ */
|
|
|
+ private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
|
|
|
+ for (AbstractCpsObject cps : toCopy) {
|
|
|
+ if (cps instanceof CpsUpperNode) {
|
|
|
+ copyObjects(((CpsUpperNode) cps).getNodes());
|
|
|
+ } else {
|
|
|
+ objectsToHandle.add(cps);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Reset all Data to the current state of the Model.
|
|
|
+ */
|
|
|
+ public void reset() {
|
|
|
+ objectsToHandle = new ArrayList<>();
|
|
|
+ copyObjects(model.getObjectsOnCanvas());
|
|
|
+ flexDevicesTurnedOnThisTurn = new HashMap<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Resets the State of all Edges
|
|
|
+ */
|
|
|
+ private void resetEdges() {
|
|
|
+ for (CpsEdge e : brokenEdges) {
|
|
|
+ e.setWorkingState(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Resets the State for the whole Simulation Model
|
|
|
+ */
|
|
|
+ void resetSimulation() {
|
|
|
+ reset();
|
|
|
+ resetEdges();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get all Subnets.
|
|
|
+ *
|
|
|
+ * @return all Subnets
|
|
|
+ */
|
|
|
+ public ArrayList<SubNet> getSubNets() {
|
|
|
+ return subNets;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get broken Edges
|
|
|
+ */
|
|
|
+ // public ArrayList<CpsEdge> getBrokenEdges() {
|
|
|
+ // return brokenEdges;
|
|
|
+ // }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * checks whether a given object is connected to an object inside the upperNode.
|
|
|
+ * if yes, the state for the edge is changed in "connected" or "not connected"
|
|
|
+ */
|
|
|
+ private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) {
|
|
|
+ AbstractCpsObject tmp;
|
|
|
+ for (CpsEdge edge : cps.getConnections()) {
|
|
|
+ if (edge.getA().getId() == cps.getId()) {
|
|
|
+ tmp = edge.getB();
|
|
|
+ } else {
|
|
|
+ tmp = edge.getA();
|
|
|
+ }
|
|
|
+ if (cUNode.getNodes().contains(tmp)) {
|
|
|
+ if (tmp instanceof CpsUpperNode) {
|
|
|
+ checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
|
|
|
+ } else {
|
|
|
+ theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|