/*******************************************************************************
* 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.factorfunctions.core;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jdt.annotation.Nullable;
import com.analog.lyric.dimple.exceptions.DimpleException;
import com.analog.lyric.dimple.model.values.RealJointComponentValue;
import com.analog.lyric.dimple.model.values.RealJointValue;
import com.analog.lyric.dimple.model.values.Value;
import net.jcip.annotations.NotThreadSafe;
/**
* A unary real-joint factor function based on unary real factor functions for each dimension.
* <p>
* @since 0.08
* @author Christopher Barber
*/
@NotThreadSafe
public class UnaryJointRealFactorFunction extends UnaryFactorFunction
{
/*-------
* State
*/
private static final long serialVersionUID = 1L;
private final IUnaryFactorFunction[] _realFunctions;
/*--------------
* Construction
*/
public UnaryJointRealFactorFunction(IUnaryFactorFunction ... functions)
{
super((String)null);
_realFunctions = functions.clone();
}
protected UnaryJointRealFactorFunction(UnaryJointRealFactorFunction other)
{
super(other);
final int n = other._realFunctions.length;
_realFunctions = new IUnaryFactorFunction[n];
for (int i = _realFunctions.length; --i>=0;)
_realFunctions[i] = other._realFunctions[i].clone();
}
@Override
public UnaryFactorFunction clone()
{
return new UnaryJointRealFactorFunction(this);
}
/*------------------------------
* IUnaryFactorFunction methods
*/
@Override
public boolean objectEquals(@Nullable Object other)
{
if (this == other)
return true;
if (other instanceof UnaryJointRealFactorFunction)
{
UnaryJointRealFactorFunction that = (UnaryJointRealFactorFunction)other;
if (_realFunctions.length == that._realFunctions.length)
{
for (int i = _realFunctions.length; --i >= 0;)
{
if (!_realFunctions[i].objectEquals(that._realFunctions[i]))
{
return false;
}
}
return true;
}
}
return false;
}
@Override
public double evalEnergy(Value[] args)
{
double energy = 0;
final int n = _realFunctions.length;
RealJointComponentValue value = null;
outer:
for (Value arg : args)
{
if (!(arg instanceof RealJointValue))
{
}
RealJointValue values = (RealJointValue)arg;
if (values.size() != n)
throw new DimpleException("Dimension of variable does not equal to the dimension of joint function.");
if (value == null)
{
value = new RealJointComponentValue(values);
}
else
{
value.setRealJoint(values);
}
for (int i = 0; i < n; ++i)
{
value.setComponentIndex(i);
energy += _realFunctions[i].evalEnergy(value);
if (Double.isInfinite(energy))
break outer;
}
}
return energy;
}
/*---------------
* Local methods
*/
public final List<IUnaryFactorFunction> realFunctions()
{
return Arrays.asList(_realFunctions);
}
}