/*******************************************************************************
* 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.lp;
import java.io.PrintStream;
import net.jcip.annotations.Immutable;
import net.jcip.annotations.NotThreadSafe;
import org.eclipse.jdt.annotation.Nullable;
/**
* Represents a linear equality describing the constraint that the probabilities
* of a discrete random variable's values add up to one. The assumption is that the
* variable's possible values are represented by n consecutive variables px to px+n,
* so the equation is of the form:
* <p>
* px + ... + px+n = 1
* </p>
*/
@Immutable
public final class LPVariableConstraint extends IntegerEquation
{
@NotThreadSafe
public static class TermIterator implements IntegerEquation.TermIterator
{
private int _cur;
private int _last;
TermIterator(@Nullable LPVariableConstraint varConstraint)
{
reset(varConstraint);
}
/**
* Reset the iterator from a new variable constraint.
*/
public TermIterator reset(@Nullable LPVariableConstraint varConstraint)
{
if (varConstraint == null)
{
_cur = -1;
_last = -1;
}
else
{
_cur = varConstraint._firstLpVar - 1;
_last = _cur + varConstraint._size;
}
return this;
}
@Override
public boolean advance()
{
return ++_cur <= _last;
}
@Override
public int getVariable()
{
return _cur;
}
@Override
public int getCoefficient()
{
return 1;
}
}
private final LPDiscrete _svar;
private final int _firstLpVar;
private final int _size;
/*--------------
* Construction
*/
LPVariableConstraint(LPDiscrete svar)
{
_svar = svar;
_firstLpVar = svar.getLPVarIndex();
_size = svar.getNumberOfValidAssignments();
}
/*-------------------------
* IntegerEquation methods
*/
/**
* Returns non-null if this is a {@link LPVariableConstraint}.
*/
@Override
public LPVariableConstraint asVariableConstraint()
{
return this;
}
@Override
public int getCoefficient(int variable)
{
return hasCoefficient(variable) ? 1 : 0 ;
}
@Override
public int getRHS()
{
return 1;
}
@Override
public boolean hasCoefficient(int variable)
{
return variable >= _firstLpVar && variable < (_firstLpVar + _size);
}
@Override
public TermIterator getTerms()
{
return new TermIterator(this);
}
@Override
public int[] getVariables()
{
int[] vars = new int[_size];
for (int i = 0; i < _size; ++i)
{
vars[i] = _firstLpVar + i;
}
return vars;
}
@Override
public void print(PrintStream out)
{
_svar.printConstraintEquation(out);
}
@Override
public int size()
{
return _size;
}
/*------------------------------
* LPVariableConstraint methods
*/
/**
* Returns the Dimple solver variable for which this constraint was generated.
*/
public LPDiscrete getSolverVariable()
{
return _svar;
}
}