/*******************************************************************************
* 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.dimple.matlabproxy;
import static java.util.Objects.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import org.eclipse.jdt.annotation.Nullable;
import com.analog.lyric.dimple.exceptions.DimpleException;
import com.analog.lyric.dimple.model.core.Node;
import com.analog.lyric.dimple.model.core.Port;
import com.analog.lyric.dimple.options.DimpleOptionHolder;
import com.analog.lyric.dimple.solvers.interfaces.ISolverNode;
import com.analog.lyric.util.misc.Matlab;
@Matlab
public class PNodeVector extends POptionHolder
{
/*
* State
*/
private Node [] _nodes = new Node[0];
/*--------------
* Construction
*/
public PNodeVector() {}
public PNodeVector(Node [] nodes)
{
_nodes = nodes.clone();
}
/*-----------------
* PObject methods
*/
@Override
public Node[] getDelegate()
{
return _nodes;
}
@Override
public boolean isVector()
{
return true;
}
/*-----------------------
* POptionHolder methods
*/
@Override
public final DimpleOptionHolder getOptionHolder(int i)
{
return _nodes[i];
}
/*---------------------
* PNodeVector methods
*/
public void setNodes(Node [] nodes)
{
_nodes = nodes;
}
public PNodeVector concat(Object [] varVectors, int [] varVectorIndices, int [] varIndices)
{
return concat(PHelpers.convertObjectArrayToNodeVectorArray(varVectors),varVectorIndices,varIndices);
}
public PNodeVector concat(PNodeVector [] varVectors, int [] varVectorIndices, int [] varIndices)
{
Node [] nodes = new Node[varIndices.length];
for (int i = 0; i < varIndices.length; i++)
{
nodes[i] = varVectors[varVectorIndices[i]]._nodes[varIndices[i]];
}
return createNodeVector(nodes);
}
public PNodeVector createNodeVector(Node [] nodes)
{
return new PNodeVector(nodes);
}
public PNodeVector concat(Object [] varVectors)
{
return concat(PHelpers.convertObjectArrayToNodeVectorArray(varVectors));
}
public PNodeVector concat(PNodeVector [] varVectors)
{
ArrayList<Node> variables = new ArrayList<Node>();
for (int i = 0; i < varVectors.length; i++)
{
for (int j =0; j < varVectors[i].size(); j++)
{
variables.add(varVectors[i]._nodes[j]);
}
}
Node [] retval = new Node[variables.size()];
variables.toArray(retval);
return createNodeVector(retval);
}
public void replace(PNodeVector vector, int [] indices)
{
for (int i = 0; i < indices.length; i++)
{
_nodes[indices[i]] = vector._nodes[i];
}
}
public PNodeVector getSlice(int [] indices)
{
Node [] variables = new Node[indices.length];
for (int i = 0; i < indices.length; i++)
{
variables[i] = _nodes[indices[i]];
}
return createNodeVector(variables);
}
public Node getModelerNode(int index)
{
return _nodes[index];
}
public Node[] getModelerNodes()
{
return _nodes;
}
@Override
public int size()
{
return _nodes.length;
}
public long [] getIds()
{
long [] ids = new long[_nodes.length];
for (int i = 0; i < ids.length; i++)
ids[i] = _nodes[i].getGlobalId();
return ids;
}
public double getScore()
{
double sum = 0;
for (int i = 0; i < _nodes.length; i++)
sum += _nodes[i].getScore();
return sum;
}
public double getBetheEntropy()
{
double sum = 0;
for (int i = 0; i < _nodes.length; i++)
sum += _nodes[i].getBetheEntropy();
return sum;
}
public double getInternalEnergy()
{
double sum = 0;
for (int i = 0; i < _nodes.length; i++)
sum += _nodes[i].getInternalEnergy();
return sum;
}
public void setName(String name)
{
// FIXME - I don't think this is correct if there is more than one variable unless they
// are from differnent graphs.
for (Node variable : _nodes)
variable.setName(name);
}
public void setNames(String baseName)
{
for(int i = 0; i < _nodes.length; ++i)
{
// FIXME - the _vv part is annoying. Is this really what the user wants?
_nodes[i].setName(String.format("%s_vv%d", baseName, i));
}
}
public void setLabel(String name)
{
for (Node variable : _nodes)
variable.setLabel(name);
}
public String [] getNames()
{
String [] retval = new String[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getName();
}
return retval;
}
public String [] getQualifiedNames()
{
String [] retval = new String[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getQualifiedName();
}
return retval;
}
public String [] getExplicitNames()
{
String [] retval = new String[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getExplicitName();
}
return retval;
}
public String [] getNamesForPrint()
{
String [] retval = new String[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getLabel();
}
return retval;
}
public String [] getQualifiedNamesForPrint()
{
String [] retval = new String[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getQualifiedLabel();
}
return retval;
}
public UUID [] getUUIDs()
{
UUID [] retval = new UUID[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getUUID();
}
return retval;
}
@Deprecated
public int getPortNum(PNodeVector nodeVector)
{
Node thisNode = PHelpers.convertToNode(this);
Node n = PHelpers.convertToNode(nodeVector);
int num = thisNode.findSibling(n);
return num;
}
public Port [] getPorts(int index)
{
Port [] ports;
Collection<Port> alports = getModelerNode(index).getPorts();
ports = new Port[alports.size()];
alports.toArray(ports);
return ports;
}
public void update()
{
for (int i = 0; i < _nodes.length; i++)
_nodes[i].update();
}
public void updateEdge(PNodeVector nodeVector)
{
updateEdge(getPortNum(nodeVector));
}
public void updateEdge(int portNum)
{
for (int i = 0; i < _nodes.length; i++)
_nodes[i].updateEdge(portNum);
}
public @Nullable ISolverNode getSolver(int index)
{
Node n = getModelerNode(index);
return n.getSolver();
}
public ISolverNode [] getSolvers(int [] indices)
{
ISolverNode [] retval = new ISolverNode[indices.length];
for (int i = 0; i < indices.length; i++)
retval[i] = getSolver(indices[i]);
return retval;
}
public ISolverNode [] getSolvers()
{
ISolverNode[] retval = new ISolverNode[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
retval[i] = _nodes[i].getSolver();
}
return retval;
}
public void invokeSolverMethod(String methodName,Object ... args)
{
ISolverNode sn = requireNonNull(_nodes[0].getSolver());
Method [] ms = sn.getClass().getMethods();
for (Method m : ms)
{
if (m.getName().equals(methodName))
{
boolean keepTrying = false;
for (int i = 0; i < _nodes.length; i++)
{
try
{
m.invoke(_nodes[i].getSolver(),args);
}
catch (IllegalArgumentException e) {keepTrying = true;} // Might be another version with different signature
catch (Exception e)
{
throw new DimpleException(e);
}
}
if (!keepTrying) return;
}
}
throw new DimpleException("method not found");
}
public Object [] invokeSolverMethodWithReturnValue(String methodName,Object ... args)
{
ISolverNode sn = requireNonNull(_nodes[0].getSolver());
Method [] ms = sn.getClass().getMethods();
for (Method m : ms)
{
if (m.getName().equals(methodName))
{
boolean keepTrying = false;
Object [] retval = new Object[_nodes.length];
for (int i = 0; i < _nodes.length; i++)
{
try
{
retval[i] = m.invoke(_nodes[i].getSolver(),args);
}
catch (IllegalArgumentException e) {keepTrying = true;} // Might be another version with different signature
catch (Exception e)
{
throw new DimpleException(e);
}
}
if (!keepTrying) return retval;
}
}
throw new DimpleException("method not found");
}
}