/*******************************************************************************
* Copyright 2015 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 static java.util.Objects.*;
import com.analog.lyric.dimple.model.factors.Factor;
import com.analog.lyric.dimple.model.variables.Variable;
import com.analog.lyric.util.misc.Internal;
/**
* Describes an edge from a factor to a variable.
* <p>
* Edge state objects are maintained by each {@link FactorGraph} for the edges that connect
* to it's directly owned {@link Factor}s.
* <p>
* To save memory, these objects do not contain a pointer to the owning graph and some methods
* will require a reference to the parent graph. You can wrap this with an {@link Edge} object
* if you want a self-contained edge reference.
* <p>
* @since 0.08
* @author Christopher Barber
*/
public abstract class EdgeState
{
/*-------
* State
*/
int _factorToVariableEdgeNumber = -1;
int _variableToFactorEdgeNumber = -1;
/*------------------------------
* FactorGraphEdgeState methods
*/
/**
* Describes the direction of the edge.
* @since 0.08
*/
public EdgeDirection direction(FactorGraph graph)
{
// TODO - perhaps we can store the direction directly in the edge state
return getFactor(graph).getEdgeDirection(getFactorToVariableEdgeNumber());
}
/**
* The index of this edge within the {@link FactorGraph} that owns it's factor.
* <p>
* This index can be used to look up this object within the parent graph of the factor
* using the {@link FactorGraph#getSiblingEdgeState(int)} method.
* <p>
* If {@link #isLocal()} then this will be the same as {@link #variableEdgeIndex()}.
* <p>
* @since 0.08
* @category internal
*/
@Internal
public abstract int factorEdgeIndex();
/**
* The index of this edge within the {@link FactorGraph} that owns it's variable.
* <p>
* This index can be used to look up this object within the parent graph of its variable
* using the {@link FactorGraph#getSiblingEdgeState(int)} method.
* <p>
* If {@link #isLocal()} then this will be the same as {@link #factorEdgeIndex()}.
* <p>
* @since 0.08
* @category internal
*/
@Internal
public abstract int variableEdgeIndex();
/**
* Given an end node for this edge, return the corresponding edge index.
*
* @param node Must be a variable or factor at one end of the edge.
* @return {@link #variableEdgeIndex()} or {@link #factorEdgeIndex()} as appropriate.
* @since 0.08
* @category internal
*/
@Internal
public abstract int edgeIndex(Node node);
/**
* Given the parent graph containing this edge, return its index in the graph.
* @since 0.08
* @category internal
*/
@Internal
public abstract int edgeIndexInParent(FactorGraph graph);
/**
* Return instance of {@link Factor} end of edge, given parent graph.
* <p>
* @param graph is the parent graph of either the variable or factor ends of the edge.
* @since 0.08
*/
abstract public Factor getFactor(FactorGraph graph);
/**
* Returns sibling edge number from the perspective of {@link Factor} endpoint of the edge.
* <p>
* @return sibling edge number or else -1 if edge is not currently connected to its endpoints.
* @since 0.08
* @see #getVariableToFactorEdgeNumber()
*/
public final int getFactorToVariableEdgeNumber()
{
return _factorToVariableEdgeNumber;
}
/**
* Return instance of parent of factor end of edge, given parent of either edge.
* @since 0.08
* @category internal
*/
@Internal
abstract public FactorGraph getFactorParent(FactorGraph graph);
/**
* Return instance of {@link Variable} end of edge, given parent graph.
* <p>
* @param graph is the parent graph of either the variable or factor ends of the edge.
* @since 0.08
*/
abstract public Variable getVariable(FactorGraph graph);
/**
* Returns sibling edge number from the perspective of {@link Variable} endpoint of the edge.
* <p>
* @return sibling edge number or else -1 if edge is not currently connected to its endpoints.
* @since 0.08
* @see #getFactorToVariableEdgeNumber()
*/
public final int getVariableToFactorEdgeNumber()
{
return _variableToFactorEdgeNumber;
}
/**
* Return instance of parent of variable end of edge, given parent of either edge.
* @since 0.08
* @category internal
*/
@Internal
abstract public FactorGraph getVariableParent(FactorGraph graph);
/**
* Given one endpoint of edge, return the other one.
* <p>
* That is given the {@link Variable} end of the edge, this returns the {@link Factor}, and
* vice-versa.
* <p>
* @since 0.08
*/
public final Node getSibling(INode node)
{
final FactorGraph graph = requireNonNull(node.getContainingGraph());
return node.isVariable() ? getFactor(graph) : getVariable(graph);
}
/**
* Given one endpoint of edge, find the sibling number from that endpoint to the other.
* <p>
* @param node is either the {@link Variable} or {@link Factor} at one end of the edge.
* @return index that could be used to lookup this edge using {@link Node#getSiblingEdgeState(int)}
* on the given {@code node}.
* @since 0.08
*/
public final int getSiblingIndex(Node node)
{
return node.indexOfSiblingEdgeState(this);
}
/**
* The local id of the {@link Factor} referred to by this edge within its owning {@link FactorGraph}.
* @since 0.08
*/
public int factorLocalId()
{
return Ids.localIdFromParts(Ids.FACTOR_TYPE, factorIndex());
}
/**
* The index of the {@link Factor} referred to by this edge within its owning {@link FactorGraph}.
* @since 0.08
*/
abstract public int factorIndex();
/**
* True if both the factor and variable are owned by the same graph.
* @since 0.08
*/
abstract public boolean isLocal();
/**
* Describe type of edge with respect to given graph.
* @since 0.08
*/
abstract public Edge.Type type(FactorGraph graph);
/**
* The index of the {@link Variable} referred to by this edge within the graph that owns this edge.
* <p>
* Note that the graph that owns the edge is the one that owns the edge's {@link Factor}, which may
* not be the owner of the variable. In that case, this will be the index of the corresponding
* boundary variable.
* <p>
* @since 0.08
*/
abstract public int variableIndex();
/**
* The local id of the {@link Variable} referred to by this edge within the graph that owns this edge.
* <p>
* Note that the graph that owns the edge is the one that owns the edge's {@link Factor}, which may
* not be the owner of the variable. In that case, this will return a boundary variable identifier.
* <p>
* @since 0.08
*/
abstract public int variableLocalId();
/**
* Set edge index to a new value with respect to given parent graph.
* @param newEdgeIndex must be smaller than the existing value of {@link #edgeIndexInParent(FactorGraph)}.
* @since 0.08
*/
abstract void setEdgeIndexInParent(FactorGraph graph, int newEdgeIndex);
/**
* Set index of edge's factor to a new value.
* @param newIndex must be smaller than the existing value of {@link #factorIndex()}
* @since 0.08
*/
abstract void setFactorIndex(int newIndex);
/**
* Set index of edge's variable to a new value.
* @param newIndex must be smaller than the existing value of {@link #variableIndex()}
* @since 0.08
*/
abstract void setVariableIndex(int newIndex);
}