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

net.automatalib.util.ts.traversal.TSTraversal Maven / Gradle / Ivy

Go to download

This artifact provides various common utility operations for analyzing and manipulating automata and graphs, such as traversal, minimization and copying.

There is a newer version: 0.11.0
Show newest version
/* Copyright (C) 2013-2019 TU Dortmund
 * This file is part of AutomataLib, http://www.automatalib.net/.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.automatalib.util.ts.traversal;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;

import net.automatalib.commons.util.Holder;
import net.automatalib.ts.TransitionSystem;
import net.automatalib.util.traversal.TraversalOrder;

/**
 * @author Malte Isberner
 */
public final class TSTraversal {

    public static final int NO_LIMIT = -1;

    private TSTraversal() {
    }

    public static  boolean depthFirst(TransitionSystem ts,
                                                  Collection inputs,
                                                  TSTraversalVisitor vis) {
        return depthFirst(ts, NO_LIMIT, inputs, vis);
    }

    public static  boolean depthFirst(TransitionSystem ts,
                                                  int limit,
                                                  Collection inputs,
                                                  TSTraversalVisitor vis) {
        Deque> dfsStack = new ArrayDeque<>();

        Holder dataHolder = new Holder<>();

        // setting the following to false means that the traversal had to be aborted
        // due to reaching the limit
        boolean complete = true;
        int stateCount = 0;

        for (S initS : ts.getInitialStates()) {
            dataHolder.value = null;
            TSTraversalAction act = vis.processInitial(initS, dataHolder);
            switch (act) {
                case ABORT_INPUT:
                case ABORT_STATE:
                case IGNORE:
                    continue;
                case ABORT_TRAVERSAL:
                    return complete;
                case EXPLORE:
                    if (stateCount != limit) {
                        dfsStack.push(new DFRecord<>(initS, inputs, dataHolder.value));
                        stateCount++;
                    } else {
                        complete = false;
                    }
                    break;
                default:
                    throw new IllegalStateException("Unknown action " + act);
            }
        }

        while (!dfsStack.isEmpty()) {
            DFRecord current = dfsStack.peek();

            S source = current.state;
            D data = current.data;

            if (current.start(ts)) {
                if (!vis.startExploration(source, data)) {
                    dfsStack.pop();
                    continue;
                }
            }

            if (!current.hasNextTransition(ts)) {
                dfsStack.pop();
                continue;
            }

            I input = current.input();
            T trans = current.transition();

            S succ = ts.getSuccessor(trans);
            dataHolder.value = null;
            TSTraversalAction act = vis.processTransition(source, data, input, trans, succ, dataHolder);

            switch (act) {
                case ABORT_INPUT:
                    current.advanceInput(ts);
                    break;
                case ABORT_STATE:
                    dfsStack.pop();
                    break;
                case ABORT_TRAVERSAL:
                    return complete;
                case IGNORE:
                    current.advance(ts);
                    break;
                case EXPLORE:
                    if (stateCount != limit) {
                        dfsStack.push(new DFRecord<>(succ, inputs, dataHolder.value));
                        stateCount++;
                    } else {
                        complete = false;
                    }
                    break;
                default:
                    throw new IllegalStateException("Unknown action " + act);
            }
        }

        return complete;
    }

    public static  boolean breadthFirst(TransitionSystem ts,
                                                    Collection inputs,
                                                    TSTraversalVisitor vis) {
        return breadthFirst(ts, NO_LIMIT, inputs, vis);
    }

    /**
     * Traverses the given transition system in a breadth-first fashion. The traversal is steered by the specified
     * visitor.
     *
     * @param ts
     *         the transition system.
     * @param inputs
     *         the input alphabet.
     * @param vis
     *         the visitor.
     */
    public static  boolean breadthFirst(TransitionSystem ts,
                                                    int limit,
                                                    Collection inputs,
                                                    TSTraversalVisitor vis) {
        Deque> bfsQueue = new ArrayDeque<>();

        // setting the following to false means that the traversal had to be aborted
        // due to reaching the limit
        boolean complete = true;
        int stateCount = 0;

        Holder dataHolder = new Holder<>();

        for (S initS : ts.getInitialStates()) {
            dataHolder.value = null;
            TSTraversalAction act = vis.processInitial(initS, dataHolder);
            switch (act) {
                case ABORT_TRAVERSAL:
                    return complete;
                case EXPLORE:
                    if (stateCount != limit) {
                        bfsQueue.offer(new BFSRecord<>(initS, dataHolder.value));
                        stateCount++;
                    } else {
                        complete = false;
                    }
                    break;
                default: // case ABORT_INPUT: case ABORT_STATE: case IGNORE:
            }
        }

        while (!bfsQueue.isEmpty()) {
            BFSRecord current = bfsQueue.poll();

            S state = current.state;
            D data = current.data;

            if (!vis.startExploration(state, data)) {
                continue;
            }

            inputs_loop:
            for (I input : inputs) {
                Collection transitions = ts.getTransitions(state, input);

                for (T trans : transitions) {
                    S succ = ts.getSuccessor(trans);

                    dataHolder.value = null;
                    TSTraversalAction act = vis.processTransition(state, data, input, trans, succ, dataHolder);

                    switch (act) {
                        case ABORT_INPUT:
                            continue inputs_loop;
                        case ABORT_STATE:
                            break inputs_loop;
                        case ABORT_TRAVERSAL:
                            return complete;
                        case EXPLORE:
                            if (stateCount != limit) {
                                bfsQueue.offer(new BFSRecord<>(succ, dataHolder.value));
                                stateCount++;
                            } else {
                                complete = false;
                            }
                            break;
                        case IGNORE:
                            break;
                        default:
                            throw new IllegalStateException("Unknown action " + act);
                    }
                }
            }
        }

        return complete;
    }

    public static  boolean traverse(TraversalOrder order,
                                                TransitionSystem ts,
                                                Collection inputs,
                                                TSTraversalVisitor vis) {
        return traverse(order, ts, NO_LIMIT, inputs, vis);
    }

    public static  boolean traverse(TraversalOrder order,
                                                TransitionSystem ts,
                                                int limit,
                                                Collection inputs,
                                                TSTraversalVisitor vis) {
        switch (order) {
            case BREADTH_FIRST:
                return breadthFirst(ts, limit, inputs, vis);
            case DEPTH_FIRST:
                return depthFirst(ts, limit, inputs, vis);
            default:
                throw new IllegalArgumentException("Unknown traversal order: " + order);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy