/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * 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 com.analog.lyric.dimple.model.core; import java.util.AbstractCollection; import java.util.Iterator; import com.analog.lyric.dimple.model.factors.Factor; import com.analog.lyric.dimple.model.factors.FactorBase; import com.analog.lyric.dimple.model.variables.Constant; import com.analog.lyric.dimple.model.variables.Variable; import com.analog.lyric.dimple.model.variables.VariableBlock; /** * Contains static methods for constructing {@link Iterable}s over contents of {@link FactorGraph}s. * <p> * Note that the methods in this class typically return an unmodifiable subclass of {@link java.util.Collection} * for convenience. * <p> * @since 0.08 * @author Christopher Barber * @see FactorGraphIterators */ public class FactorGraphIterables { /** * Returns iterable over the boundary variables for a graph. * <p> * Iterates using {@link FactorGraphIterators#boundary(FactorGraph)} * @since 0.08 */ public static IFactorGraphChildren<Variable> boundary(FactorGraph graph) { return new BoundaryVariables(graph); } /** * Returns iterable over all {@link Constant} objects contained in this graph. * <p> * Iterates using {@link FactorGraphIterators#constants(FactorGraph)}. * @since 0.08 */ public static IFactorGraphChildren<Constant> constants(FactorGraph graph) { return constantsDownto(graph, Integer.MAX_VALUE); } /** * Returns iterable over all {@link Constant} objects contained in this graph down to specified depth. * <p> * Iterates using {@link FactorGraphIterators#constantsDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<Constant> constantsDownto(FactorGraph graph, int maxNestingDepth) { return new NestedConstants(graph, maxNestingDepth); } /** * Returns iterable over all {@link Factor} objects contained in this graph. * <p> * Iterates using {@link FactorGraphIterators#factors(FactorGraph)}. * @since 0.08 */ public static IFactorGraphChildren<Factor> factors(FactorGraph graph) { return factorsDownto(graph, Integer.MAX_VALUE); } /** * Returns iterable over all {@link Factor} objects contained in this graph down to specified depth. * <p> * Iterates using {@link FactorGraphIterators#factorsDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<Factor> factorsDownto(FactorGraph graph, int maxNestingDepth) { return new NestedFactors(graph, maxNestingDepth); } /** * Returns iterable over all {@link Factor} objects contained in this graph down to specified depth * and any {@link FactorGraph} objects at specified depth. * <p> * Iterates using {@link FactorGraphIterators#factorsAndLeafSubgraphsDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<FactorBase> factorsAndLeafSubgraphsDownto(FactorGraph graph, int maxNestingDepth) { return new NestedFactorsAndGraphs(graph, maxNestingDepth); } /** * Returns iterable over all {@link FactorGraph} objects contained in this graph including this graph. * <p> * Iterates using {@link FactorGraphIterators#subgraphs(FactorGraph)}. * @since 0.08 */ public static IFactorGraphChildren<FactorGraph> subgraphs(FactorGraph graph) { return subgraphsDownto(graph, Integer.MAX_VALUE); } /** * Returns iterable over all {@link FactorGraph} objects contained in this graph including this graph * down to specified depth. * <p> * Iterates using {@link FactorGraphIterators#subgraphsDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<FactorGraph> subgraphsDownto(FactorGraph graph, int maxNestingDepth) { return new NestedFactorGraphs(graph, maxNestingDepth); } /** * Returns iterable over all {@link Variable} objects contained in this graph. * <p> * Iterates using {@link FactorGraphIterators#variables(FactorGraph)}. * @since 0.08 */ public static IFactorGraphChildren<Variable> variables(FactorGraph graph) { return variablesDownto(graph, Integer.MAX_VALUE); } /** * Returns iterable over all {@link Variable} objects contained in this graph down to specified depth. * <p> * Iterates using {@link FactorGraphIterators#variablesDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<Variable> variablesDownto(FactorGraph graph, int maxNestingDepth) { return new NestedVariables(graph, maxNestingDepth, false); } /** * Returns iterable over all {@link Variable} objects contained in this graph including boundary * variables of this graph. * <p> * Iterates using {@link FactorGraphIterators#variablesAndBoundary(FactorGraph)}. * @since 0.08 */ public static IFactorGraphChildren<Variable> variablesAndBoundary(FactorGraph graph) { return variablesAndBoundaryDownto(graph, Integer.MAX_VALUE); } /** * Returns iterable over all {@link Variable} objects contained in this graph down to specified depth and * including boundary variables of this graph. * <p> * Iterates using {@link FactorGraphIterators#variablesAndBoundaryDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<Variable> variablesAndBoundaryDownto(FactorGraph graph, int maxNestingDepth) { return new NestedVariables(graph, maxNestingDepth, true); } /** * Returns iterable over all {@link VariableBlock} objects contained in this graph. * <p> * Iterates using {@link FactorGraphIterators#variableBlocks(FactorGraph)}. * @since 0.08 */ public static IFactorGraphChildren<VariableBlock> variableBlocks(FactorGraph graph) { return variableBlocksDownto(graph, Integer.MAX_VALUE); } /** * Returns iterable over all {@link VariableBlock} objects contained in this graph down to specified depth. * <p> * Iterates using {@link FactorGraphIterators#variableBlocksDownto(FactorGraph, int)}. * @since 0.08 */ public static IFactorGraphChildren<VariableBlock> variableBlocksDownto(FactorGraph graph, int maxNestingDepth) { return new NestedVariableBlocks(graph, maxNestingDepth); } /*----------------- * Implementations */ private static class NestedFactorGraphs extends AbstractCollection<FactorGraph> implements IFactorGraphChildren<FactorGraph> { /*------- * State */ private final FactorGraph _root; private final int _maxNestingDepth; private NestedFactorGraphs(FactorGraph root, int maxNestingDepth) { _root = root; _maxNestingDepth = maxNestingDepth; } @Override public IFactorGraphChildIterator<FactorGraph> iterator() { return FactorGraphIterators.subgraphsDownto(_root, _maxNestingDepth); } @Override public int size() { switch (_maxNestingDepth) { case 0: return 1; case 1: return 1 + _root.ownedGraphCount(); } final Iterator<FactorGraph> iter = iterator(); int count = 0; while (iter.hasNext()) { iter.next(); ++count; } return count; } @Override public FactorGraph root() { return _root; } @Override public int maxNestingDepth() { return _maxNestingDepth; } } private static abstract class NestedFactorGraphChildren<T> extends AbstractCollection<T> implements IFactorGraphChildren<T> { protected final FactorGraph _root; protected final int _maxNestingDepth; private NestedFactorGraphChildren(FactorGraph graph, int maxNestingDepth) { _root = graph; _maxNestingDepth = maxNestingDepth; } @Override public abstract IFactorGraphChildIterator<T> iterator(); @Override public int size() { if (_maxNestingDepth == 0 || _root.ownedGraphCount() == 0) { return childCount(_root, 0); } final IFactorGraphChildIterator<FactorGraph> graphIter = FactorGraphIterators.subgraphsDownto(_root, _maxNestingDepth); int count = 0; while (true) { FactorGraph graph = graphIter.next(); if (graph != null) { count += childCount(graph, graphIter.lastDepth()); } else { return count; } } } @Override public int maxNestingDepth() { return _maxNestingDepth; } @Override public FactorGraph root() { return _root; } protected abstract int childCount(FactorGraph graph, int depth); } private static class NestedConstants extends NestedFactorGraphChildren<Constant> { private NestedConstants(FactorGraph graph, int maxNestingDepth) { super(graph, maxNestingDepth); } @Override protected int childCount(FactorGraph graph, int depth) { return graph.ownedConstantCount(); } @Override public IFactorGraphChildIterator<Constant> iterator() { return FactorGraphIterators.constantsDownto(_root, _maxNestingDepth); } } private static class NestedFactors extends NestedFactorGraphChildren<Factor> { private NestedFactors(FactorGraph graph, int maxNestingDepth) { super(graph, maxNestingDepth); } @Override protected int childCount(FactorGraph graph, int depth) { return graph.ownedFactorCount(); } @Override public IFactorGraphChildIterator<Factor> iterator() { return FactorGraphIterators.factorsDownto(_root, _maxNestingDepth); } } private static class NestedFactorsAndGraphs extends NestedFactorGraphChildren<FactorBase> { /** * @param graph * @param maxNestingDepth * @since 0.08 */ private NestedFactorsAndGraphs(FactorGraph graph, int maxNestingDepth) { super(graph, maxNestingDepth); } @Override protected int childCount(FactorGraph graph, int depth) { int count = graph.ownedFactorCount(); if (depth == _maxNestingDepth) { count += graph.ownedGraphCount(); } return count; } @Override public IFactorGraphChildIterator<FactorBase> iterator() { return FactorGraphIterators.factorsAndLeafSubgraphsDownto(_root, _maxNestingDepth); } } private static class NestedVariables extends NestedFactorGraphChildren<Variable> { private final boolean _includeBoundary; private NestedVariables(FactorGraph graph, int maxNestingDepth, boolean includeBoundary) { super(graph, maxNestingDepth); _includeBoundary = includeBoundary; } @Override public IFactorGraphChildIterator<Variable> iterator() { if (_includeBoundary) { return FactorGraphIterators.variablesAndBoundaryDownto(_root, _maxNestingDepth); } else { return FactorGraphIterators.variablesDownto(_root, _maxNestingDepth); } } @Override protected int childCount(FactorGraph graph, int depth) { int count = graph.ownedVariableCount(); if (depth == 0 && _includeBoundary) { Iterator<?> iter = graph.externalBoundaryVariableIterator(); while (iter.hasNext()) { iter.next(); ++count; } } return count; } } private static class BoundaryVariables extends NestedFactorGraphChildren<Variable> { private BoundaryVariables(FactorGraph graph) { super(graph, 0); } @Override public IFactorGraphChildIterator<Variable> iterator() { return FactorGraphIterators.boundary(_root); } @Override protected int childCount(FactorGraph graph, int depth) { return _root.getBoundaryVariableCount(); } } private static class NestedVariableBlocks extends NestedFactorGraphChildren<VariableBlock> { private NestedVariableBlocks(FactorGraph graph, int maxNestingDepth) { super(graph, maxNestingDepth); } @Override protected int childCount(FactorGraph graph, int depth) { return graph.ownedVariableBlockCount(); } @Override public IFactorGraphChildIterator<VariableBlock> iterator() { return FactorGraphIterators.variableBlocksDownto(_root, _maxNestingDepth); } } }