/*******************************************************************************
* 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.solvers.core.proxy;
import org.eclipse.jdt.annotation.Nullable;
import com.analog.lyric.dimple.exceptions.DimpleException;
import com.analog.lyric.dimple.factorfunctions.core.IFactorTable;
import com.analog.lyric.dimple.model.core.EdgeState;
import com.analog.lyric.dimple.model.core.FactorGraph;
import com.analog.lyric.dimple.model.factors.Factor;
import com.analog.lyric.dimple.solvers.core.SFactorGraphBase;
import com.analog.lyric.dimple.solvers.interfaces.ISolverEdgeState;
import com.analog.lyric.dimple.solvers.interfaces.ISolverFactor;
import com.analog.lyric.dimple.solvers.interfaces.ISolverFactorGraph;
import com.analog.lyric.dimple.solvers.interfaces.ISolverNode;
import com.analog.lyric.dimple.solvers.interfaces.ISolverVariable;
import com.analog.lyric.dimple.solvers.interfaces.ISolverVariableBlock;
/**
* @since 0.05
*/
public abstract class ProxySolverFactorGraph<SFactor extends ISolverFactor, SVariable extends ISolverVariable,
SEdge extends ISolverEdgeState, SBlock extends ISolverVariableBlock, Delegate extends ISolverFactorGraph>
extends SFactorGraphBase<SFactor, SVariable, SEdge, SBlock>
implements IProxySolverNode<ISolverFactorGraph>
{
/*--------------
* Construction
*/
/**
* @param modelFactorGraph
*/
protected ProxySolverFactorGraph(FactorGraph modelFactorGraph, @Nullable ISolverFactorGraph parent)
{
super(modelFactorGraph, parent);
}
/*---------------------
* ISolverNode methods
*/
@Override
public double getBetheEntropy()
{
return requireDelegate("getBetheEntropy").getBetheEntropy();
}
@Override
public double getInternalEnergy()
{
return requireDelegate("getInternalEnergy").getInternalEnergy();
}
@Deprecated
@Override
public double getScore()
{
return requireDelegate("getScore").getScore();
}
@Override
public void initialize()
{
clearFlags();
requireDelegate("initialize").initialize();
}
@Override
public void update()
{
requireDelegate("update").update();
}
@Override
public void updateEdge(int outPortNum)
{
throw unsupported("updateEdge");
}
/*----------------------------
* ISolverFactorGraph methods
*/
@Override
public void baumWelch(IFactorTable[] tables, int numRestarts, int numSteps)
{
throw unsupported("baumWelch");
}
@Override
public void continueSolve()
{
requireDelegate("continueSolve").continueSolve();
}
@SuppressWarnings("null")
@Override
public SEdge createEdgeState(EdgeState edge)
{
return null;
}
@Deprecated
@Override
public boolean customFactorExists(String funcName)
{
ISolverFactorGraph sfg = getDelegate();
return sfg != null && sfg.customFactorExists(funcName);
}
@Override
public void estimateParameters(IFactorTable[] tables, int numRestarts, int numSteps, double stepScaleFactor)
{
throw unsupported("estimateParameters");
}
@Override
public double getBetheFreeEnergy()
{
return requireDelegate("getBetheFreeEnergy").getBetheFreeEnergy();
}
@Override
public @Nullable String getMatlabSolveWrapper()
{
ISolverFactorGraph sfg = getDelegate();
return sfg != null ? sfg.getMatlabSolveWrapper() : null;
}
@Override
public void setNumIterations(int numIterations)
{
if (numIterations != _numIterations)
{
_numIterations = numIterations;
ISolverFactorGraph delegate = getDelegate();
if (delegate != null)
{
delegate.setNumIterations(numIterations);
}
}
}
@Override
public int getNumIterations()
{
return _numIterations;
}
@Override
public boolean hasEdgeState()
{
return false;
}
@Override
public void interruptSolver()
{
ISolverFactorGraph sfg = getDelegate();
if (sfg != null)
{
sfg.interruptSolver();
}
}
@Override
public boolean isSolverRunning()
{
ISolverFactorGraph sfg = getDelegate();
return sfg != null && sfg.isSolverRunning();
}
@Override
public void iterate()
{
requireDelegate("iterate").iterate();
}
@Override
public void iterate(int numIters)
{
requireDelegate("iterate").iterate(numIters);
}
@Override
public void moveMessages(ISolverNode other)
{
requireDelegate("moveMessages").moveMessages(other);
}
@Override
public void solve()
{
requireDelegate("solve").solve();
}
@Override
public void solveOneStep()
{
requireDelegate("solveOneSte").solveOneStep();
}
@Override
public void startContinueSolve()
{
requireDelegate("startContinueSolve").startContinueSolve();
}
@Override
public void startSolveOneStep()
{
requireDelegate("startSolveOneStep").startSolveOneStep();
}
@Override
public void startSolver()
{
requireDelegate("startSolver").startSolver();
}
@Override
public void postAdvance()
{
requireDelegate("postAdvance").postAdvance();
}
@Override
public void postAddFactor(Factor f)
{
ISolverFactorGraph sfg = getDelegate();
if (sfg != null)
{
sfg.postAddFactor(f);
}
}
@Override
public void postSetSolverFactory()
{
ISolverFactorGraph sfg = getDelegate();
if (sfg != null)
{
sfg.postSetSolverFactory();
}
}
@Override
public void useMultithreading(boolean use)
{
if (use != _useMultithreading)
{
_useMultithreading = use;
ISolverFactorGraph delegate = getDelegate();
if (delegate != null)
{
delegate.useMultithreading(use);
}
}
}
/*---------------
* SNode methods
*/
@Override
protected void doUpdateEdge(int edge)
{
}
/*-------------------------
* ProxySolverNode methods
*/
@Override
public abstract @Nullable Delegate getDelegate();
/**
* Returns non-null delegate or throws an error indicating method requires that
* delegate solver has been set.
* @since 0.06
*/
protected Delegate requireDelegate(String method)
{
Delegate delegate = getDelegate();
if (delegate == null)
{
throw new DimpleException("Delegate solver required by '%s' has not been set.", method);
}
return delegate;
}
protected RuntimeException unsupported(String method)
{
return DimpleException.unsupportedMethod(getClass(), method,
"Not supported for proxy solver because graph topology may be different.");
}
/**
* Should be invoked by implementing subclass when delegate changes.
*
* @param delegate is the new value that will be returned by {@link #getDelegate()}. May be null.
* @return delegate
* @since 0.05
*/
protected @Nullable Delegate notifyNewDelegate(@Nullable Delegate delegate)
{
if (delegate != null)
{
// Copy locally saved parameters.
delegate.useMultithreading(_useMultithreading);
delegate.setNumIterations(_numIterations);
}
return delegate;
}
}