org.sosy_lab.cpachecker.pcc.strategy.partialcertificate.WeightedGraph.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.pcc.strategy.partialcertificate.WeightedGraph.java

Source

/*
 *  CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2016  Dirk Beyer
 *  All rights reserved.
 *
 *  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.
 *
 *
 *  CPAchecker web page:
 *    http://cpachecker.sosy-lab.org
 */
package org.sosy_lab.cpachecker.pcc.strategy.partialcertificate;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * Store and access a weighted graph structure
 */
public class WeightedGraph implements Iterable<WeightedNode> {

    private final int numNodes;
    private int totalNodeWeight;
    private final WeightedNode[] nodes;
    /**
     * store for each node its out- and incoming edges (each edge is stored twice)
     */
    private final Map<Integer, Set<WeightedEdge>> outgoingEdges;
    private final Map<Integer, Set<WeightedEdge>> incomingEdges;

    public WeightedGraph(PartialReachedSetDirectedGraph pGraph) {
        if (pGraph == null) {
            throw new IllegalArgumentException("Graph may not be null.");
        }
        totalNodeWeight = 0;
        numNodes = pGraph.getNumNodes();
        nodes = new WeightedNode[numNodes];
        outgoingEdges = new HashMap<>(numNodes);
        incomingEdges = new HashMap<>(numNodes);

        int weight = 1;
        ImmutableList<ImmutableList<Integer>> adjacencyList = pGraph.getAdjacencyList();

        for (int actualNode = 0; actualNode < numNodes; actualNode++) {
            WeightedNode start = new WeightedNode(actualNode, weight); //start node of newly found edges
            for (Integer successorNode : adjacencyList.get(actualNode)) { //iterate over successors of actual node
                WeightedNode end = new WeightedNode(successorNode, weight);
                WeightedEdge edge = new WeightedEdge(start, end, weight);
                addEdge(edge);
            }
        }
    }

    /**
     * Create empty graph, for successively construction
     * @param pNumNodes number of nodes it should contain
     */
    public WeightedGraph(int pNumNodes) {
        if (pNumNodes <= 0) {
            throw new IllegalArgumentException("Graph Size may not be 0.");
        }
        numNodes = pNumNodes;
        nodes = new WeightedNode[numNodes];
        outgoingEdges = new HashMap<>(numNodes);
        incomingEdges = new HashMap<>(numNodes);
    }

    /**
     * Inserts a new node into the graph structure. This method automatically updates the graph's total node-weight.
     * @param node node to be inserted into the structure
     */
    public void insertNode(WeightedNode node) {
        int nodeNum = node.getNodeNumber();
        int nodeWeight = node.getWeight();
        if (nodes[nodeNum] != null) {//The node stored before is deleted, so its weight needs to be subtracted
            totalNodeWeight -= nodes[nodeNum].getWeight();
        }
        nodes[nodeNum] = node;
        totalNodeWeight += nodeWeight;

    }

    /**
     * Insert an edge into structure. If edge between both end-nodes already exists, the edge's weight is updated
     * @param edge edge to be inserted; corresponding nodes' weights are changed according to the edge's nodes
     */
    public void addEdge(WeightedEdge edge) {
        WeightedNode start = edge.getStartNode();
        int startNumber = start.getNodeNumber();
        WeightedNode end = edge.getEndNode();
        int endNumber = end.getNodeNumber();
        insertNode(start);
        insertNode(end);
        boolean edgeExisted = false;

        //Check if for the end node already an incoming edge from start node existed
        //==> if yes: change the edges weight
        if (!incomingEdges.containsKey(endNumber)) {//neither start nor end-node had edge until now
            incomingEdges.put(endNumber, new HashSet<WeightedEdge>());
        }
        if (!outgoingEdges.containsKey(startNumber)) {//neither start nor end-node had edge until now
            outgoingEdges.put(startNumber, new HashSet<WeightedEdge>());
        }

        if (!incomingEdges.get(endNumber).isEmpty() && !outgoingEdges.get(startNumber).isEmpty()) {//check if edge between nodes already existed
            Set<WeightedEdge> inEdges = incomingEdges.get(endNumber); //incoming edges for endNode are updated
            for (WeightedEdge inEdge : inEdges) {
                if (inEdge.getStartNode().getNodeNumber() == startNumber) {//edge with same end- and start-node
                    inEdge.addWeight(edge.getWeight()); //This updates the edge in outgoing edges as well
                    edgeExisted = true;
                    break;
                }
            }
        }

        if (!edgeExisted) {
            incomingEdges.get(endNumber).add(edge);
            outgoingEdges.get(startNumber).add(edge);
        }

    }

    /**
     * Insert a whole set of weighted edges into the graph structure
     * @param edges the edges to be inserted
     */
    public void addEdges(Set<WeightedEdge> edges) {
        for (WeightedEdge edge : edges) {
            addEdge(edge);
        }
    }

    public Iterable<WeightedNode> randomIterator() {
        return new Iterable<WeightedNode>() {
            @Override
            public Iterator<WeightedNode> iterator() {
                return new WeightedGraphRandomIterator(WeightedGraph.this);
            }
        };
    }

    /**
     * Get a node via its number, if it is contained in the graph
     * @param node the node number
     * @return The weighted node, or null, if not contained in graph
     */
    @Nullable
    public WeightedNode getNode(int node) {
        return nodes[node];
    }

