All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.happy3w.math.graph.ScIterator Maven / Gradle / Ivy

There is a newer version: 1.0.13
Show newest version
package com.happy3w.math.graph;

import com.happy3w.java.ext.NeedFindIterator;
import com.happy3w.java.ext.NullableOptional;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Stack;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ScIterator extends NeedFindIterator> {
    private final Map> nodesToDeal;

    private Stack> candidateCircles = new Stack<>();
    private Stack idPath = new Stack<>();

    public ScIterator(Map> nodes) {
        this.nodesToDeal = new HashMap<>(nodes);
    }

    @Override
    protected NullableOptional> findNext() {
        ScNode leafNode = findLeafNode();
        if (leafNode == null) {
            return NullableOptional.empty();
        } else {
            leafNode.idStream()
                    .forEach(nodesToDeal::remove);
            return NullableOptional.of(leafNode);
        }
    }

    private ScNode findLeafNode() {
        while (!nodesToDeal.isEmpty()) {
            SingleScNode curScNode;
            if (!idPath.isEmpty()) {
                NK lastId = idPath.pop();
                GraphNode graphNode = nodesToDeal.get(lastId);
                curScNode = SingleScNode.from(graphNode);
            } else if (!candidateCircles.isEmpty()) {
                CircleInfo curCircle = candidateCircles.pop();
                NK newStartNode = curCircle.nextNewStartNode();
                if (newStartNode == null) {
                    idPath.addAll(curCircle.getPathFromParent());
                    return new CombineScNode(idToNode(curCircle.getCircle(), nodesToDeal::get));
                }
                candidateCircles.push(curCircle);
                GraphNode graphNode = nodesToDeal.get(newStartNode);
                if (graphNode == null) {
                    continue;
                }
                curScNode = SingleScNode.from(graphNode);
            } else {
                GraphNode graphNode = nodesToDeal.values().iterator().next();
                curScNode = SingleScNode.from(graphNode);
            }

            NK curId = curScNode.getGraphNode().getId();
            CircleInfo curCircle = CircleInfo.createNewCircle(idPath, curId, nodesToDeal::get);
            if (curCircle != null) {
                idPath.clear();
                candidateCircles.push(curCircle);
            } else if (CircleInfo.mergeIntoBigCircle(idPath, curId, candidateCircles, nodesToDeal::get)) {
                idPath.clear();
            } else {
                SingleScNode outNode = pickAnyOutNode(curScNode.getGraphNode(), nodesToDeal::get);
                if (outNode == null) {
                    return curScNode;
                }

                idPath.push(curId);
                idPath.push(outNode.getGraphNode().getId());
            }
        }
        return null;
    }
    private SingleScNode pickAnyOutNode(GraphNode node,
                                                        Function> nodeMapper) {
        return node.outcomeStream()
                .map(edge -> nodeMapper.apply(edge.getTo()))
                .filter(Objects::nonNull)
                .map(SingleScNode::from)
                .findFirst()
                .orElse(null);
    }

    private List> idToNode(Collection ids,
                                                     Function> idNodeTranslator) {
        return ids.stream()
                .map(idNodeTranslator)
                .collect(Collectors.toList());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy