workcraft/workcraft

View on GitHub
workcraft/SonPlugin/src/org/workcraft/plugins/son/algorithm/ErrorTracingAlg.java

Summary

Maintainability
D
3 days
Test Coverage
package org.workcraft.plugins.son.algorithm;

import org.workcraft.dom.Node;
import org.workcraft.dom.math.MathNode;
import org.workcraft.plugins.son.SON;
import org.workcraft.plugins.son.connections.SONConnection.Semantics;
import org.workcraft.plugins.son.elements.ChannelPlace;
import org.workcraft.plugins.son.elements.Condition;
import org.workcraft.plugins.son.elements.PlaceNode;
import org.workcraft.plugins.son.elements.TransitionNode;
import org.workcraft.plugins.son.util.Phase;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

public class ErrorTracingAlg extends SimulationAlg {

    private final SON net;
    private final BSONAlg bsonAlg;

    public ErrorTracingAlg(SON net) {
        super(net);
        bsonAlg = new BSONAlg(net);
        this.net = net;
    }

    //Forward error tracing
    public void setErrNum(Collection<TransitionNode> fireList, Collection<Path> sync, Map<Condition, Collection<Phase>> phases, boolean isLower) {

        while (!fireList.isEmpty()) {
            Collection<TransitionNode> removeList = new ArrayList<>();

            for (TransitionNode e : fireList) {
                if (!net.getSONConnectionTypes((MathNode) e).contains(Semantics.SYNCLINE)) {
                    //set number from the very first asynchronous event
                    if (getPreAsynEvents(e).isEmpty() || !hasCommonElements(fireList, getPreAsynEvents(e))) {
                        setAsynErrNum(e, phases, isLower);
                        fireList.remove(e);
                        break;
                    }
                }

                //set number for the synchronous events with no pre-async-events
                boolean b = false;
                for (Path cycle : sync) {
                    if (cycle.contains(e)) {
                        Collection<TransitionNode> fireList2 = new ArrayList<>();
                        Collection<TransitionNode> eventCycle = new ArrayList<>();

                        fireList2.addAll(fireList);
                        fireList2.removeAll(cycle);
                        boolean hasPreAsyn = false;
                        for (Node n: cycle) {
                            if (n instanceof TransitionNode) {
                                eventCycle.add((TransitionNode) n);
                                if (!getPreAsynEvents((TransitionNode) n).isEmpty()
                                        && hasCommonElements(fireList2, getPreAsynEvents((TransitionNode) n))) {
                                    hasPreAsyn = true;
                                }
                            }
                        }
                        if (!hasPreAsyn) {
                            setSyncErrNum(eventCycle, phases, isLower);
                            removeList.addAll(eventCycle);
                            b = true;
                            break;
                        }
                    }
                }
                if (b) {
                    break;
                }
            }
            fireList.removeAll(removeList);
        }
    }

    private boolean hasCommonElements(Collection<TransitionNode> cycle1, Collection<TransitionNode> cycle2) {
        for (Node n : cycle1) {
            if (cycle2.contains(n)) {
                return true;
            }
        }
        for (Node n : cycle2) {
            if (cycle1.contains(n)) {
                return true;
            }
        }
        return false;
    }

    private void setAsynErrNum(TransitionNode e, Map<Condition, Collection<Phase>> phases, boolean isLower) {
        int err = 0;
        if (e.isFaulty()) {
            err++;
        }
        //get err number from lower conditions and channel places
        for (MathNode pre : net.getPreset((MathNode) e)) {
            if (pre instanceof PlaceNode) {
                err += ((PlaceNode) pre).getErrors();
            }
        }

        for (MathNode post: net.getPostset((MathNode) e)) {
            if (post instanceof Condition) {
                ((Condition) post).setErrors(err);
                //set err number for lower condition
                if (!isLower) {
                    for (Condition min : bsonAlg.getMinimalPhase(getActivatedPhases(phases.get(post)))) {
                        min.setErrors(min.getErrors() + ((Condition) post).getErrors());
                    }
                }
            }
            if (post instanceof ChannelPlace) {
                ((ChannelPlace) post).setErrors(err);
            }
        }
    }

    private void setSyncErrNum(Collection<TransitionNode> sync, Map<Condition, Collection<Phase>> phases, boolean isLower) {
        int err = 0;

        for (TransitionNode e : sync) {
            if (e.isFaulty()) {
                err++;
            }
            for (MathNode pre : net.getPreset((MathNode) e)) {
                if (pre instanceof Condition) {
                    err += ((Condition) pre).getErrors();
                }
                if (pre instanceof ChannelPlace) {
                    for (Node n : net.getPreset(pre)) {
                        if (!sync.contains(n)) {
                            err += ((ChannelPlace) pre).getErrors();
                        }
                    }
                }
            }
        }

        for (TransitionNode e : sync) {
            for (MathNode post: net.getPostset((MathNode) e)) {
                if (post instanceof Condition) {
                    ((Condition) post).setErrors(err);
                    //set err number for upper conditions
                    if (!isLower) {
                        for (Condition min : bsonAlg.getMinimalPhase(getActivatedPhases(phases.get(post)))) {
                            min.setErrors(min.getErrors() + ((Condition) post).getErrors());
                        }
                    }
                }

                if (post instanceof ChannelPlace) {
                    for (MathNode n : net.getPostset(post)) {
                        if (!sync.contains(n)) {
                            ((ChannelPlace) post).setErrors(err);
                        }
                    }
                }
            }
        }
    }