    public Set<WeightedNode> getPredecessors(int node) {
        Set<WeightedNode> predecessors = new HashSet<>();
        if (incomingEdges.get(node) != null) {
            for (WeightedEdge e : incomingEdges.get(node)) {
                predecessors.add(e.getStartNode());
            }
        }
        return predecessors;
    }

    public Set<WeightedNode> getPredecessors(WeightedNode node) {
        return getPredecessors(node.getNodeNumber());
    }

    public Set<WeightedNode> getSuccessors(int node) {
        Set<WeightedNode> successors = new HashSet<>();
        if (outgoingEdges.get(node) != null) {
            for (WeightedEdge e : outgoingEdges.get(node)) {
                successors.add(e.getEndNode());
            }
        }
        return successors;
    }

    public Set<WeightedNode> getSuccessors(WeightedNode node) {
        return getSuccessors(node.getNodeNumber());
    }

    public Set<Integer> getIntSuccessors(int node) {
        Set<Integer> successors = new HashSet<>();
        if (outgoingEdges.get(node) != null) {
            for (WeightedEdge e : outgoingEdges.get(node)) {
                successors.add(e.getEndNode().getNodeNumber());
            }
        }
        return successors;
    }

    public Set<Integer> getIntSuccessors(WeightedNode node) {
        return getIntSuccessors(node.getNodeNumber());

    }

    public Set<WeightedNode> getNeighbors(WeightedNode node) {
        return getNeighbors(node.getNodeNumber());
    }

    public Set<WeightedNode> getNeighbors(int node) {
        Set<WeightedNode> neighbors = getSuccessors(node);
        neighbors.addAll(getPredecessors(node));
        return neighbors;
    }

    static public int computeWeight(Set<WeightedNode> nodes) {
        int weight = 0;
        for (WeightedNode node : nodes) {
            weight += node.getWeight();
        }
        return weight;
    }

    static public int computeWeight(Set<Integer> nodes, WeightedGraph wGraph) {
        int weight = 0;
        for (Integer node : nodes) {
            weight += wGraph.getNode(node).getWeight();
        }
        return weight;
    }

    public int getNumNodes() {
        return numNodes;
    }

    public Set<WeightedEdge> getOutgoingEdges(WeightedNode node) {
        return getOutgoingEdges(node.getNodeNumber());
    }

    public Set<WeightedEdge> getOutgoingEdges(int node) {
        Set<WeightedEdge> edges = outgoingEdges.get(node);
        if (edges != null) {
            return edges;
        } else {
            return new HashSet<>(0);
        }
    }

    public Set<WeightedEdge> getIncomingEdges(WeightedNode node) {
        return getIncomingEdges(node.getNodeNumber());
    }

    public Set<WeightedEdge> getIncomingEdges(int node) {
        Set<WeightedEdge> edges = incomingEdges.get(node);
        if (edges != null) {
            return edges;
        } else {
            return new HashSet<>(0);
        }
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();

        for (int node = 0; node < numNodes; node++) {
            if (nodes[node] == null) {
                continue;
            }
            int nodeWeight = getNode(node).getWeight();
            s.append(node).append("(W:").append(nodeWeight).append("):");
            for (WeightedEdge edge : this.getOutgoingEdges(node)) {
                s.append("--").append(edge.getWeight()).append("-->");
                s.append(edge.getEndNode().getNodeNumber());
            }
            s.append("|| \t");
        }
        return s.toString();
    }

    /**
     * Compute sum of all contained nodes' weights of
     * @return the total node weight of graph
     */
    public int getTotalNodeWeight() {
        return totalNodeWeight;
    }

    /**
     * Iterates in increasing node-number order over all nodes contained in graph
     */
    @Override
    public Iterator<WeightedNode> iterator() {
        return Iterators.forArray(nodes);
    }

    /**
     * Computes a partition's weight, if graph is split up into numPartitions equal parts
     * @param numPartitions The number of partitions to be created
     * @return maximal weight of the partitions
     */
    public int computePartitionLoad(int numPartitions) {
        return this.getTotalNodeWeight() / numPartitions + 1;
    }

    /**
     * Generates a partition consisting of all nodes
     * @return All nodes in one partition
     */
    public List<Set<Integer>> getGraphAsOnePartition() {
        List<Set<Integer>> partitioning = new ArrayList<>(1);
        Set<Integer> partition = new HashSet<>(numNodes);
        for (WeightedNode node : nodes) {
            partition.add(node.getNodeNumber());
        }
        partitioning.add(partition);
        return partitioning;
    }

    /**
     * Generates a partitioning, in which each node has its own partition.
     * If there are more partitions needed, than nodes in graph exist, empty partitions are added
     * @param numPartitions number of Partitions to be at least created. if numNodes<numPartitions==> empty partitions necessary
     * @return A partitioning consisting of numNodes partitions
     */
    public List<Set<Integer>> getNodesSeperatelyPartitioned(int numPartitions) {
        List<Set<Integer>> partitioning = new ArrayList<>(numNodes);
        int currentPartition = 0;
        for (WeightedNode node : nodes) {
            Set<Integer> partition = new HashSet<>(1);
            partition.add(node.getNodeNumber());
            partitioning.add(partition);
            currentPartition++;
        }
        while (currentPartition < numPartitions) {
            partitioning.add(new HashSet<Integer>(1));
            currentPartition++;
        }
        return partitioning;
    }

}