package org.societies.context.user.refinement.impl.bayesianLibrary.inference.structures.impl.bayeslets; import java.util.ArrayList; import java.util.Arrays; import org.societies.context.user.refinement.impl.bayesianLibrary.inference.solving.utils.Util; import org.societies.context.user.refinement.impl.bayesianLibrary.inference.structures.impl.Edge; import org.societies.context.user.refinement.impl.bayesianLibrary.inference.structures.impl.Node; import org.societies.context.user.refinement.impl.bayesianLibrary.inference.structures.impl.Probability; /** * @author gall_pa * */ public class NodeBL extends Node implements Comparable { private ArrayList incoming = new ArrayList(); private ArrayList outgoing = new ArrayList(); private ArrayList undirectedConnections = new ArrayList(); private CliqueBL parentClique = null; protected String name; protected String[] states; private ProbabilityDistributionBL prob; private ProbabilityDistributionBL marginalization; private ProbabilityDistributionBL likelihood; public NodeBL(String variableName, String[] states){ name = variableName; this.states = states; } /** * FOR USE IN CLIQUE; * */ public NodeBL(){ } /////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////Added by Pablo////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /** * This method combines the name of the node with the parameter string. * It is used to store the name of those nodes whose combination gives as result the current node. */ public void updateName(String string) { this.name=this.name+"+"+string; } /** * This method returns the position in the ArrayList containing all incoming edges of the incoming edge whose source is the parameter inputNode. * ////////////Removing influence of a common parent//////////// * @param inputNode * @return */ public int getIncomingEdgePosition(NodeBL inputNode){ int indexEdges=0; boolean founded=false; // Search the edge that connects inputNode with this one. while ((!founded)&&(indexEdges<this.incoming.size())){ Edge tempEdge=(Edge) this.incoming.get(indexEdges); if (tempEdge.getSource()==inputNode){ founded=true; }else{ indexEdges++; } } return indexEdges; } /** * This method returns the combination of states of all nodes places at the right side from the node placed in position nodeStatePosition * at the probabilities table from the node. * * @param inputNode * @param nodeStatePosition * @return */ public int getRightCases(int incomingEdgePosition){ int toReturn=1; int indexEdges=incomingEdgePosition+1; // Calculate the combination of states of nodes at the right side of inputNode. while (indexEdges<this.incoming.size()){ toReturn*=((Edge)this.incoming.get(indexEdges)).getSource().countStates(); indexEdges++; } return(toReturn); } /** * This method moves the incoming edge placed in statePos-1 * in the incoming edges arraylist to position 0 in that array. * * @param statePos Position of the incoming edge to be moved. */ public void moveIncomingEdgePosition(int edgePos){ ArrayList tempEdges=this.getIncoming(); Edge tempE=(Edge) tempEdges.get(edgePos); tempEdges.remove(edgePos); tempEdges.add(0, tempE); } /** * This method re-orders a probabilities table in order to have a certain variable listed just after the * variable that owns the table. * * @param input It is the table to be modified. * @param casesRight It is the combination of the different states the variable to be moved has on its right side. * In case the variable to be moved is at the last position (top right in the table), casesRight has to be assigned with * the value 1. * * @param statesCommonParent It is the number of different states of the variable to be moved. * @param statesCombinedNode It is the number of different states of the variable that owns the table. * */ /* This is an example of what this method does. * The table on the right side shows the result of moving variable C in the table on the left side. * Table Configuration Example Table After Moving C * A B C Probability A C B Probability * S1 S1 S1 P1 S1 S1 S1 P1 * S1 S1 S2 P2 S1 S1 S2 P3 * S1 S2 S1 P3 S1 S1 S3 P5 * S1 S2 S2 P4 S1 S2 S1 P2 * S1 S3 S1 P5 S1 S2 S2 P4 * S1 S3 S2 P6 S1 S2 S3 P6 * S2 S1 S1 P7 S2 S1 S1 P7 * S2 S1 S2 P8 S2 S1 S2 P9 * S2 S2 S1 P9 S2 S1 S3 P11 * S2 S2 S2 P10 S2 S2 S1 P8 * S2 S3 S1 P11 S2 S2 S2 P10 * S2 S3 S2 P12 S2 S2 S3 P12 */ public void moveVariableInTable(int casesRight, int statesCommonParent,int statesCombinedNode,int statePosition){ Probability newProbTable[]=new Probability[this.getProbTable().getProbabilities().length]; int totalCases=this.getProbTable().getProbabilities().length/statesCombinedNode; int index1=0; int jump=statesCommonParent*casesRight; boolean finished=false; int cont=0; int startingPosition=0; int index2=0; int cont2=0; while (!finished){ index1=0; while (index1<totalCases){ for (int j=0;j<casesRight;j++){ double tempProb=this.getProbTable().getProbabilities()[index2+j].getProbability(); Object[] newOrder = this.getProbTable().getProbabilities()[index2+j].getStates(); ArrayList tempArrayList=Util.arrayToArrayList(newOrder); String temp=(String) tempArrayList.get(statePosition); tempArrayList.remove(statePosition); tempArrayList.add(1, temp); newOrder=Util.convertToArrayOfStrings(tempArrayList); newProbTable[j+index1+startingPosition]=new Probability((String[]) newOrder,tempProb); } index1=index1+casesRight; index2=index2+jump; if ((index2)>=(totalCases*(1+cont))){ cont2++; index2=startingPosition+(cont2*casesRight); } } cont++; if (cont<statesCombinedNode){ startingPosition=startingPosition+totalCases; index2=startingPosition; cont2=0; }else{ finished=true; } } this.setProbDistribution(newProbTable); } /** * This method reorders the probability table of its owner taking Node node to the second position (just after the owner), * making the necessary changes to do it. * @param node */ public void reorderProbTable(NodeBL node){ int edgePos=this.getIncomingEdgePosition(node); int casesRight=this.getRightCases(edgePos); // Position in the table is (position in the incoming edges ArrayList +1), because the probabilities table also // includes its owner. this.moveVariableInTable(casesRight, node.countStates(), this.countStates(),edgePos+1); this.moveIncomingEdgePosition(edgePos); } ///////// Modification of method assignClique to consider node combined names /** * This method is equivalent to assignClique (see above) but it takes into consideration the possibility of having * combined nodes into the clique (whose names will be the combination of the names of the nodes that were combined) */ public CliqueBL assignCliqueCombinedNames(ArrayList cliques) { boolean fits=true; int indexFamily=0; ArrayList family = new ArrayList(Arrays.asList(getParticipants())); for (int i=0;i<cliques.size();i++) { fits=true; CliqueBL current = (CliqueBL)cliques.get(i); while ((fits)&&(indexFamily<family.size())){ String wanted= ((NodeBL)family.get(indexFamily)).getName(); if (current.getName().contains(wanted)){ indexFamily++; }else{ fits=false; indexFamily=0; } } if (fits){ parentClique = current; // System.out.println("Node: " + name + ", parent Clique: " + parentClique); return current; } } System.err.println("Node:assignClique(ArrayList): run through all cliques, but no parent one for Node "+this); return null; } public void setParentClique(CliqueBL input){ this.parentClique=input; } public String printMarginalizationWithoutParents(){ return(this.marginalization.toStringWithoutParents()); } public void setName(String input){ this.name=input; } /////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////Added by Sergio////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// /** * This method returns the correct length for a node Probability Distribution. * * @return correct length */ public int getCorrectProbDistrLength() { int testLength = countStates(); for (int i=0; i<incoming.size();i++){ Edge e = (Edge)incoming.get(i); testLength*=e.getSource().countStates(); } return testLength; } public NodeBL[] getParents() { NodeBL[] result = new NodeBL[incoming.size()]; for (int i=0;i<incoming.size();i++){ Node n = ((Edge) incoming.get(i)).getSource(); if (n instanceof NodeBL) result[i]= (NodeBL)n; } return result; } public ArrayList<NodeBL> getParentsArrayList() { ArrayList<NodeBL> result = new ArrayList<NodeBL>(); for (int i=0;i<incoming.size();i++){ Node n = ((Edge) incoming.get(i)).getSource(); if (n instanceof NodeBL) result.add((NodeBL)n); } return result; } public ArrayList<NodeBL> getParticipantsArrayList() { ArrayList<NodeBL> result = new ArrayList<NodeBL>(); result.add(this); for (int i=0;i<incoming.size();i++){ Node n = ((Edge) incoming.get(i)).getSource(); if (n instanceof NodeBL) result.add((NodeBL)n); } return result; } public ArrayList<NodeBL> getChildrensArrayList() { ArrayList<NodeBL> result = new ArrayList<NodeBL>(); for (int i=0;i<outgoing.size();i++){ Node n = ((Edge) outgoing.get(i)).getTarget(); if (n instanceof NodeBL) result.add((NodeBL)n); } return result; } public void setProbTable(ProbabilityDistributionBL prob) { this.prob = prob; } public void setLikelihood(ProbabilityDistributionBL likelihood) { this.likelihood = likelihood; } public ProbabilityDistributionBL getLikelihood() { return likelihood; } }