/*******************************************************************************
* Copyright 2014 Felipe Takiyama
*
* 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 br.usp.poli.takiyama.common;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import br.usp.poli.takiyama.prv.Prv;
import br.usp.poli.takiyama.prv.RangeElement;
import br.usp.poli.takiyama.prv.StdPrv;
import br.usp.poli.takiyama.prv.Substitution;
import br.usp.poli.takiyama.prv.Term;
public interface Factor extends Iterable<Tuple<RangeElement>> {
/**
* Returns the index of a tuple.
*
* @param tuple The tuple to search.
* @return The index of a tuple in this factor.
* @throws IllegalArgumentException if the tuple is empty.
*/
public int getIndex(Tuple<RangeElement> tuple)
throws IllegalArgumentException;
/**
* Returns a tuple given its index.
*
* @param index The index of the tuple.
* @return A tuple at the position specified by the parameter <b>index</b>.
*/
public Tuple<RangeElement> getTuple(int index);
/**
* Returns the value of the tuple specified by its index.
*
* @param index The index of the tuple in this factor.
* @return The value of the tuple specified by its index.
*/
public BigDecimal getValue(int index);
/**
* Returns the value of the specified tuple.
*
* @param tuple The tuple whose value is to return
* @return The value of the specified tuple.
*/
public BigDecimal getValue(Tuple<RangeElement> tuple);
/**
* Returns an iterator over all tuples of this factor.
* <p>
* The tuples returned <b>depend</b> on the order of its {@link Prv}s.
* </p>
*
* @return An iterator over all tuples of this factor
*/
public Iterator<Tuple<RangeElement>> iterator();
/**
* Returns the number of values in this factor, which is the same as the
* number of tuples in this factor.
*
* @return The number of values in this factor.
*/
public int size();
/**
* Returns the name of this factor.
*
* @return The name of this factor.
*/
public String name();
/**
* Returns the list of {@link Prv}s associated with this factor. This
* list has the same order in which Prvs were inserted when creating
* this factor.
*
* @return The list of {@link Prv}s associated with this factor
*/
public List<Prv> variables();
/**
* Returns the values of all tuples, in the order they were created.
*
* @return A list containing all values of the factor, in order.
*/
public List<BigDecimal> values();
/**
* Returns <code>true</code> if the specified {@link Term} is in this factor.
*
* @param t The term to search for.
* @return <code>true</code> if the specified term specified is in this
* factor, <code>false</code> otherwise.
*/
public boolean contains(Term t);
/**
* Returns the number of occurrences of the specified {@link Term} in
* {@link Prv}s from this factor.
*
* @param t The term to search for.
* @return the number of occurrences of the specified {@link Term} in
* {@link Prv}s from this factor.
*/
public int occurrences(Term t);
/**
* Returns the first occurrence of a PRV in this factor having the
* specified term, according to the order returned by the iterator of
* variables of this factor.
* <p>
* If there is no PRV having the specified term, returns an empty
* {@link StdPrv}.
* </p>
*
* @param t The term to search for
* @return The first occurrence of a PRV in this factor having the
* specified term.
*/
public Prv getVariableHaving(Term t);
/**
* Returns <code>true</code> if this factor is a sub-factor of the
* specified factor.
* <p>
* Factor F1 is a sub-factor of factor F2 if the set of {@link Prv}s from
* F1 is a subset of the of Prvs from F2.
* </p>
*
* @return <code>true</code> if this factor is a sub-factor of the
* specified factor, <code>false</code> otherwise.
*/
public boolean isSubFactorOf(Factor factor);
/**
* Returns <code>true</code> if this factor is constant.
* <p>
* A constant factor returns the value 1 for all tuples in the factor.
* </p>
*
* @return <code>true</code> if this factor is constant, <code>false</code>
* otherwise.
*/
public boolean isConstant();
/**
* Returns <code>true</code> if this factor is empty.
* <p>
* An empty factor has no variables, nor values.
* </p>
*
* @return <code>true</code> if this factor is empty, <code>false</code>
* otherwise.
*/
public boolean isEmpty();
@Override
public int hashCode();
@Override
public boolean equals(Object other);
@Override
public String toString();
/**
* Returns the result of applying the specified substitution to this
* Factor. The substitution is applied to PRVs in this Factor, but its
* values are not modified.
* @param s The substitution to apply
* @return The result of applying the specified substitution to this
* Factor
*/
public Factor apply(Substitution s);
/**
* Returns a copy of this factor with the value of the specified tuple
* replaced by the specified value.
*
* @param tuple The tuple whose value must be modified
* @param value The new value of the tuple
* @return a copy of this factor with the value of the specified tuple
* replaced by the specified value.
*/
public Factor set(Tuple<RangeElement> tuple, BigDecimal value);
/**
* Sums out a random variable from a factor.
* <p>
* Suppose F is a factor on random variables x<sub>1</sub>,...,
* x<sub>i</sub>,...,x<sub>j</sub>. The summing out of random variable
* x<sub>i</sub> from F, denoted as Σ<sub>x<sub>i</sub></sub>F
* is the factor on
* random variables x<sub>1</sub>,...,x<sub>i-1</sub>, x<sub>i+1</sub>,
* ..., x<sub>j</sub> such that
* </p>
* (Σ<sub>x<sub>i</sub></sub> F)
* (x<sub>1</sub>,...,x<sub>i-1</sub>,x<sub>i+1</sub>,...,x<sub>j</sub>) =
* Σ <sub>y ∈ dom(x<sub>i</sub>)</sub>
* F(x<sub>1</sub>,...,x<sub>i-1</sub>,x<sub>i</sub> = y,
* x<sub>i+1</sub>,...,x<sub>j</sub>).
* <p>
* If the variable to be summed out does not exist in the factor, this
* method returns the specified factor unmodified.
* </p>
*
* @param prv The {@link Prv} to be summed out.
* @return A factor with the specified Prv summed out, or this factor
* if <code>prv</code> does not exist in this factor.
*/
public Factor sumOut(Prv prv);
/**
* Returns this factor raised by <code>p/q</code>.
* <p>
* Raising a factor to some exponent is the same as raising its values to
* that exponent.
* </p>
*
* @param p Exponents's numerator
* @param q Exponenet's denominator
* @return The value of this factor raised to <code>p/q</code>
*/
public Factor pow(int p, int q);
/**
* Multiplies this factor with the specified factor.
* <p>
* Given two factors
* F<sub>1</sub>(x<sub>1</sub>,...,x<sub>n</sub>,
* y<sub>1</sub>,...,y<sub>j</sub>) and
* F<sub>2</sub>(y<sub>1</sub>,...,y<sub>j</sub>,
* z<sub>1</sub>,...,z<sub>k</sub>)
* the resulting factor will be
* F(x<sub>1</sub>,...,x<sub>n</sub>,y<sub>1</sub>,...,
* y<sub>j</sub>,z<sub>1</sub>,...,z<sub>k</sub>) =
* F<sub>1</sub>(x<sub>1</sub>,...,x<sub>n</sub>,y<sub>1</sub>,...,
* y<sub>j</sub>) x
* F<sub>2</sub>(y<sub>1</sub>,...,y<sub>j</sub>,z<sub>1</sub>,...,
* z<sub>k</sub>)
* </p>
* That is, for each assignment of values to the variables in the factors,
* the method multiply the values that have the same assignment for common
* variables.
*
* @param secondFactor The second factor to be multiplied
* @return The multiplication of fisrtFactor by secondFactor.
*/
public Factor multiply(Factor factor);
/**
* Returns this factor reordered using the specified factor as a reference.
* The returned factor will have the same Prv order as the reference, with
* values reordered in order to not modify the distribution it represents.
*
* @param reference A reference factor that dictates the new PRV order
* @return This factor reordered using the specified factor as a reference.
* @throws IllegalArgumentException If the reference does not have the same
* PRVs as this factor.
*/
public Factor reorder(Factor reference) throws IllegalArgumentException;
}