de.uni_potsdam.hpi.asg.logictool.srgraph.StateGraphComputer.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_potsdam.hpi.asg.logictool.srgraph.StateGraphComputer.java

Source

package de.uni_potsdam.hpi.asg.logictool.srgraph;

/*
 * Copyright (C) 2014 - 2016 Norman Kluge
 * 
 * This file is part of ASGlogic.
 * 
 * ASGlogic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ASGlogic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ASGlogic.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.io.File;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.google.common.collect.Sets;

import de.uni_potsdam.hpi.asg.common.iohelper.WorkingdirGenerator;
import de.uni_potsdam.hpi.asg.common.stg.GFile;
import de.uni_potsdam.hpi.asg.common.stg.model.STG;
import de.uni_potsdam.hpi.asg.common.stg.model.Signal;
import de.uni_potsdam.hpi.asg.common.stg.model.Transition;
import de.uni_potsdam.hpi.asg.common.stggraph.AbstractSTGGraphComputer;
import de.uni_potsdam.hpi.asg.common.stggraph.AbstractState.Value;
import de.uni_potsdam.hpi.asg.logictool.srgraph.csc.CSCSolver;

import gnu.trove.map.hash.THashMap;

public class StateGraphComputer extends AbstractSTGGraphComputer<State> {
    private static final Logger logger = LogManager.getLogger();

    private SortedSet<Signal> sortedSignals;
    private CSCSolver cscsolver;

    //tmp
    private Set<State> checkedStates;
    private List<State> alsoset;

    public StateGraphComputer(STG stg, SortedSet<Signal> sortedSignals, CSCSolver cscsolver) {
        super(State.class, stg);
        this.sortedSignals = new TreeSet<Signal>();
        for (Signal sig : sortedSignals) {
            if (!sig.isDummy()) {
                this.sortedSignals.add(sig);
            }
        }
        this.cscsolver = cscsolver;
    }

    public StateGraph compute() {
        if (!internalCompute(true)) {
            return null;
        }
        checkedStates = new HashSet<>();
        alsoset = new ArrayList<>();

        Set<State> states2 = new HashSet<State>();
        states2.addAll(states.values());

        if (!fillStates(states2)) {
            return null;
        }

        if (!checkCSC(states2)) {
            if (cscsolver != null) {
                String newfilename = stg.getFile().getName() + "_csc.g";
                File newFile = new File(WorkingdirGenerator.getInstance().getWorkingDir(), newfilename);
                if (cscsolver.solveCSC(stg, newFile)) {
                    STG newSTG = GFile.importFromFile(
                            new File(WorkingdirGenerator.getInstance().getWorkingDir(), newfilename));
                    StateGraphComputer newcomp = new StateGraphComputer(newSTG,
                            new TreeSet<Signal>(newSTG.getSignals()), null);
                    return newcomp.compute();
                } else {
                    logger.error("Failed to solve CSC");
                    return null;
                }
            } else {
                logger.error("CSC solving not activated");
                return null;
            }
        }
        logger.info("STG has CSC");

        if (!checkOutputDetermency(states2)) {
            return null;
        }
        //TODO: check contains dummy trans

        logger.info("Number of states: " + states2.size());

        clear();
        return new StateGraph(stg, init, states2, sortedSignals);
    }

    private boolean checkOutputDetermency(Set<State> states2) {
        boolean retVal = true;
        for (State s : states2) {
            for (Entry<Signal, Value> sv : s.getStateValues().entrySet()) {
                switch (sv.getValue()) {
                case falling:
                case rising:
                    if (sv.getKey().isInternalOrOutput()) {
                        for (Entry<Transition, State> arc : s.getNextStates().entrySet()) {
                            if (arc.getKey().getSignal() != sv.getKey()) {
                                if (arc.getValue().getStateValues().get(sv.getKey()) != sv.getValue()) {
                                    retVal = false;
                                    logger.error("Output " + sv.getKey().getName() + " disabled by "
                                            + arc.getKey().getSignal().getName());
                                }
                            }
                        }
                    }
                    break;
                case low:
                case high:
                    break;
                }
            }
        }
        if (!retVal) {
            logger.error("No output determency");
        }
        return retVal;
    }

    private boolean checkCSC(Set<State> states2) {
        Map<BitSet, State> checkList = new THashMap<BitSet, State>();
        HashMap<BitSet, Set<State>> equallyEncodedStates = new HashMap<BitSet, Set<State>>();
        BitSet binRep = null;
        State otherState = null;
        Value v1 = null, v2 = null;
        boolean csc;
        Signal problematicSignal = null;
        for (State state : states2) {
            binRep = state.getBinaryRepresentationNormalised(sortedSignals);
            if (checkList.containsKey(binRep)) {
                otherState = checkList.get(binRep);
                csc = true;
                for (Entry<Signal, Value> entry2 : otherState.getStateValues().entrySet()) {
                    if (entry2.getKey().isInternalOrOutput()) {
                        v1 = state.getStateValues().get(entry2.getKey());
                        v2 = entry2.getValue();
                        if (v1 != v2) {
                            csc = false;
                            problematicSignal = entry2.getKey();
                            break;
                        }
                    }
                }
                if (csc) {
                    if (!equallyEncodedStates.containsKey(binRep)) {
                        equallyEncodedStates.put(binRep, new HashSet<State>());
                    }
                    if (state.hashCode() == otherState.hashCode()) {
                        logger.fatal("Different state objects have same Hash");
                        System.exit(-1);
                    }
                    equallyEncodedStates.get(binRep).add(state);
                    equallyEncodedStates.get(binRep).add(otherState);
                } else {
                    logger.warn("STG has no CSC");
                    logger.debug("States: " + state.getId() + " and " + otherState.getId() + ", Signal: "
                            + problematicSignal.getName());
                    return false;
                }
            } else {
                checkList.put(binRep, state);
            }
        }

        //      System.out.println("Equally encoded states:");
        //      for(Entry<BitSet, Set<State>> e : equallyEncodedStates.entrySet()) {
        //         for(State s : e.getValue()) {
        //            System.out.print(s.getId() + ", ");
        //         }
        //         System.out.println();
        //      }

        //merge
        Transition t = null;
        State s1 = null, s2 = null;
        Iterator<State> it = null;
        boolean change = false;
        do {
            change = false;
            for (Entry<BitSet, Set<State>> entry : equallyEncodedStates.entrySet()) {
                for (Set<State> set : Sets.powerSet(entry.getValue())) {
                    if (set.size() == 2) {
                        it = set.iterator();
                        s1 = it.next();
                        s2 = it.next();
                        //only merge if nextstates are the same
                        boolean merge = true;
                        for (Entry<Transition, State> nextentry : s2.getNextStates().entrySet()) {
                            State repnext = null;
                            for (Entry<Transition, State> repnextentry : s1.getNextStates().entrySet()) {
                                if (repnextentry.getKey().getSignal() == nextentry.getKey().getSignal()) {
                                    repnext = repnextentry.getValue();
                                }
                            }
                            if (repnext == null || !repnext.equals(nextentry.getValue())) {
                                merge = false;
                                break;
                            }
                        }

                        if (merge) {
                            for (State prev : s2.getPrevStates()) {
                                t = null;
                                for (Entry<Transition, State> entry2 : prev.getNextStates().entrySet()) {
                                    if (entry2.getValue() == s2) {
                                        t = entry2.getKey();
                                        break;
                                    }
                                }
                                if (t == null) {
                                    logger.error("Transition in map not found (Missing edge?)");
                                    return false;
                                }
                                prev.addEdgeNextState(s1, t);
                            }
                            s2.getPrevStates().clear();
                            for (Entry<Transition, State> next : s2.getNextStates().entrySet()) {
                                if (!next.getValue().getPrevStates().contains(s1)) {
                                    if (s1.getNextStates().containsKey(next.getKey())) {
                                        next.getValue().getPrevStates().remove(s2);
                                    } else {
                                        s1.addEdgeNextState(next.getValue(), next.getKey());
                                    }
                                }
                                next.getValue().getPrevStates().remove(s2);
                            }
                            states2.remove(s2);
                            entry.getValue().remove(s2);
                            change = true;
                            break;
                        }
                    }
                }
            }
        } while (change);

        for (Entry<BitSet, Set<State>> e : equallyEncodedStates.entrySet()) {
            if (e.getValue().size() <= 1) {
                continue;
            }
            for (State s3 : e.getValue()) {
                for (State s4 : e.getValue()) {
                    if (s3 != s4) {
                        s3.addEquallyEncodedState(s4);
                    }
                }
            }
        }

        return true;
    }

    private boolean fillStates(Set<State> states) {

        int sigsize = 0;
        for (Signal sig : stg.getSignals()) {
            if (!sig.isDummy()) {
                sigsize++;
            }
        }

        for (State s : states) {
            if (sigsize > s.getStateValues().size()) {
                for (Signal sig : stg.getSignals()) {
                    if (!sig.isDummy()) {
                        if (!s.isSignalSet(sig)) {
                            checkstates.clear();
                            checkedStates.clear();
                            checkstates.addAll(s.getPrevStates());
                            alsoset.clear();
                            State s2 = null;
                            boolean isNowSet = false;
                            while (!checkstates.isEmpty()) {
                                s2 = checkstates.poll();
                                if (checkedStates.contains(s2)) {
                                    continue;
                                }
                                if (s2.isSignalSet(sig)) {
                                    Value val = s2.getStateValues().get(sig);
                                    switch (val) {
                                    case falling:
                                    case rising:
                                        logger.error("Not possible: State: " + s.toStringSimple() + ", Sig "
                                                + sig.getName() + ", OtherState: " + s2.toStringSimple() + ": "
                                                + val);
                                        //                                 new Graph(new StateGraph(stg, init, states, sortedSignals), true, null);
                                        return false;
                                    case high:
                                    case low:
                                        s.setSignalState(sig, val);
                                        for (State s3 : alsoset) {
                                            s3.setSignalState(sig, val);
                                        }
                                        isNowSet = true;
                                        break;
                                    }
                                    if (isNowSet) {
                                        break;
                                    }
                                } else {
                                    alsoset.add(s2);
                                    checkstates.addAll(s2.getPrevStates());
                                    checkedStates.add(s2);
                                    if (checkedStates.size() == states.size()) {
                                        logger.error("Aborting fill states");
                                        return false;
                                    }
                                }
                            }
                            if (!isNowSet) {
                                logger.error("Cannot fill states");
                                return false;
                            }
                        }
                    }
                }
            }
        }
        return true;
    }
}