it.uniroma2.sag.kelp.data.representation.graph.DirectedGraphRepresentation.java Source code

Java tutorial

Introduction

Here is the source code for it.uniroma2.sag.kelp.data.representation.graph.DirectedGraphRepresentation.java

Source

/*
 * Copyright 2014-2015 Simone Filice and Giuseppe Castellucci and Danilo Croce and Roberto Basili
 * and Giovanni Da San Martino and Alessandro Moschitti
 * 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 it.uniroma2.sag.kelp.data.representation.graph;

import gnu.trove.map.hash.TIntIntHashMap;
import it.uniroma2.sag.kelp.data.representation.Representation;
import it.uniroma2.sag.kelp.data.representation.structure.StructureElement;
import it.uniroma2.sag.kelp.data.representation.structure.StructureElementFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeName;

/**
 * This class implements a directed Graph representation. 
 * 
 * 
 * @author Giovanni Da San Martino
 *
 */
@JsonTypeName("G")
public class DirectedGraphRepresentation implements Representation {

    private Logger logger = LoggerFactory.getLogger(DirectedGraphRepresentation.class);

    private static final String NODE_SEPARATOR = "&&";
    public static final String EDGE_SEPARATOR = "&&";
    private static final String NODE_EDGE_SEPARATOR = "%%";
    private static final long serialVersionUID = 5688462570989530911L;

    protected List<GraphNode> nodes;
    protected TIntIntHashMap nodesIdToGraphObjs;
    protected List<NodeDistance> nodesDistances = null;

    public DirectedGraphRepresentation() {
        this.nodes = new ArrayList<GraphNode>();
        this.nodesIdToGraphObjs = new TIntIntHashMap(0, 0.5f, -1, -1);
    }

    @Override //required by Representation
    public String getTextFromData() {
        StringBuilder graphString = new StringBuilder();
        String tmpEdgeString;
        for (GraphNode g : this.nodes) { //TODO: order nodes by Id
            graphString.append(g.toString());
            graphString.append(NODE_SEPARATOR);
        }
        if (graphString.length() == 0) {
            System.out.println("Empty Graph!!");
            return "";
        }
        graphString.setLength(graphString.length() - NODE_SEPARATOR.length()); //delete last separator
        graphString.append(NODE_EDGE_SEPARATOR);
        for (GraphNode g : this.nodes) {
            tmpEdgeString = g.edgesToString();
            if (tmpEdgeString.length() > 0) {
                graphString.append(tmpEdgeString + EDGE_SEPARATOR);
            }
        }
        return graphString.toString();
    }

    @Override //required by Representation
    public void setDataFromText(String graphString) throws Exception {
        String inputString = graphString.trim();
        String[] nodeList = null;
        String[] edgeList = null;
        if (inputString.contains(NODE_EDGE_SEPARATOR)) {
            String[] resultString = inputString.split(NODE_EDGE_SEPARATOR);
            nodeList = resultString[0].split(NODE_SEPARATOR);
            edgeList = resultString[1].split(EDGE_SEPARATOR);
        } else { //no edges are present
            nodeList = inputString.split(NODE_SEPARATOR);
        }
        //this.InitNodesData(nodeList.length);
        for (String nodeS : nodeList) {
            //read a number, discard following space, read the rest as StructureElement
            String[] res = nodeS.split(" ");
            Integer nodeId = Integer.parseInt(res[0]);
            StructureElement content = StructureElementFactory.getInstance().parseStructureElement(res[1]);
            this.addNode(nodeId, content);
        }
        if (edgeList != null) {
            for (String edgeS : edgeList) {
                String[] res = edgeS.split(" ");
                Integer firstNodeId = Integer.parseInt(res[0]);
                Integer secondNodeId = Integer.parseInt(res[1]);
                this.addEdge(firstNodeId, secondNodeId);
            }
        }
    }

    /**
     * Given a node id, return the corresponding GraphNode object
     * @param Id
     * @return the graphNode
     */
    public GraphNode getNodeFromID(Integer Id) {

        Integer arrayPosition = this.nodesIdToGraphObjs.get(Id);
        if (arrayPosition == -1) {
            System.out.print("Node ID not Found! ");
            System.out.println(Id);
            System.exit(0);
        }
        return this.nodes.get(arrayPosition);
    }

    /**
     * Adds a node whose id is <code>nodeId</code> and whose content is <code>nodeContent</code>
     * 
     * @param nodeId the id of the node to be added
     * @param nodeContent the content of the node to be added
     */
    public void addNode(Integer nodeId, StructureElement nodeContent) {

        GraphNode v = new GraphNode(nodeId, nodeContent);
        this.nodes.add(v);
        this.nodesIdToGraphObjs.put(nodeId, this.nodes.size() - 1);
    }

    /**
     * Adds an edge between the nodes whose IDs are <code>firstNodeId</code>
     * and <code>secondNodeId</code>
     * 
     * @param firstNodeId the id of the first node
     * @param secondNodeId the id of the second node
     */
    public void addEdge(Integer firstNodeId, Integer secondNodeId) {

        this.getNodeFromID(firstNodeId).addOutgoingEdge(this.getNodeFromID(secondNodeId));
        //this.getNodeFromID(secondNodeId).addIncomingEdge(this.getNodeFromID(firstNodeId));//set a flag to control whether incoming edges are actually added?
    }

    /**
     * Returns a list containing all the nodes in this graph
     * 
     * @return a list of GraphNode objects
     */
    @JsonIgnore
    public List<GraphNode> getNodeList() {
        return this.nodes;
    }

    /**
     * Returns the number of nodes in the graph.
     * @return an int representing the number of nodes of the graph
     */
    @JsonIgnore
    public int getNumberOfNodes() {
        return this.nodes.size();
    }

