/*******************************************************************************
* 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.util.misc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import com.analog.lyric.dimple.factorfunctions.XorDelta;
import com.analog.lyric.dimple.factorfunctions.core.FactorFunction;
import com.analog.lyric.dimple.model.core.FactorGraph;
import com.analog.lyric.dimple.model.core.INameable;
import com.analog.lyric.dimple.model.factors.Factor;
import com.analog.lyric.dimple.model.variables.Discrete;
import com.analog.lyric.dimple.model.variables.Variable;
import com.analog.lyric.dimple.model.variables.VariableList;
import com.analog.lyric.dimple.schedulers.schedule.FixedSchedule;
import com.analog.lyric.dimple.schedulers.scheduleEntry.NodeScheduleEntry;
import com.analog.lyric.dimple.solvers.interfaces.IFactorGraphFactory;
public class Misc
{
/**
* A do-nothing function you can use for in-code conditional breakpoints when debugging.
* <p>
* Just set a method breakpoint on this method in Eclipse and leave it there and
* insert this
*/
public static void breakpoint()
{
}
public static Object [] nDimensionalArray2indicesAndValues(Object obj)
{
Object tmpObj = obj;
ArrayList<Integer> sizes = new ArrayList<Integer>();
int size = 1;
while (tmpObj.getClass().isArray())
{
if (tmpObj instanceof double [])
{
int sz = ((double[])tmpObj).length;
size*=sz;
sizes.add(sz);
break;
}
else
{
Object [] tmp = (Object[])tmpObj;
sizes.add(tmp.length);
size*=tmp.length;
tmpObj = tmp[0];
}
}
int [][] indices = new int[size][];
double [] values = new double[size];
int [] domainSizes = new int[sizes.size()];
for (int i = 0; i < domainSizes.length; i++)
domainSizes[i] = sizes.get(i);
IndexCounter ic = new IndexCounter(domainSizes);
int index = 0;
for ( int [] counter : ic)
{
tmpObj = obj;
int i = 0;
while (tmpObj.getClass().isArray())
{
if (tmpObj instanceof double[])
tmpObj = ((double[])tmpObj)[counter[i]];
else
tmpObj = ((Object[])tmpObj)[counter[i]];
i++;
}
final double value = (Double)tmpObj;
if (value != 0.0)
{
// Skip zero values
values[index] = value;
indices[index] = counter.clone();
index++;
}
}
if (index < size)
{
// Trim arrays if necessary
indices = Arrays.copyOf(indices, index);
values = Arrays.copyOf(values, index);
}
return new Object[]{indices,values};
}
public static long [] convertToIds(Collection<?> nameables)
{
//ArrayList<Integer> result = new ArrayList<Integer>();
long [] ids = new long[nameables.size()];
int i = 0;
for (Object n : nameables)
{
ids[i] = ((INameable)n).getGlobalId();
i++;
//result.add(((INameable)n).getId());
}
return ids;
}
public static FactorGraph makeXorGraphFromMatrix(byte[][] matrix, IFactorGraphFactory<?> solver)
{
return makeGraphFromMatrix(matrix,
new Double[]{0.0, 1.0},
new XorDelta(),
solver);
}
public static FactorGraph makeGraphFromMatrix(byte[][] matrix,
Object[] domain,
FactorFunction f,
IFactorGraphFactory<?> solver)
{
//Make all variables first
Discrete[] variables = new Discrete[matrix[0].length];
for(int i = 0; i < variables.length; ++i)
{
variables[i] = new Discrete(domain);
}
FactorGraph fg = new FactorGraph();
fg.setSolverFactory(solver);
fg.addVariables(variables);
//Now go function by function (row by row)
Object[] oneFactorsArgs = null;
for(int i = 0; i < matrix.length; ++i)
{
//###########################################################
//## Variables for this function
//###########################################################
//First build up array of the variable args to the function.
//count args for *this* factor (this row)
int numArgs = 0;
for(int j = 0; j < matrix[i].length; ++j)
{
if(matrix[i][j] != 0)
{
numArgs++;
}
}
//if num args is different than last iteration,
//make a new array with appropriate size
if(oneFactorsArgs == null ||
numArgs != oneFactorsArgs.length)
{
oneFactorsArgs = new Discrete[numArgs];
}
//Actually store the variable args
int nextArgIdx = 0;
for(int j = 0; j < matrix[i].length; ++j)
{
if(matrix[i][j] != 0)
{
oneFactorsArgs[nextArgIdx] = variables[j];
nextArgIdx++;
}
}
//###########################################################
//## The function
//###########################################################
fg.addFactor(f, oneFactorsArgs);
}
return fg;
}
static public double[][] getBeliefs(FactorGraph fg)
{
VariableList vs = fg.getVariablesFlat();
ArrayList<Variable> vbs = (ArrayList<Variable>)vs.values();
double[][] beliefs = new double[vbs.size()][];
for(int i = 0; i < vbs.size(); ++i)
{
beliefs[i] = ((Discrete)vbs.get(i)).getBelief();
}
return beliefs;
}
static public FixedSchedule nodeFloodingSchedule(FactorGraph fg)
{
FixedSchedule fs = new FixedSchedule(fg);
for(Variable vb : fg.getVariablesFlat().values())
{
fs.add(new NodeScheduleEntry(vb));
}
for(Factor f : fg.getNonGraphFactorsFlat().values())
{
fs.add(new NodeScheduleEntry(f));
}
return fs;
}
}