/******************************************************************************* * 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); }