    //Backward error tracing
    public void setRevErrNum(Collection<TransitionNode> fireList, Collection<Path> sync, Map<Condition, Collection<Phase>> phases, boolean isLower) {

        while (!fireList.isEmpty()) {
            Collection<TransitionNode> removeList = new ArrayList<>();

            for (TransitionNode e : fireList) {
                if (!net.getSONConnectionTypes((MathNode) e).contains(Semantics.SYNCLINE)) {
                    //set number from the very first asynchronous event
                    if (getPostAsynEvents(e).isEmpty() || !hasCommonElements(fireList, getPostAsynEvents(e))) {
                        setRevAsynErrNum(e, phases, isLower);
                        fireList.remove(e);
                        break;
                    }
                }

                //set number for the synchronous events with no pre-async-events
                boolean b = false;
                for (Path cycle : sync) {
                    if (cycle.contains(e)) {
                        Collection<TransitionNode> fireList2 = new ArrayList<>();
                        Collection<TransitionNode> eventCycle = new ArrayList<>();

                        fireList2.addAll(fireList);
                        fireList2.removeAll(cycle);
                        boolean hasPostAsyn = false;
                        for (Node n: cycle) {
                            if (n instanceof TransitionNode) {
                                eventCycle.add((TransitionNode) n);
                                if (!getPostAsynEvents((TransitionNode) n).isEmpty()
                                        && hasCommonElements(fireList2, getPostAsynEvents((TransitionNode) n))) {
                                    hasPostAsyn = true;
                                }
                            }
                        }
                        if (!hasPostAsyn) {
                            setRevSyncErrNum(eventCycle, phases, isLower);
                            removeList.addAll(eventCycle);
                            b = true;
                            break;
                        }
                    }
                }
                if (b) {
                    break;
                }
            }
            fireList.removeAll(removeList);
        }
    }

    private void setRevAsynErrNum(TransitionNode e, Map<Condition, Collection<Phase>> phases, boolean isLower) {
        int err = 0;
        if (e.isFaulty()) {
            err++;
        }
        //get err number from lower conditions and channel places
        for (MathNode pre : net.getPreset((MathNode) e)) {
            if (pre instanceof PlaceNode) {
                err += ((PlaceNode) pre).getErrors();
            }
        }

        for (MathNode post: net.getPostset((MathNode) e)) {
            if (post instanceof Condition) {
                ((Condition) post).setErrors(err);
                //set err number for lower condition
                if (!isLower) {
                    for (Condition min : bsonAlg.getMinimalPhase(getActivatedPhases(phases.get(post)))) {
                        min.setErrors(min.getErrors() - ((Condition) post).getErrors());
                    }
                }
                ((Condition) post).setErrors(((Condition) post).getErrors() - err);
            }
            if (post instanceof ChannelPlace) {
                ((ChannelPlace) post).setErrors(((ChannelPlace) post).getErrors() - err);
            }
        }
    }

    private void setRevSyncErrNum(Collection<TransitionNode> sync, Map<Condition, Collection<Phase>> phases, boolean isLower) {
        int err = 0;

        for (TransitionNode e : sync) {
            if (e.isFaulty()) {
                err++;
            }
            for (MathNode pre : net.getPreset((MathNode) e)) {
                if (pre instanceof Condition) {
                    err += ((Condition) pre).getErrors();
                }
                if (pre instanceof ChannelPlace) {
                    for (MathNode n : net.getPreset(pre)) {
                        if (!sync.contains(n)) {
                            err += ((ChannelPlace) pre).getErrors();
                        }
                    }
                }
            }
        }

        for (TransitionNode e : sync) {
            for (MathNode post: net.getPostset((MathNode) e)) {
                if (post instanceof Condition) {
                    ((Condition) post).setErrors(err);
                    //set err number for upper conditions
                    if (!isLower) {
                        for (Condition min : bsonAlg.getMinimalPhase(getActivatedPhases(phases.get(post)))) {
                            min.setErrors(min.getErrors() - ((Condition) post).getErrors());
                        }
                    }
                    ((Condition) post).setErrors(((Condition) post).getErrors() - err);
                }

                if (post instanceof ChannelPlace) {
                    for (MathNode n : net.getPostset(post)) {
                        if (!sync.contains(n)) {
                            ((ChannelPlace) post).setErrors(((ChannelPlace) post).getErrors() - err);
                        }
                    }
                }
            }
        }
    }

}