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; 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 merge(Holon other) { holonObjects.addAll(other.holonObjects); edges.addAll(other.edges); objects.addAll(other.objects); other.clear(); } 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(int timeStep) { Map> partition = holonObjects.stream().collect(Collectors.partitioningBy(hO -> hO.getActualEnergy() > 0)); List supplierList = partition.get(true); List consumerList = partition.get(false); // log.info("Supplier [" + supplierList.stream().map(AbstractCanvasObject::getName).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() + // "Consumer [" + consumerList.stream().map(AbstractCanvasObject::getName).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() // ); // Sort SupplierList according to the EnergyToSupplyNetwork maximum first. supplierList.sort((a, b) -> -Float.compare(a.getActualEnergy(), b.getActualEnergy())); log.info("Supplier [" + supplierList.stream().map(hO -> hO.getName() + hO.getActualEnergy()).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() + "Consumer [" + consumerList.stream().map(hO -> hO.getName() + hO.getMinimumConsumingElementEnergy()).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() ); 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; } log.info("Supplier [" + supplierList.stream().map(hO -> hO.getName() + hO.getActualEnergy()).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() + "Consumer [" + consumerList.stream().map(hO -> hO.getName() + hO.getActualEnergy()).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() ); // 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; } log.info("energyToSupplyInTheNetwork: " + energyToSupplyInTheNetwork); 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); } }