    /*   *//**
           * Compute the distances between a given node and all other nodes in the graph.
           * The results are stored into the field <code>nodesDistancesMap</code> (an hash map). 
           * In order to access or modify the hash map use the methods <code>setNodeDistance()</code>
           * and <code>getNodeDistance()</code>
           *//*
              public int[] computeDistancesFromNode(int nodeIndex) {
              this.nodesDistances = new ArrayList<NodeDistance>(0);
              int nnodes = this.getNumberOfNodes();
              int[] tmpNodeDistances = new int[nnodes];
              ArrayList<Integer> stack = new ArrayList<Integer>();
              int j, arrayPosition, depth;
              for(j=0; j<nnodes; j++) {
                  tmpNodeDistances[j] = Integer.MAX_VALUE;
               }
               stack.add(nodeIndex);
               depth = 0;
               while(stack.size()>0) {
                  j=stack.remove(0);
                  depth++;
                  for(GraphNode v : this.nodes.get(j).getNeighbours()) {
                     arrayPosition = this.nodesIdToGraphObjs.get(v.getId());
                     if(depth < tmpNodeDistances[arrayPosition]) {
                        tmpNodeDistances[arrayPosition] = depth;
                        stack.add(arrayPosition);
                        //System.out.println("SP: adding pair (" + i + ", " + arrayPosition + ") -> " + depth);
                     }
                  }
              }
              return tmpNodeDistances;      
              }
              */

    /**
     * Compute the distances between all pairs of nodes in the graph.
     * The results are stored into the field <code>nodesDistancesMap</code> (an hash map). 
     * In order to access or modify the hash map use the methods <code>setNodeDistance()</code>
     * and <code>getNodeDistance()</code>
     */
    private void computeNodeDistances() {
        this.nodesDistances = new ArrayList<NodeDistance>(0);
        int nnodes = this.getNumberOfNodes();
        int[] tmpNodeDistances = new int[nnodes];
        ArrayList<Integer> stack = new ArrayList<Integer>();
        int j, arrayPosition, depth;
        for (int i = 0; i < nnodes; i++) {
            for (j = 0; j < nnodes; j++) {
                tmpNodeDistances[j] = Integer.MAX_VALUE;
            }
            stack.add(i);
            depth = 0;
            while (stack.size() > 0) {
                j = stack.remove(0);
                depth++;
                for (GraphNode v : this.nodes.get(j).getNeighbours()) {
                    arrayPosition = this.nodesIdToGraphObjs.get(v.getId());
                    if (depth < tmpNodeDistances[arrayPosition]) {
                        tmpNodeDistances[arrayPosition] = depth;
                        stack.add(arrayPosition);
                        //System.out.println("SP: adding pair (" + i + ", " + arrayPosition + ") -> " + depth);
                    }
                }
            }
            for (j = 0; j < nnodes; j++) {
                depth = tmpNodeDistances[j];
                if (depth < Integer.MAX_VALUE) {
                    this.setNodesDistance(i, j, (float) tmpNodeDistances[j]);
                }
            }
        }

        Collections.sort(this.nodesDistances);

    }

    /**
     * Returns the list of NodeDistance Objects
     * @return
     */
    @JsonIgnore
    public List<NodeDistance> getNodeDistances() {
        if (this.nodesDistances == null) {
            computeNodeDistances();
        }
        return this.nodesDistances;
    }

    /**
     * Encode the distance between two nodes in the field nodesDistancesMap  
     * @param firstNodeIndex, index of the first node of the pair in <code>nodes</code>
     * @param secondNodeIndex, index of the second node of the pair in <code>nodes</code>
     * @param distance, the distance between the two nodes
     */
    private void setNodesDistance(int firstNodeIndex, int secondNodeIndex, float distance) {
        NodeDistance nodeDistance = new NodeDistance(this.nodes.get(firstNodeIndex),
                this.nodes.get(secondNodeIndex), distance);

        this.nodesDistances.add(nodeDistance);
    }

    @Override
    public boolean isCompatible(Representation rep) {
        if (!(rep instanceof DirectedGraphRepresentation)) {
            logger.error("incompatible representations: " + this.getClass().getSimpleName() + " vs "
                    + rep.getClass().getSimpleName());
            return false;
        }
        return true;
    }

    //   /**
    //    * Given a pair of nodes, return the, previously computed, distance between them
    //    * @param nodePairKey, long encoding the node-pair
    //    * @return the distance between the two nodes
    //    */
    //   public float getNodePairDistance(long nodePairKey) {
    //      if(this.nodesDistancesMap==null) {
    //         this.computeNodeDistances();
    //      }
    //      return this.nodesDistancesMap.get(nodePairKey);
    //      //return this.nodesDistancesMap.get(this.getNodePairKey(firstNodeIndex, secondNodeIndex));
    //   }

    //   /**
    //    * Given a pair of node indices, returns the corresponding key in the hash map <code>nodesDistancesMap</code> 
    //    * @param firstNodeIndex, index of the first node of the pair in <code>nodes</code>
    //    * @param secondNodeIndex, index of the second node of the pair in <code>nodes</code>
    //    * @return the key related to the node pair in <code>nodesDistancesMap</code>
    //    */
    //   private long getNodePairKey(int firstNodeIndex, int secondNodeIndex) {
    //      if (firstNodeIndex <= secondNodeIndex) {
    //         return (long)firstNodeIndex << 32 | secondNodeIndex & 0xFFFFFFFFL;
    //      }else{
    //         return (long)secondNodeIndex << 32 | firstNodeIndex & 0xFFFFFFFFL;
    //      }
    //   }

}