/******************************************************************************* * 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.util.List; import br.usp.poli.takiyama.cfove.StdParfactor; import br.usp.poli.takiyama.prv.Prv; import br.usp.poli.takiyama.prv.Prvs; import br.usp.poli.takiyama.prv.RandomVariableSet; import br.usp.poli.takiyama.utils.Sets; /** * Encapsulates the algorithm to check conditions for multiplication between * {@link Parfactor}s. * <p> * Currently, it supports {@link StdParfactor} and {@link AggregationParfactor}. * If new types of parfactors are added, the interface needs to be remodeled. * </p> * * @author Felipe Takiyama * */ public final class MultiplicationChecker implements ParfactorVisitor { private boolean areMultipliable; /** * Constructor. */ public MultiplicationChecker() { areMultipliable = false; } /** * Checks whether the specified {@link StdParfactor} can be * multiplied by another {@link StdParfactor}. This is possible if * all parameterized random variables f(...) ∈ Vi and f'(...) ∈ Vj such * that ground(f(...)) : Ci = ground(f'(...)) : Cj, f(...) and f'(...) are * identically parameterized by logical variables and the set of other * logical variables present in parfactor gi is disjoint with the set of * logical variables present in parfactor gj. * */ @Override public void visit(StdParfactor p1, StdParfactor p2) { /* * This code only verifies the first condition. * The other condition, concerning disjoint logical variables, is not * verified. I think I have misinterpreted this rule... */ areMultipliable = true; for (Prv prv1 : p1.prvs()) { for (Prv prv2 : p2.prvs()) { RandomVariableSet rvs1 = RandomVariableSet.getInstance(prv1, Sets.union(prv1.constraints(), p1.constraints())); RandomVariableSet rvs2 = RandomVariableSet.getInstance(prv2, Sets.union(prv2.constraints(), p2.constraints())); if (!Prvs.areDisjoint(rvs1, rvs2) && !rvs1.equals(rvs2)) { areMultipliable = false; break; } } } // TODO Need to use unification, nevertheless, I'll have a set of shattered parfactors, // so multiplication is always possible between std parfactors. // hehe - it is not // areMultipliable = true; // Set<LogicalVariable> lv1 = p1.logicalVariables(); // Set<LogicalVariable> lv2 = p2.logicalVariables(); // for (Prv prv1 : p1.prvs()) { // for (Prv prv2 : p2.prvs()) { // if (sameName(prv1, prv2)) { // boolean sameParameters = sameParameters(prv1, prv2); // // I think the disjoint lv thing is not correct // //boolean disjointRemainingLogicalVariables = disjointRemainingLogicalVariables(lv1, prv1, lv2, prv2); // if (!sameParameters /*|| !disjointRemainingLogicalVariables*/) { // areMultipliable = false; // break; // } // } // } // } } /** * Checks whether the specified {@link AggregationParfactor} can be * multiplied by the specified {@link StdParfactor}. This is possible if * <li> They both have the same set of constraints * <li> The specified standard parfactor has the same PRVs as * the specified aggregation parfactor, excluding the child PRV. */ @Override public void visit(AggregationParfactor agg, StdParfactor std) { boolean stdIsEmpty = std.factor().isEmpty(); boolean sameConstraints = agg.constraints().equals(std.constraints()); List<Prv> stdPrvs = std.factor().variables(); List<Prv> aggPrvs = agg.factor().variables(); boolean samePrvsInFactor = stdPrvs.containsAll(aggPrvs) && aggPrvs.containsAll(stdPrvs); areMultipliable = (stdIsEmpty || (sameConstraints && samePrvsInFactor)); } /** * Returns <code>false</code>, because an * {@link AggregationParfactor} cannot * multiply another {@link AggregationParfactor} */ @Override public void visit(AggregationParfactor agg1, AggregationParfactor agg2) { areMultipliable = false; } /** * Returns the status of a multiplication check. If no visit were made, * returns <code>false</code>. * * @return The status of a multiplication check or <code>false</code> if * no visits were made. */ public boolean areMultipliable() { return areMultipliable; } }