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

net.automatalib.util.automata.ads.ADSUtil 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.automata.ads;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import com.google.common.math.LongMath;
import net.automatalib.automata.transducers.MealyMachine;
import net.automatalib.commons.util.Pair;
import net.automatalib.graphs.ads.ADSNode;
import net.automatalib.graphs.ads.impl.ADSSymbolNode;
import net.automatalib.words.Word;
import net.automatalib.words.WordBuilder;

/**
 * Utility class, that offers some operations revolving around adaptive distinguishing sequences.
 *
 * @author frohme
 */
public final class ADSUtil {

    private ADSUtil() {
    }

    public static  int computeLength(final ADSNode node) {
        if (node.isLeaf()) {
            return 0;
        }

        return 1 + node.getChildren().values().stream().mapToInt(ADSUtil::computeLength).max().getAsInt();
    }

    public static  int countSymbolNodes(final ADSNode node) {
        if (node.isLeaf()) {
            return 0;
        }

        return 1 + node.getChildren().values().stream().mapToInt(ADSUtil::countSymbolNodes).sum();
    }

    public static  Pair, ADSNode> buildFromTrace(final MealyMachine automaton,
                                                                                    final Word trace,
                                                                                    final S state) {
        final Iterator sequenceIter = trace.iterator();
        final I input = sequenceIter.next();
        final ADSNode head = new ADSSymbolNode<>(null, input);

        ADSNode tempADS = head;
        I tempInput = input;
        S tempState = state;

        while (sequenceIter.hasNext()) {
            final I nextInput = sequenceIter.next();
            final ADSNode nextNode = new ADSSymbolNode<>(tempADS, nextInput);

            final O oldOutput = automaton.getOutput(tempState, tempInput);

            tempADS.getChildren().put(oldOutput, nextNode);

            tempADS = nextNode;
            tempState = automaton.getSuccessor(tempState, tempInput);
            tempInput = nextInput;
        }

        return Pair.of(head, tempADS);
    }

    public static  Set> collectLeaves(final ADSNode root) {
        final Set> result = new LinkedHashSet<>();
        collectLeavesRecursively(result, root);
        return result;
    }

    private static  void collectLeavesRecursively(final Set> nodes,
                                                           final ADSNode current) {
        if (current.isLeaf()) {
            nodes.add(current);
        } else {
            for (ADSNode n : current.getChildren().values()) {
                collectLeavesRecursively(nodes, n);
            }
        }
    }

    public static  Pair, Word> buildTraceForNode(final ADSNode node) {

        ADSNode parentIter = node.getParent();
        ADSNode nodeIter = node;

        final WordBuilder inputBuilder = new WordBuilder<>();
        final WordBuilder outputBuilder = new WordBuilder<>();

        while (parentIter != null) {
            inputBuilder.append(parentIter.getSymbol());
            outputBuilder.append(getOutputForSuccessor(parentIter, nodeIter));

            nodeIter = parentIter;
            parentIter = parentIter.getParent();
        }

        return Pair.of(inputBuilder.reverse().toWord(), outputBuilder.reverse().toWord());
    }

    public static  O getOutputForSuccessor(final ADSNode node, final ADSNode successor) {

        if (!successor.getParent().equals(node)) {
            throw new IllegalArgumentException("No parent relationship");
        }

        for (Map.Entry> entry : node.getChildren().entrySet()) {
            if (entry.getValue().equals(successor)) {
                return entry.getKey();
            }
        }

        throw new IllegalArgumentException("No child relationship");
    }

    /**
     * Computes an upper bound for the length of a splitting word. Based on
     * 

* I.V. Kogan. "Estimated Length of a Minimal Simple Conditional Diagnostic Experiment". In: Automation and Remote * Control 34 (1973) * * @param n * the size of the automaton (number of states) * @param i * the number of states that should be distinguished by the current splitting word * @param m * the number of states that should originally be distinguished * * @return upper bound for the length of a splitting word */ public static long computeMaximumSplittingWordLength(final int n, final int i, final int m) { if (m == 2) { return n; } return LongMath.binomial(n, i) - LongMath.binomial(m - 1, i - 1) - 1; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy