Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
soot.jimple.toolkits.annotation.arraycheck.WeightedDirectedSparseGraph Maven / Gradle / Ivy
/* Soot - a J*va Optimization Framework
* Copyright (C) 2000 Feng Qian
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.jimple.toolkits.annotation.arraycheck;
import java.util.*;
class WeightedDirectedSparseGraph
{
private boolean isUnknown;
/* The graph is in linked list structure. */
private Hashtable> sources = new Hashtable>();
/* vertex set, may contain superious nodes. */
private HashSet vertexes = new HashSet();
public WeightedDirectedSparseGraph(HashSet vertexset)
{
this(vertexset, false);
}
public WeightedDirectedSparseGraph(HashSet vertexset, boolean isTop)
{
this.vertexes = vertexset;
this.isUnknown = !isTop;
}
public void setTop()
{
this.isUnknown = false;
this.sources.clear();
}
public HashSet getVertexes()
{
return this.vertexes;
}
public void setVertexes(HashSet newset)
{
this.vertexes = newset;
this.sources.clear();
}
/**
* Add an edge with weight to the graph
*/
public void addEdge(Object from, Object to, int w)
{
if (this.isUnknown)
throw new RuntimeException("Unknown graph can not have edges");
Hashtable targets = sources.get(from);
if (targets == null)
{
/* a new node was added to the graph */
targets = new Hashtable();
sources.put(from, targets);
}
IntContainer weight = targets.get(to);
if (weight == null)
{
weight = new IntContainer(w);
targets.put(to, weight);
}
else
{
if (weight.value > w)
weight.value = w;
}
}
/** addMutualEdge adds bi-direct edges between two nodes.
* for example,
* i = j + 1;
* generates two directed edges.
* one from j to i with weight 1, another from i to j with weight -1
*/
public void addMutualEdges(Object from, Object to, int weight)
{
addEdge(from, to, weight);
addEdge(to, from, -weight);
}
/* removeEdge removes all edges from source to target.
*/
public void removeEdge(Object from, Object to)
{
Hashtable targets = sources.get(from);
if (targets == null)
return;
targets.remove(to);
if (targets.size() == 0)
{
sources.remove(from);
}
}
public boolean hasEdge(Object from, Object to)
{
Hashtable targets = sources.get(from);
if (targets == null)
return false;
return targets.containsKey(to);
}
/* return back the weight of the edge from source to target */
public int edgeWeight(Object from, Object to)
{
Hashtable targets = sources.get(from);
if (targets == null)
throw new RuntimeException("No such edge ("+from+" ,"+to+") exists.");
IntContainer weight = (IntContainer)targets.get(to);
if (weight == null)
throw new RuntimeException("No such edge ("+from+", "+to+") exists.");
return weight.value;
}
/* If other graph is unknown, keep current one.
* If current graph is unknown, copy the other.
And if both are not unknown, union each edge.
*/
public void unionSelf(WeightedDirectedSparseGraph other)
{
if (other == null)
return;
WeightedDirectedSparseGraph othergraph =
other;
if (othergraph.isUnknown)
return;
if (this.isUnknown)
addAll(othergraph);
List sourceList = new ArrayList(this.sources.keySet());
Iterator firstSrcIt = sourceList.iterator();
while (firstSrcIt.hasNext())
{
Object srcKey = firstSrcIt.next();
Hashtable src1 = this.sources.get(srcKey);
Hashtable src2 = othergraph.sources.get(srcKey);
/* other is unbounded */
if (src2 == null)
{
this.sources.remove(srcKey);
continue;
}
List targetList = new ArrayList(src1.keySet());
Iterator targetIt = targetList.iterator();
while (targetIt.hasNext())
{
Object target = targetIt.next();
IntContainer w1 = (IntContainer)src1.get(target);
IntContainer w2 = (IntContainer)src2.get(target);
/* other is unbounded */
if (w2 == null)
{
src1.remove(target);
continue;
}
if (w2.value > w1.value)
w1.value = w2.value;
}
if (src1.size() == 0)
this.sources.remove(srcKey);
}
}
/* it was used to compare with former graph, if the edge weight is increasing,
the edge is removed (unlimited distance).
*/
public void widenEdges(WeightedDirectedSparseGraph othergraph)
{
WeightedDirectedSparseGraph other =
othergraph;
if (other.isUnknown)
return;
Hashtable> othersources = other.sources;
List sourceList = new ArrayList(this.sources.keySet());
Iterator srcIt = sourceList.iterator();
while (srcIt.hasNext())
{
Object src = srcIt.next();
Hashtable thistargets = this.sources.get(src);
Hashtable othertargets = othersources.get(src);
/* the former is unbounded */
if (othertargets == null)
{
this.sources.remove(src);
continue;
}
List targetList = new ArrayList(thistargets.keySet());
Iterator targetIt = targetList.iterator();
while (targetIt.hasNext())
{
Object target = targetIt.next();
IntContainer thisweight = (IntContainer)thistargets.get(target);
IntContainer otherweight = (IntContainer)othertargets.get(target);
/* the former edge is unbounded. */
if (otherweight == null)
{
thistargets.remove(target);
continue;
}
if (thisweight.value > otherweight.value)
{
thistargets.remove(target);
}
}
if (thistargets.size()==0)
this.sources.remove(src);
}
}
/* It is necessary to prune the graph to the shortest path. */
/* it could be replaced by a ShortestPathGraph */
/* kill a node. */
public void killNode(Object tokill)
{
if (!this.vertexes.contains(tokill))
return;
this.makeShortestPathGraph();
List sourceList = new ArrayList(sources.keySet());
Iterator srcIt = sourceList.iterator();
while (srcIt.hasNext())
{
Object src = srcIt.next();
Hashtable targets = sources.get(src);
/* delete the in edge */
targets.remove(tokill);
if (targets.size() == 0)
sources.remove(src);
}
sources.remove(tokill);
this.makeShortestPathGraph();
}
/* when met i=i+c, it is necessary to update the weight of in and out edges */
public void updateWeight(Object which, int c)
{
/* for the in edge, the weight + c. for the out edge, the weight - c */
Iterator srcIt = sources.keySet().iterator();
while (srcIt.hasNext())
{
Object from = srcIt.next();
Hashtable targets = sources.get(from);
IntContainer weight = (IntContainer)targets.get(which);
if (weight != null)
weight.value += c;
}
/* update out edges */
Hashtable toset = sources.get(which);
if (toset == null)
return;
Iterator toIt = toset.keySet().iterator();
while (toIt.hasNext())
{
Object to = toIt.next();
IntContainer weight = (IntContainer)toset.get(to);
weight.value -= c;
}
}
public void clear()
{
sources.clear();
}
public void replaceAllEdges(WeightedDirectedSparseGraph other)
{
this.isUnknown = other.isUnknown;
this.vertexes = other.vertexes;
this.sources = other.sources;
}
/* add edges that belong to this vertex set */
public void addBoundedAll(WeightedDirectedSparseGraph another)
{
this.isUnknown = another.isUnknown;
Hashtable> othersources = another.sources;
Iterator thisnodeIt = this.vertexes.iterator();
while (thisnodeIt.hasNext())
{
Object src = thisnodeIt.next();
Hashtable othertargets = othersources.get(src);
if (othertargets == null)
continue;
Hashtable thistargets = new Hashtable();
Iterator othertargetIt = othertargets.keySet().iterator();
while (othertargetIt.hasNext())
{
Object key = othertargetIt.next();
if (this.vertexes.contains(key))
{
IntContainer weight = (IntContainer)othertargets.get(key);
thistargets.put(key, weight.dup());
}
}
if (thistargets.size() > 0)
this.sources.put(src, thistargets);
}
}
/* add another graph's edge and weight to this graph,
it simply replace the edge weight.
When used with clear, it can copy a graph to a new graph
*/
public void addAll(WeightedDirectedSparseGraph othergraph)
{
WeightedDirectedSparseGraph another =
othergraph;
this.isUnknown = another.isUnknown;
this.clear();
Hashtable> othersources = another.sources;
Iterator othersrcIt = othersources.keySet().iterator();
while (othersrcIt.hasNext())
{
Object src = othersrcIt.next();
Hashtable othertargets = othersources.get(src);
Hashtable thistargets = new Hashtable(othersources.size());
this.sources.put(src, thistargets);
Iterator targetIt = othertargets.keySet().iterator();
while (targetIt.hasNext())
{
Object target = targetIt.next();
IntContainer otherweight = (IntContainer)othertargets.get(target);
thistargets.put(target, otherweight.dup());
}
}
}
public boolean equals(Object other)
{
if (other == null)
return false;
if (!(other instanceof WeightedDirectedSparseGraph))
return false;
WeightedDirectedSparseGraph othergraph =
(WeightedDirectedSparseGraph)other;
if (this.isUnknown != othergraph.isUnknown)
return false;
if (this.isUnknown)
return true;
// compare each edges. It is not always true, only when shortest path graph can be guaranteed.
Hashtable> othersources = othergraph.sources;
if (this.sources.size() != othersources.size())
return false;
Iterator sourceIt = this.sources.keySet().iterator();
while (sourceIt.hasNext())
{
Object src = sourceIt.next();
Hashtable thistarget = sources.get(src);
Hashtable othertarget = othersources.get(src);
if (othertarget == null)
return false;
if (thistarget.size() != othertarget.size())
return false;
Iterator targetIt = thistarget.keySet().iterator();
while (targetIt.hasNext())
{
Object target = targetIt.next();
IntContainer thisweight = (IntContainer)thistarget.get(target);
IntContainer otherweight = (IntContainer)othertarget.get(target);
if (otherweight == null)
return false;
if (thisweight.value != otherweight.value)
return false;
}
}
return true;
}
public String toString()
{
String graphstring="WeightedDirectedSparseGraph:\n";
graphstring = graphstring+this.vertexes+"\n";
Iterator srcIt = sources.keySet().iterator();
while (srcIt.hasNext())
{
Object src = srcIt.next();
graphstring = graphstring + src +" : ";
Hashtable targets = sources.get(src);
Iterator targetIt = targets.keySet().iterator();
while (targetIt.hasNext())
{
Object target = targetIt.next();
IntContainer weight = (IntContainer)targets.get(target);
graphstring = graphstring + target +"("+weight.value+") ";
}
graphstring +="\n";
}
return graphstring;
}
public WeightedDirectedSparseGraph dup()
{
WeightedDirectedSparseGraph newone =
new WeightedDirectedSparseGraph(this.vertexes);
newone.addAll(this);
return newone;
}
public boolean makeShortestPathGraph()
{
boolean nonegcycle = true;
List srcList = new ArrayList(sources.keySet());
Iterator srcIt = srcList.iterator();
while (srcIt.hasNext())
{
Object src = srcIt.next();
if (!SSSPFinder(src))
{
nonegcycle = false;
}
}
return nonegcycle;
}
private final HashSet reachableNodes = new HashSet();
private final HashSet reachableEdges = new HashSet();
private final Hashtable distance = new Hashtable();
private final Hashtable pei = new Hashtable();
private boolean SSSPFinder(Object src)
{
Hashtable outedges = sources.get(src);
if (outedges == null)
return true;
if (outedges.size() == 0)
return true;
InitializeSingleSource(src);
getReachableNodesAndEdges(src);
// relaxation
int vSize = reachableNodes.size();
for (int i=0; i edgeIt = reachableEdges.iterator();
while (edgeIt.hasNext())
{
WeightedDirectedEdge edge =
edgeIt.next();
Relax(edge.from, edge.to, edge.weight);
}
}
distance.remove(src);
// check negative cycle
{
Iterator edgeIt = reachableEdges.iterator();
while (edgeIt.hasNext())
{
WeightedDirectedEdge edge =
edgeIt.next();
IntContainer dfrom = distance.get(edge.from);
if (dfrom == null)
continue;
IntContainer dto = distance.get(edge.to);
if (dto == null)
continue;
if (dto.value > (dfrom.value + edge.weight))
return false;
}
}
// update the graph
outedges.clear();
Iterator targetIt = distance.keySet().iterator();
while (targetIt.hasNext())
{
Object to = targetIt.next();
IntContainer dist = distance.get(to);
outedges.put(to, dist.dup());
}
return true;
}
private void InitializeSingleSource(Object src)
{
reachableNodes.clear();
reachableEdges.clear();
pei.clear();
distance.clear();
distance.put(src, new IntContainer(0));
}
private void getReachableNodesAndEdges(Object src)
{
LinkedList worklist = new LinkedList();
reachableNodes.add(src);
worklist.add(src);
while (!worklist.isEmpty())
{
Object from = worklist.removeFirst();
Hashtable targets = sources.get(from);
if (targets == null)
continue;
Iterator targetIt = targets.keySet().iterator();
while (targetIt.hasNext())
{
Object target = targetIt.next();
if (!reachableNodes.contains(target))
{
worklist.add(target);
reachableNodes.add(target);
}
IntContainer weight = (IntContainer)targets.get(target);
reachableEdges.add(new WeightedDirectedEdge(from, target, weight.value));
}
}
}
private void Relax(Object from, Object to, int weight)
{
IntContainer dfrom = distance.get(from);
IntContainer dto = distance.get(to);
if (dfrom != null)
{
int vfrom = dfrom.value;
int vnew = vfrom+weight;
if (dto == null)
{
distance.put(to, new IntContainer(vnew));
pei.put(to, from);
}
else
{
int vto = dto.value;
if (vto > vnew)
{
distance.put(to, new IntContainer(vnew));
pei.put(to, from);
}
}
}
}
}