/*******************************************************************************
* 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.test.model.core;
import static com.analog.lyric.util.test.ExceptionTester.*;
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.Test;
import com.analog.lyric.dimple.data.DataLayer;
import com.analog.lyric.dimple.data.GenericDataLayer;
import com.analog.lyric.dimple.events.DimpleEventListener;
import com.analog.lyric.dimple.events.IDimpleEventSource;
import com.analog.lyric.dimple.factorfunctions.Normal;
import com.analog.lyric.dimple.model.core.FactorGraph;
import com.analog.lyric.dimple.model.core.Node;
import com.analog.lyric.dimple.model.factors.Factor;
import com.analog.lyric.dimple.model.values.Value;
import com.analog.lyric.dimple.model.variables.Real;
import com.analog.lyric.dimple.model.variables.Variable;
import com.analog.lyric.dimple.options.DimpleOptions;
import com.analog.lyric.dimple.schedulers.IScheduler;
import com.analog.lyric.dimple.schedulers.schedule.ISchedule;
import com.analog.lyric.dimple.solvers.interfaces.ISolverFactorGraph;
import com.analog.lyric.dimple.solvers.sumproduct.SumProductSolver;
import com.analog.lyric.dimple.test.DimpleTestBase;
/**
*
* @since 0.08
* @author Christopher Barber
*/
public class TestFreezing extends DimpleTestBase
{
@Test
public void test()
{
FactorGraph fg0 = new FactorGraph();
Real a = new Real(), b = new Real();
fg0.addVariables(a, b);
fg0.addFactor(new Normal(), 0.0, 1.0, a, b);
expectThrow(IllegalStateException.class, ".*has a solver graph.*", fg0, "freezeGraphTree");
fg0.setSolverFactory(null);
fg0.setDefaultConditioningLayer(new GenericDataLayer(fg0));
expectThrow(IllegalStateException.class, ".*default conditioning layer is not null.*", fg0, "freezeGraphTree");
fg0.setDefaultConditioningLayer(null);
assertFalse(fg0.frozen());
fg0.freezeGraphTree();
expectFrozenErrors(fg0);
FactorGraph fg1 = new FactorGraph();
fg1.addGraph(fg0);
assertFalse(fg1.frozen());
fg1.setSolverFactory(null);
fg1.freezeGraphTree();
expectFrozenErrors(fg1);
}
private void expectFrozenErrors(FactorGraph graph)
{
assertTrue(graph.frozen());
graph.freezeGraphTree(); // no effect
expectFrozenErrors((Node)graph);
expectFrozen(graph, "addBoundaryVariables", new Real());
expectFrozen(graph, "addConstant", 42);
expectFrozen(graph, "addConstant", Value.create(42));
expectFrozen(graph, "addFactor", new Normal());
expectFrozen(graph, "addFactor", "Normal");
expectFrozen(graph, "addGraph", new FactorGraph());
expectFrozen(graph, "addVariables", new Real());
expectFrozen(graph, "reindexGraphTree");
expectFrozen(graph, "setDefaultConditioningLayer", (DataLayer<?>)null);
expectFrozen(graph, "setEventAndOptionParent", (IDimpleEventSource)null);
expectFrozen(graph, "setScheduler", (IScheduler)null);
expectFrozen(graph, "setSolver", (ISolverFactorGraph)null);
expectFrozen(graph, "setSolverFactory", new SumProductSolver());
// Deprecated
expectFrozen(graph, "clearNames");
expectFrozen(graph, "defineVariableGroup", new ArrayList<>());
expectFrozen(graph, "setEventListener", (DimpleEventListener)null);
expectFrozen(graph, "setNamesByStructure");
expectFrozen(graph, "setNamesByStructure", "b", "o", "f", "r", "c");
expectFrozen(graph, "setSchedule", (ISchedule)null);
for (Variable var : graph.getOwnedVariables())
{
expectFrozenErrors(var);
expectFrozen(graph, "remove", var);
expectFrozen(graph, "removeVariables", var);
expectFrozen(graph, "addVariableBlock", var);
expectFrozen(graph, "join", var);
expectFrozen(graph, "split", var);
expectFrozen(graph, "setChildName", var, null);
}
for (Factor factor : graph.getOwnedFactors())
{
expectFrozenErrors(factor);
expectFrozen(graph, "join", factor);
expectFrozen(graph, "join", new Variable[] { new Real() }, factor);
expectFrozen(graph, "remove", factor);
expectFrozen(graph, "replaceEdge", factor, 0, new Real());
}
for (FactorGraph subgraph : graph.getOwnedGraphs())
{
expectFrozenErrors(subgraph);
expectFrozen(graph, "absorbSubgraph", subgraph);
expectFrozen(graph, "remove", subgraph);
}
}
private void expectFrozenErrors(Node node)
{
// INameable
expectFrozen(node, "setName", "barf");
expectFrozen(node, "setLabel", "barf");
// IOptionHolder
expectFrozen(node, "clearLocalOptions");
expectFrozen(node, "setOption", DimpleOptions.randomSeed, 1234);
expectFrozen(node, "unsetOption", DimpleOptions.randomSeed);
expectFrozen(node, "clearMarked");
expectFrozen(node, "clearVisited");
expectFrozen(node, "setMarked");
expectFrozen(node, "setVisited");
// FactorGraphChild
expectFrozen(node, "setLocalId", 0);
}
@SafeVarargs
private final <T> void expectFrozen(Object object, String methodName, T ... args)
{
expectThrow(IllegalStateException.class, "Changes cannot be made to frozen graph", object, methodName, args);
}
}