package holeg.model; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; public class Holon { private static final Logger log = Logger.getLogger(Holon.class.getName()); public Set holonObjects = new HashSet<>(); public Set objects = new HashSet<>(); public Set edges = new HashSet<>(); public Holon(HolonObject holonObject) { holonObjects.add(holonObject); objects.add(holonObject); } public Holon(Edge edge) { add(edge); } public void add(Edge edge) { add(edge.getA()); add(edge.getB()); edges.add(edge); } public void add(AbstractCanvasObject obj) { if (obj instanceof HolonObject holonObject) { holonObjects.add(holonObject); } objects.add(obj); } public void clear() { holonObjects.clear(); edges.clear(); objects.clear(); } @Override public String toString() { return "[" + objects.stream().map(AbstractCanvasObject::getName) .collect(Collectors.joining(", ")) + "]"; } public void calculate() { Map> partition = holonObjects.stream() .collect(Collectors.partitioningBy(hO -> hO.getActualEnergy() > 0)); List supplierList = partition.get(true); List consumerList = partition.get(false); supplierList.sort((a, b) -> -Float.compare(a.getActualEnergy(), b.getActualEnergy())); float energyToSupplyInTheNetwork = supplierList.stream() .map(HolonObject::getActualEnergy) .reduce(0f, Float::sum); // STEP 1: // Supply consuming element first // Sort ConsumerList according to the MinimumConsumingElementEnergy minimum first. consumerList.sort((a, b) -> Float.compare(a.getMinimumConsumingElementEnergy(), b.getMinimumConsumingElementEnergy())); outerLoop: for (HolonObject con : consumerList) { for (HolonObject sup : supplierList) { float energyRdyToSupply = sup.getActualEnergy() - sup.getEnergyToHolon(); if (energyRdyToSupply <= 0.0f) { continue; } float energyNeededForMinimumConsumingElement = con.getMinimumConsumingElementEnergy() - con.getEnergyFromHolon(); if (energyNeededForMinimumConsumingElement > energyToSupplyInTheNetwork) { // Dont supply a minimumElement when you cant supply it fully break outerLoop; } if (energyRdyToSupply >= energyNeededForMinimumConsumingElement) { energyToSupplyInTheNetwork -= energyNeededForMinimumConsumingElement; supply(con, sup, energyNeededForMinimumConsumingElement); continue outerLoop; } else { energyToSupplyInTheNetwork -= energyRdyToSupply; supply(con, sup, energyRdyToSupply); } } // No more Energy in the network break; } // STEP 2: // Supply consumer fully // Sort ConsumerList according to the EnergyNeeded to supply fully after minimum // Demand First. consumerList.sort((l, r) -> Float.compare( l.getEnergyNeededFromHolon() - l.getEnergyFromHolon(), r.getEnergyNeededFromHolon() - r.getEnergyFromHolon())); outerLoop: for (HolonObject con : consumerList) { for (HolonObject sup : supplierList) { float energyRdyToSupply = sup.getActualEnergy() - sup.getEnergyToHolon(); if (energyRdyToSupply <= 0.0f) { continue; } float energyNeededForFullySupply = con.getEnergyNeededFromHolon() - con.getEnergyFromHolon(); if (energyNeededForFullySupply <= 0.0f) { continue outerLoop; } if (energyRdyToSupply >= energyNeededForFullySupply) { energyToSupplyInTheNetwork -= energyNeededForFullySupply; supply(con, sup, energyNeededForFullySupply); continue outerLoop; } else { energyToSupplyInTheNetwork -= energyRdyToSupply; supply(con, sup, energyRdyToSupply); } } // No more Energy in the network break; } // STEP 3: // If energy is still left, oversupply if (energyToSupplyInTheNetwork > 0.0f && (consumerList.size() != 0)) { float equalAmountOfEnergyToSupply = energyToSupplyInTheNetwork / ((float) (consumerList.size())); outerLoop: for (HolonObject con : consumerList) { for (HolonObject sup : supplierList) { float energyRdyToSupply = sup.getActualEnergy() - sup.getEnergyToHolon(); if (energyRdyToSupply <= 0.0f) { continue; } float energyNeededToSupplyConsumerTheEqualAmount = equalAmountOfEnergyToSupply + con.getEnergyNeededFromHolon() - con.getEnergyFromHolon(); if (energyRdyToSupply >= energyNeededToSupplyConsumerTheEqualAmount) { supply(con, sup, energyNeededToSupplyConsumerTheEqualAmount); continue outerLoop; } else { supply(con, sup, energyRdyToSupply); } } // No more Energy in the network break; } } holonObjects.forEach(HolonObject::calculateState); } private void supply(HolonObject consumer, HolonObject supplier, float energy) { consumer.setEnergyFromHolon(consumer.getEnergyFromHolon() + energy); supplier.setEnergyToHolon(supplier.getEnergyToHolon() + energy); } public Stream getListOfEnergyThatIsOfferedByFlexibilitiesInThisNetwork() { return holonObjects.stream().flatMap(HolonObject::elementsStream) .filter(ele -> (ele.flexList.stream().anyMatch(flex -> flex.offered))) .map(ele -> -ele.getActualEnergy()); } public Stream getListOfEnergyInProductionThatIsOfferedByFlexibilitiesInThisNetwork() { return getListOfEnergyThatIsOfferedByFlexibilitiesInThisNetwork().filter( value -> (value > 0.f)); } public Stream getListOfEnergyInConsumptionThatIsOfferedByFlexibilitiesInThisNetwork() { return getListOfEnergyThatIsOfferedByFlexibilitiesInThisNetwork().filter(value -> (value < 0.f)) .map(value -> -value); } public float getFlexibilityProductionCapacity() { return getListOfEnergyInProductionThatIsOfferedByFlexibilitiesInThisNetwork().reduce(0.f, Float::sum); } public float getFlexibilityConsumptionCapacity() { return getListOfEnergyInConsumptionThatIsOfferedByFlexibilitiesInThisNetwork().reduce(0.f, Float::sum); } public int getAmountOfProductionFlexibilities() { return (int) getListOfEnergyInProductionThatIsOfferedByFlexibilitiesInThisNetwork().count(); } public int getAmountOfConsumptionFlexibilities() { return (int) getListOfEnergyInConsumptionThatIsOfferedByFlexibilitiesInThisNetwork().count(); } public float getAverageFlexibilityProduction() { int amount = getAmountOfProductionFlexibilities(); return (amount > 0) ? getFlexibilityProductionCapacity() / (float) amount : 0.f; } public float getAverageFlexibilityConsumption() { int amount = getAmountOfConsumptionFlexibilities(); return (amount > 0) ? getFlexibilityConsumptionCapacity() / (float) amount : 0.f; } public float getVarianceInFlexibilitiesConsumption() { float average = getAverageFlexibilityConsumption(); float sum = getListOfEnergyInConsumptionThatIsOfferedByFlexibilitiesInThisNetwork() .map(energy -> squared(energy - average)).reduce(0.f, Float::sum); int amountOfFlexibilities = getAmountOfConsumptionFlexibilities(); return (amountOfFlexibilities > 0) ? sum / (float) amountOfFlexibilities : 0.f; } public float getVarianceInFlexibilityProduction() { float average = getAverageFlexibilityProduction(); float sum = getListOfEnergyInProductionThatIsOfferedByFlexibilitiesInThisNetwork() .map(energy -> squared(energy - average)).reduce(0.f, Float::sum); int amountOfFlexibilities = getAmountOfProductionFlexibilities(); return (amountOfFlexibilities > 0) ? sum / (float) amountOfFlexibilities : 0.f; } public float getDeviationInFlexibilityConsumption() { return (float) Math.sqrt(getVarianceInFlexibilitiesConsumption()); } public float getDeviationInFlexibilityProduction() { return (float) Math.sqrt(getVarianceInFlexibilityProduction()); } public float getTotalConsumption() { return holonObjects.stream().map(HolonObject::getConsumption).reduce(0.f, Float::sum); } public float getAverageConsumptionInNetworkForHolonObject() { return getTotalConsumption() / (float) holonObjects.size(); } public float getTotalProduction() { return holonObjects.stream().map(HolonObject::getProduction).reduce(0.f, Float::sum); } public float getAverageProductionInNetworkForHolonObject() { return getTotalProduction() / (float) holonObjects.size(); } /** * returns the Varianz in Poduction */ public float getVarianceInProductionInNetworkForHolonObjects() { float average = getAverageProductionInNetworkForHolonObject(); float sum = holonObjects.stream().map(hO -> squared(hO.getProduction() - average)) .reduce(0.f, Float::sum); return sum / (float) holonObjects.size(); } public float getDeviationInProductionInNetworkForHolonObjects() { return (float) Math.sqrt(getVarianceInProductionInNetworkForHolonObjects()); } public float getVarianceInConsumptionInNetworkForHolonObjects() { float average = getAverageConsumptionInNetworkForHolonObject(); float sum = holonObjects.stream().map(hO -> squared(hO.getConsumption() - average)) .reduce(0.f, Float::sum); return sum / (float) holonObjects.size(); } public float getDeviationInConsumptionInNetworkForHolonObjects() { return (float) Math.sqrt(getVarianceInConsumptionInNetworkForHolonObjects()); } // Help Function private float squared(float input) { return input * input; } public int getAmountOfElements() { return (int) holonObjects.stream().flatMap(HolonObject::elementsStream).count(); } }