1
2
3 """
4 Functions for manipulating dependencies.
5
6 Parameter values must be updated in the correct order. If parameter A
7 depends on parameter B, then parameter B must be evaluated first.
8 """
9
11 """
12 Order elements from pairs so that b comes before a in the
13 ordered list for all pairs (a,b).
14 """
15
16 emptyset = set()
17 order = []
18
19
20 left,right = [set(s) for s in zip(*pairs)] if pairs != [] else ([],[])
21 while pairs != []:
22
23
24 independent = right - left
25 if independent == emptyset:
26 cycleset = ", ".join(str(s) for s in left)
27 raise ValueError,"Cyclic dependencies amongst %s"%cycleset
28
29
30 dependent = set([a for a,b in pairs if b in independent])
31 pairs = [(a,b) for a,b in pairs if b not in independent]
32 if pairs == []:
33 resolved = dependent
34 else:
35 left,right = [set(s) for s in zip(*pairs)]
36 resolved = dependent - left
37
38 order += resolved
39
40 order.reverse()
41 return order
42
43
45 """
46 Verify that the list n contains the given items, and that the list
47 satisfies the partial ordering given by the pairs in partial order.
48 """
49 left,right = zip(*pairs) if pairs != [] else ([],[])
50 items = set(left)
51 n = order_dependencies(pairs)
52 if set(n) != items or len(n) != len(items):
53 n.sort()
54 items = list(items); items.sort()
55 raise Exception,"%s expect %s to contain %s for %s"%(msg,n,items,pairs)
56 for lo,hi in pairs:
57 if lo in n and hi in n and n.index(lo) >= n.index(hi):
58 raise Exception,"%s expect %s before %s in %s for %s"%(msg,lo,hi,n,pairs)
59
61 import numpy
62
63
64 _check("test empty",[])
65
66
67 _check("test1",[(2,7),(1,5),(1,4),(2,1),(3,1),(5,6)])
68 _check("test1 renumbered",[(6,1),(7,3),(7,4),(6,7),(5,7),(3,2)])
69 _check("test1 numpy",numpy.array([(2,7),(1,5),(1,4),(2,1),(3,1),(5,6)]))
70
71
72 _check("test2",[(4,1),(3,2),(8,4)])
73
74
75 pairs = [(1,4),(4,3),(4,5),(5,1)]
76 try: n = order_dependencies(pairs)
77 except ValueError: pass
78 else: raise Exception,"test3 expect ValueError exception for %s"%(pairs,)
79
80
81 A = numpy.random.randint(4000,size=(1000,2))
82 A[:,1] += 4000
83 _check("test-large",A)
84
85
86 k = 200
87 A = numpy.array([range(0,k),range(1,k+1)]).T
88 _check("depth-1",A)
89
90 A = numpy.array([range(1,k+1),range(0,k)]).T
91 _check("depth-2",A)
92
93 if __name__ == "__main__":
94 test()
95