/*******************************************************************************
* Copyright 2012 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.sumproduct;
import org.eclipse.jdt.annotation.Nullable;
import com.analog.lyric.dimple.data.IDatum;
import com.analog.lyric.dimple.environment.DimpleEnvironment;
import com.analog.lyric.dimple.model.values.Value;
import com.analog.lyric.dimple.model.variables.Real;
import com.analog.lyric.dimple.solvers.core.PriorAndCondition;
import com.analog.lyric.dimple.solvers.core.SNormalEdge;
import com.analog.lyric.dimple.solvers.core.SRealVariableBase;
import com.analog.lyric.dimple.solvers.core.parameterizedMessages.NormalParameters;
/**
* Solver variable for Real variables under Sum-Product solver.
*
* @since 0.07
*/
public class SumProductReal extends SRealVariableBase
{
public SumProductReal(Real var, SumProductSolverGraph parent)
{
super(var, parent);
}
@Override
protected void doUpdateEdge(int outPortNum)
{
doUpdate(getSiblingEdgeState(outPortNum).varToFactorMsg, outPortNum);
}
@Override
public NormalParameters getBelief()
{
return doUpdate(new NormalParameters(), -1);
}
@Override
public Object getValue()
{
NormalParameters belief = getBelief();
return new Double(belief.getMean());
}
public NormalParameters createDefaultMessage()
{
return new NormalParameters();
}
@Deprecated
@Override
public void setInputMsgValues(int portIndex, Object obj)
{
getSiblingEdgeState(portIndex).factorToVarMsg.set((NormalParameters)obj);
}
public NormalParameters createFixedValueMessage(double fixedValue)
{
NormalParameters message = new NormalParameters();
message.setMean(fixedValue);
message.setPrecision(Double.POSITIVE_INFINITY);
return message;
}
/*-----------------------
* SVariableBase methods
*/
@Override
protected NormalParameters cloneMessage(int edge)
{
return getSiblingEdgeState(edge).varToFactorMsg.clone();
}
@Override
protected boolean supportsMessageEvents()
{
return true;
}
@Override
@SuppressWarnings("null")
public SNormalEdge getSiblingEdgeState(int siblingIndex)
{
return (SNormalEdge)getSiblingEdgeState_(siblingIndex);
}
/*-----------------
* Private methods
*/
private NormalParameters doUpdate(NormalParameters outMsg, int excludeEdge)
{
PriorAndCondition known = getPriorAndCondition();
Value fixedValue = known.value();
if (fixedValue != null)
{
outMsg.setDeterministic(fixedValue);
}
else
{
outMsg.setNull();
for (IDatum datum : known)
{
NormalParameters input = priorToNormal(datum);
if (input != null)
{
outMsg.addFrom(input);
}
}
for (int i = getSiblingCount(); --i>=0;)
{
if (i != excludeEdge)
{
outMsg.addFrom(getSiblingEdgeState(i).factorToVarMsg);
}
}
}
known.release();
return outMsg;
}
private @Nullable NormalParameters priorToNormal(@Nullable IDatum prior)
{
NormalParameters result = null;
if (prior != null)
{
result = NormalParameters.fromDatum(prior);
if (result == null)
{
DimpleEnvironment.logError(
"Ignoring prior on %s: sum-product reals only supports NormalParameters for priors but got %s",
_model, prior);
}
}
return result;
}
}