/*******************************************************************************
* 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.parameterizedMessages;
import java.io.Serializable;
import org.eclipse.jdt.annotation.Nullable;
import com.analog.lyric.dimple.factorfunctions.core.IUnaryFactorFunction;
import com.analog.lyric.dimple.model.domains.Domain;
import com.analog.lyric.dimple.model.values.Value;
import com.analog.lyric.util.misc.IPrintable;
public interface IParameterizedMessage extends IUnaryFactorFunction, Cloneable, Serializable, IPrintable
{
/*-----------
* Cloneable
*/
@Override
public abstract IParameterizedMessage clone();
/*------------------------------
* IUnaryFactorFunction methods
*/
/**
* {@inheritDoc}
* <p>
* The returned energy value may be normalized by subtracting the
* {@linkplain #getNormalizationEnergy() normalization energy}.
*/
@Override
public double evalEnergy(Value value);
/*-------------------------------
* IParameterizedMessage methods
*/
/**
* Adds natural parameters from another message.
* <p>
* @param other unless otherwise documented must be the same type as this object.
* @throws UnsupportedOperationException if message does not support additive parameters
* @throws ClassCastException if {@code other} is not the same or compatible class type.
* @since 0.08
*/
public void addFrom(IParameterizedMessage other);
/**
* Adds additional energy to the normalization constant returned by {@link #getNormalizationEnergy()}.
* <p>
* This is equivalent to the following:
* <blockquote><pre>
* double energy = getNormalizationEnergy() + additionalEnergy;
* setNormalizationEnergy(energy);
* </pre></blockquote>
* <p>
* @param additionalEnergy must not be {@link Double#NaN}.
* @return the new normalization energy.
* @since 0.08
*/
public double addNormalizationEnergy(double additionalEnergy);
/**
* Computes the KL divergence of this message with respect to a
* another message of the same type. I.e. it should compute:
* <blockquote>
* D<sub>KL</sub>(P || Q)
* </blockquote>
* where P refers to the distribution described by this message, and Q to the distribution
* described by {@code that} message.
*
* @param that another message with a compatible type with this message. Typically this means
* that the class type must match. See specific subclass implementations for details.
* @return computed KL divergence in units of <A href="http://en.wikipedia.org/wiki/Nat_(unit)">nats</a>,
* @throws IllegalArgumentException if {@code that} is not compatible with {@code this}.
* @since 0.06
*/
public double computeKLDivergence(IParameterizedMessage that);
/**
* Return energy normalization constant based on the parameters.
* <p>
* This may be subtracted from the energy returned by the {@link #evalEnergy} method to normalize
* the value so that it represents a negative log probability.
* <p>
* If not explicitly set via {@link #setNormalizationEnergy}, this value will be computed based
* on the parameters. Implementations should ensure that any changes to the parameters will cause
* this value to be recomputed. Once computed, {@link #addNormalizationEnergy} may be used to
* add to the normalization energy value. This can be used to transmit normalization information
* from other parts of the graph.
* <p>
* @since 0.08
*/
public double getNormalizationEnergy();
/**
* Sets the energy normalization constant returned by {@link #getNormalizationEnergy()}.
* <p>
* @param energy is the new normalization energy. Setting to {@link Double#NaN}, will force
* value to be recomputed by {@link #getNormalizationEnergy()}.
* @since 0.08
*/
public void setNormalizationEnergy(double energy);
/**
* True if message corresponds to a single deterministic value with non-zero probability.
* <p>
* When true, {@link #toDeterministicValue(Domain)} will return a non-null value. Not all
* messages support parameter settings that will produce such a value. Ones that do include:
* <ul>
* <li>{@link DiscreteMessage}
* <li>{@link NormalParameters}
* <li>{@link MultivariateNormalParameters}
* </ul>
* <p>
* @since 0.08
*/
public boolean hasDeterministicValue();
/**
* True if parameters set to their "null" setting.
* @since 0.08
* @see #setNull()
*/
public boolean isNull();
/**
* Set parameters to value that will produce given deterministic value.
* <p>
* @param value
* @throws UnsupportedOperationException if message does not support deterministic parameter settings.
* @throws IllegalArgumentException if {@code value} is not supported data type
* @since 0.08
*/
public void setDeterministic(Value value);
/**
* Sets parameter values from another message.
* <p>
* @param other a message of the same type as this one (although specific subclasses
* could support other message types).
* @throws ClassCastException if {@code other} does not have supported class type
* @throws IllegalArgumentException if {@code other} is otherwise not compatible
* with this message
* @since 0.08
*/
public void setFrom(IParameterizedMessage other);
/**
* Sets message to its "null" form.
* <p>
* Sets parameters to values that will result in a zero energy for all (legal) inputs.
* <p>
* For exponential families, this will set the natural parameters to zero.
* <p>
* Usually, but not always, this means the parameters will be set to represent a weak uniform distribution.
* <p>
* @see #setUniform()
*/
public void setNull();
/**
* Sets parameters to approximate a uniform distribution.
* <p>
* @since 0.08
*/
public void setUniform();
/**
* Produces unique deterministic {@link Value} for message, if there is one.
* <p>
* If there is only one value with non-zero probability for the message parameters,
* this will return it, else null. This will only return non-null if {@link #hasDeterministicValue()}
* is true. The value it returns is the only one for which {@link #evalEnergy(Value)} returns
* finite energy.
* <p>
* <p>
* @param domain is the domain of the value.
* @since 0.08
*/
public @Nullable Value toDeterministicValue(Domain domain);
}