2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,14 +1,19 @@
Given a mapping between items, and items they depend on, a [[wp:Topological sorting|topological sort]] orders items so that no item precedes an item it depends upon.
The compiling of a library in the [[wp:VHDL|VHDL]] language has the constraint that a library must be compiled after any library it depends on.
A tool exists that extracts library dependencies.
The task is to '''write a function that will return a valid compile order of VHDL libraries from their dependencies.'''
;Task;
Write a function that will return a valid compile order of VHDL libraries from their dependencies.
* Assume library names are single words.
* Items mentioned as only dependants, (sic), have no dependants of their own, but their order of compiling must be given.
* Items mentioned as only dependents, (sic), have no dependents of their own, but their order of compiling must be given.
* Any self dependencies should be ignored.
* Any un-orderable dependencies should be flagged.
<br>
Use the following data as an example:
<pre>
LIBRARY LIBRARY DEPENDENCIES
@ -25,12 +30,17 @@ dware ieee dware
gtech ieee gtech
ramlib std ieee
std_cell_lib ieee std_cell_lib
synopsys </pre>
synopsys
</pre>
<br>
<small>Note: the above data would be un-orderable if, for example, <code>dw04</code> is added to the list of dependencies of <code>dw01</code>.</small>
C.f: [[Topological sort/Extracted top item]].
;C.f.:
* [[Topological sort/Extracted top item]].
<br>
There are two popular algorithms for topological sorting:
Kahn's 1962 topological sort, and depth-first search.
<ref>
@ -39,3 +49,4 @@ Kahn's 1962 topological sort, and depth-first search.
Jason Sachs
[http://www.embeddedrelated.com/showarticle/799.php "Ten little algorithms, part 4: topological sort"].
</ref>
<br><br>

View file

@ -0,0 +1,46 @@
defmodule Topological do
def sort(library) do
g = :digraph.new
Enum.each(library, fn {l,deps} ->
:digraph.add_vertex(g,l) # noop if library already added
Enum.each(deps, fn d -> add_dependency(g,l,d) end)
end)
if t = :digraph_utils.topsort(g) do
print_path(t)
else
IO.puts "Unsortable contains circular dependencies:"
Enum.each(:digraph.vertices(g), fn v ->
if vs = :digraph.get_short_cycle(g,v), do: print_path(vs)
end)
end
end
defp print_path(l), do: IO.puts Enum.join(l, " -> ")
defp add_dependency(_g,l,l), do: :ok
defp add_dependency(g,l,d) do
:digraph.add_vertex(g,d) # noop if dependency already added
:digraph.add_edge(g,d,l) # Dependencies represented as an edge d -> l
end
end
libraries = [
des_system_lib: ~w[std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee]a,
dw01: ~w[ieee dw01 dware gtech]a,
dw02: ~w[ieee dw02 dware]a,
dw03: ~w[std synopsys dware dw03 dw02 dw01 ieee gtech]a,
dw04: ~w[dw04 ieee dw01 dware gtech]a,
dw05: ~w[dw05 ieee dware]a,
dw06: ~w[dw06 ieee dware]a,
dw07: ~w[ieee dware]a,
dware: ~w[ieee dware]a,
gtech: ~w[ieee gtech]a,
ramlib: ~w[std ieee]a,
std_cell_lib: ~w[ieee std_cell_lib]a,
synopsys: []
]
Topological.sort(libraries)
IO.puts ""
bad_libraries = Keyword.update!(libraries, :dw01, &[:dw04 | &1])
Topological.sort(bad_libraries)

View file

@ -0,0 +1,71 @@
variable nodes 0 nodes ! \ linked list of nodes
: node. ( body -- )
body> >name name>string type ;
: nodeps ( body -- )
\ the word referenced by body has no (more) dependencies to resolve
['] drop over ! node. space ;
: processing ( body1 ... bodyn body -- body1 ... bodyn )
\ the word referenced by body is in the middle of resolving dependencies
2dup <> if \ unless it is a self-reference (see task description)
['] drop over !
." (cycle: " dup node. >r 1 begin \ print the cycle
dup pick dup r@ <> while
space node. 1+ repeat
." ) " 2drop r>
then drop ;
: >processing ( body -- body )
['] processing over ! ;
: node ( "name" -- )
\ define node "name" and initialize it to having no dependences
create
['] nodeps , \ on definition, a node has no dependencies
nodes @ , lastxt nodes ! \ linked list of nodes
does> ( -- )
dup @ execute ; \ perform xt associated with node
: define-nodes ( "names" <newline> -- )
\ define all the names that don't exist yet as nodes
begin
parse-name dup while
2dup find-name 0= if
2dup nextname node then
2drop repeat
2drop ;
: deps ( "name" "deps" <newline> -- )
\ name is after deps. Implementation: Define missing nodes, then
\ define a colon definition for
>in @ define-nodes >in !
' :noname ]] >processing [[ source >in @ /string evaluate ]] nodeps ; [[
swap >body ! 0 parse 2drop ;
: all-nodes ( -- )
\ call all nodes, and they then print their dependences and themselves
nodes begin
@ dup while
dup execute
>body cell+ repeat
drop ;
deps des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee
deps dw01 ieee dw01 dware gtech
deps dw02 ieee dw02 dware
deps dw03 std synopsys dware dw03 dw02 dw01 ieee gtech
deps dw04 dw04 ieee dw01 dware gtech
deps dw05 dw05 ieee dware
deps dw06 dw06 ieee dware
deps dw07 ieee dware
deps dware ieee dware
deps gtech ieee gtech
deps ramlib std ieee
deps std_cell_lib ieee std_cell_lib
deps synopsys
\ to test the cycle recognition (overwrites dependences for dw1 above)
deps dw01 ieee dw01 dware gtech dw04
all-nodes

View file

@ -1,26 +1,77 @@
import java.util.ArrayList;
import java.util.TreeMap;
import java.util.*;
public class TopologicalSort {
public static void main(String[] args) throws Exception {
TreeMap<String, ArrayList<String>> mp = new TreeMap<String, ArrayList<String>>();
String[] data, input = new String[] {
"des_system_lib: std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee",
"dw01: ieee dw01 dware gtech", "dw02: ieee dw02 dware",
"dw03: std synopsys dware dw03 dw02 dw01 ieee gtech",
"dw04: dw04 ieee dw01 dware gtech", "dw05: dw05 ieee dware",
"dw06: dw06 ieee dware", "dw07: ieee dware",
"dware: ieee dware", "gtech: ieee gtech", "ramlib: std ieee",
"std_cell_lib: ieee std_cell_lib", "synopsys:" };
for (String str : input)
mp.put((data = str.split(":"))[0], Utils.aList(//
data.length < 2 || data[1].trim().equals("")//
? null : data[1].trim().split("\\s+")));
public static void main(String[] args) {
String s = "std, ieee, des_system_lib, dw01, dw02, dw03, dw04, dw05,"
+ "dw06, dw07, dware, gtech, ramlib, std_cell_lib, synopsys";
Utils.tSortFix(mp);
System.out.println(Utils.tSort(mp));
mp.put("dw01", Utils.aList("dw04"));
System.out.println(Utils.tSort(mp));
}
Graph g = new Graph(s, new int[][]{
{2, 0}, {2, 14}, {2, 13}, {2, 4}, {2, 3}, {2, 12}, {2, 1},
{3, 1}, {3, 10}, {3, 11},
{4, 1}, {4, 10},
{5, 0}, {5, 14}, {5, 10}, {5, 4}, {5, 3}, {5, 1}, {5, 11},
{6, 1}, {6, 3}, {6, 10}, {6, 11},
{7, 1}, {7, 10},
{8, 1}, {8, 10},
{9, 1}, {9, 10},
{10, 1},
{11, 1}, {11, 10},
{12, 0}, {12, 1},
{13, 1}
});
System.out.println("Topologically sorted order: ");
System.out.println(g.topoSort());
}
}
class Graph {
String[] vertices;
boolean[][] adjacency;
int numVertices;
public Graph(String s, int[][] edges) {
vertices = s.split(",");
numVertices = vertices.length;
adjacency = new boolean[numVertices][numVertices];
for (int[] edge : edges)
adjacency[edge[0]][edge[1]] = true;
}
List<String> topoSort() {
List<String> result = new ArrayList<>();
List<Integer> todo = new LinkedList<>();
for (int i = 0; i < numVertices; i++)
todo.add(i);
try {
outer:
while (!todo.isEmpty()) {
for (Integer r : todo) {
if (!hasDependency(r, todo)) {
todo.remove(r);
result.add(vertices[r]);
// no need to worry about concurrent modification
continue outer;
}
}
throw new Exception("Graph has cycles");
}
} catch (Exception e) {
System.out.println(e);
return null;
}
return result;
}
boolean hasDependency(Integer r, List<Integer> todo) {
for (Integer c : todo) {
if (adjacency[r][c])
return true;
}
return false;
}
}

View file

@ -33,5 +33,5 @@ my %deps =
synopsys => < >;
print_topo_sort(%deps);
%deps<dw01>.push: 'dw04'; # Add unresolvable dependency
%deps<dw01> = <ieee dw01 dware gtech dw04>; # Add unresolvable dependency
print_topo_sort(%deps);

View file

@ -0,0 +1,62 @@
/*REXX pgm does a topological sort (orders such that no item precedes a dependent item).*/
idep.=0; ipos.=0; iord.=0 /*initialize some stemmed arrays to 0.*/
label= 'DES_SYSTEM_LIB DW01 DW02 DW03 DW04 DW05 DW06 DW07 DWARE GTECH RAMLIB',
'STD_CELL_LIB SYNOPSYS STD IEEE'
icode=1 14 13 12 1 3 2 11 15 0 2 15 2 9 10 0 3 15 3 9 0 4 14 213 9 4 3 2 15 10 0 5 5 15 2,
9 10 0 6 6 15 9 0 7 7 15 9 0 8 15 9 0 39 15 9 0 10 15 10 0 11 14 15 0 12 15 12 0 0
idep.=0; ipos.=0; iord.=0 /*initialize some stemmed arrays to 0.*/
nl=15; nd=44; nc=69; j=0; i=0 /* " " "parms" and indices.*/
10: i=i+1
il=word(icode, i)
if il==0 then signal 30
20: i=i+1
ir=word(icode, i)
if ir==0 then signal 10
j=j+1
idep.j.1=il
idep.j.2=ir
signal 20
30: call tsort
say 'compile order'
q=0; do o=no by -1 for no; q=q+1
say word(label, iord.o)
end /*o*/
if q==0 then q='no'
say ' ('q "libraries found.)"
say
say 'unordered libraries'
q=0; do u=no+1 to nl; q=q+1
say word(label, iord.u)
end /*u*/
if q==0 then q='no'
say ' ('q "unordered libraries found.)"
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
tSort: procedure expose nl nd idep. iord. ipos. no
do i=1 for nl
iord.i=i
ipos.i=i
end /*i*/
k=1
do forever
j=k
k=nl+1
do i=1 for nd
il=idep.i.1
ir=ipos.il
ipl=ipos.il
ipr=ipos.ir
if il==ir | ipl>.k | ipl<j | ipr<j then iterate
k=k-1
_=iord.k; ipos._=ipl
ipos.il=k
iord.ipl=iord.k
iord.k=il
end /*i*/
if k<=j then leave
end /*forever*/
no=j-1
return