Skip to content

Commit c840e10

Browse files
committed
First version of pipline wiht contexts addition.
1 parent 203e353 commit c840e10

File tree

6 files changed

+195
-23
lines changed

6 files changed

+195
-23
lines changed

cfpq_add_context/add_contexts.py

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,108 @@
1-
from load_graph import load_graph
2-
from intersection import intersection
3-
from gen_automata import generate
1+
import graphblas
2+
3+
from cfpq_add_context.load_graph import load_graph
4+
from cfpq_add_context.intersection import intersection
5+
from cfpq_add_context.gen_automata import generate
6+
from graphblas.core.dtypes import BOOL, UINT64
7+
from graphblas.core.matrix import Matrix
8+
9+
from cfpq_matrix.block.block_matrix_space_impl import BlockMatrixSpaceImpl
10+
from cfpq_model.cnf_grammar_template import Symbol
11+
from cfpq_model.label_decomposed_graph import LabelDecomposedGraph
12+
413
import time
514

15+
def indexed_to_boolean_decomposition(graph, block_count):
16+
#print("graph = ", graph)
17+
#print("block count = ", block_count )
18+
vertex_count = graph.nrows
19+
edges = graph.to_edgelist()
20+
edges = zip(edges[0], edges[1])
21+
new_edges = [(_edg[0] + vertex_count * _lbl, _edg[1]) for (_edg, _lbl) in edges]
22+
result = Matrix.from_edgelist(new_edges, values=True, dtype=BOOL, nrows = block_count * vertex_count,
23+
ncols=vertex_count, name = "boolean_decomposition_of_indexed")
24+
return result
25+
26+
def to_label_decomposed_graph(graph):
27+
vertex_count = graph.nrows
28+
alloc = Matrix(BOOL, graph.ncols, graph.nrows, name = "alloc_after_intersection")
29+
alloc << graph.select(graphblas.select.select_alloc)
30+
31+
alloc_r = Matrix(BOOL, graph.ncols, graph.nrows, name = "alloc_r_after_intersection")
32+
alloc_r << graph.select(graphblas.select.select_alloc_r)
33+
34+
assign = Matrix(BOOL, graph.ncols, graph.nrows, name = "assign_after_intersection")
35+
assign << graph.select(graphblas.select.select_assign)
36+
37+
assign_r = Matrix(BOOL, graph.ncols, graph.nrows, name = "assign_r_after_intersection")
38+
assign_r << graph.select(graphblas.select.select_assign_r)
39+
40+
load_i = Matrix(UINT64, graph.ncols, graph.nrows, name = "load_i_after_intersection")
41+
load_i << graph.select(graphblas.select.select_load).apply(graphblas.unary.decode_load)
42+
43+
load_r_i = Matrix(UINT64, graph.ncols, graph.nrows, name = "load_r_i_after_intersection")
44+
load_r_i << graph.select(graphblas.select.select_load_r).apply(graphblas.unary.decode_load_r)
45+
46+
store_i = Matrix(UINT64, graph.ncols, graph.nrows, name = "store_i_after_intersection")
47+
store_i << graph.select(graphblas.select.select_store).apply(graphblas.unary.decode_store)
48+
49+
store_r_i = Matrix(UINT64, graph.ncols, graph.nrows, name = "store_r_i_after_intersection")
50+
store_r_i << graph.select(graphblas.select.select_store_r).apply(graphblas.unary.decode_store_r)
51+
52+
store_block_count = store_i.reduce_scalar("max").get(0) + 1
53+
load_block_count = load_i.reduce_scalar("max").get(0) + 1
54+
block_count = max(store_block_count, load_block_count)
55+
56+
boolean_decompose_load = indexed_to_boolean_decomposition(load_i, block_count)
57+
boolean_decompose_load_r = indexed_to_boolean_decomposition(load_r_i, block_count)
58+
boolean_decompose_store = indexed_to_boolean_decomposition(store_i, block_count)
59+
boolean_decompose_store_r = indexed_to_boolean_decomposition(store_r_i, block_count)
60+
61+
matrices: Dict[Symbol, Matrix] = {}
62+
63+
matrices[Symbol('alloc')] = alloc
64+
matrices[Symbol('alloc_r')] = alloc_r
65+
66+
matrices[Symbol('assign')] = assign
67+
matrices[Symbol('assign_r')] = assign_r
68+
69+
matrices[Symbol('store_i')] = boolean_decompose_store
70+
matrices[Symbol('load_i')] = boolean_decompose_load
71+
matrices[Symbol('store_r_i')] = boolean_decompose_store_r
72+
matrices[Symbol('load_r_i')] = boolean_decompose_load_r
73+
74+
return LabelDecomposedGraph(
75+
vertex_count=vertex_count,
76+
block_matrix_space=BlockMatrixSpaceImpl(n=vertex_count, block_count=block_count),
77+
dtype=BOOL,
78+
matrices=matrices
79+
)
80+
681
def add_context(file_path):
782
load_graph_start = time.perf_counter()
883

984
graph,number_of_contexts = load_graph(file_path)
1085

1186
load_graph_end = time.perf_counter()
1287
print("Graph loaded in ", load_graph_end - load_graph_start)
88+
print("Vertices in graph: ", graph.ncols)
89+
print("Edges in graph: ", graph.nvals)
90+
print("Numer of contexts: ", number_of_contexts)
1391

1492
automata = generate(number_of_contexts)
1593

1694
automata_generation_end = time.perf_counter()
1795
print("Automata generated in ", automata_generation_end - load_graph_end)
96+
print("Vertices in automata: ", automata.ncols)
97+
print("Edges in automata: ", automata.nvals)
1898

1999
result = intersection(graph, automata)
20100

21101
intersection_end = time.perf_counter()
22102
print("Graph and automata intersection competed in ", intersection_end - automata_generation_end)
103+
print("Vertices in intersection: ", result.ncols)
104+
print("Edges in intersection: ", result.nvals)
23105

24-
return result
106+
return to_label_decomposed_graph(result)
107+
108+

cfpq_add_context/gen_automata.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from graphblas.core.matrix import Matrix
44
from graphblas.core.dtypes import UINT64
55

6-
from labels import SIGMA, SIGMA_WITHOUT_CONTEXTS, SIGMA_WITHOUT_OPEN_CONTEXTS, ALL_OPEN_CONTEXTS, mk_close_context, mk_open_context
7-
from utils import print_matrix_to_dot
6+
from cfpq_add_context.labels import SIGMA, SIGMA_WITHOUT_CONTEXTS, SIGMA_WITHOUT_OPEN_CONTEXTS, ALL_OPEN_CONTEXTS, mk_close_context, mk_open_context
7+
from cfpq_add_context.utils import print_matrix_to_dot
88

99
def generate (number_of_contexts):
1010
number_of_contexts = number_of_contexts * 2 # with reversed edges

cfpq_add_context/intersection.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
from graphblas.core.operator import Semiring, Monoid, SelectOp
66
from graphblas.core.dtypes import UINT64
77
from graphblas import op, semiring
8-
import gen_automata
8+
import cfpq_add_context.gen_automata
9+
import time
910

10-
import labels
11-
from utils import print_matrix_to_dot
11+
import cfpq_add_context.labels
12+
from cfpq_add_context.utils import print_matrix_to_dot
1213

1314
def kronecker (graph, automata):
1415
result = Matrix(graph.dtype, graph.nrows * automata.nrows, graph.ncols * automata.ncols, name="intersection")
@@ -17,7 +18,6 @@ def kronecker (graph, automata):
1718

1819
def bfs (matrix, sources):
1920
n = matrix.nrows
20-
print ("n = ", n)
2121

2222
reachable = Vector.from_coo(sources, True, size=n, name="reachable")
2323
frontier = Vector.from_coo(sources, True, size=n, name="frontier")
@@ -29,7 +29,7 @@ def bfs (matrix, sources):
2929
new_frontier = Vector(bool, size=n)
3030
new_frontier(~reachable.S) << semiring.any_first(frontier @ matrix)
3131

32-
print("new_frontier nvals = ", new_frontier.nvals)
32+
#print("new_frontier nvals = ", new_frontier.nvals)
3333

3434
if new_frontier.nvals == 0:
3535
break
@@ -46,19 +46,37 @@ def filter_not_zero_op(x,i,j,k):
4646
SelectOp.register_new("filter_not_zero", filter_not_zero_op)
4747

4848
def intersection (graph, automata) :
49+
intersection_start = time.perf_counter()
50+
4951
intersection = kronecker(graph, automata)
52+
53+
intersection_end = time.perf_counter()
54+
print("Intersection done in ", intersection_end - intersection_start)
55+
print("Vertices in intersection before zeroes removing: ", intersection.ncols)
56+
print("Edges in intersection before zeroes removing: ", intersection.nvals)
57+
5058
#TODO remove when moved to patched kronecker
5159
intersection << intersection.select(graphblas.select.filter_not_zero)
5260

53-
print_matrix_to_dot(intersection, "kron.dot")
61+
zeroes_removing_from_intersection_end = time.perf_counter()
62+
print("Removing of zeroes from intersection done in ", zeroes_removing_from_intersection_end - intersection_end)
63+
print("Vertices in intersection after zeroes removing: ", intersection.ncols)
64+
print("Edges in intersection after zeroes removing: ", intersection.nvals)
65+
66+
67+
#print_matrix_to_dot(intersection, "kron.dot")
5468

5569
sources = [i * automata.nrows for i in range(0,graph.nrows)]
5670

5771
reachable_vertices_mask = bfs(intersection, sources).diag(name="reachable_vertices_mask")
5872

5973
result = Matrix(intersection.dtype, intersection.nrows, intersection.ncols, name = "filtered intersection")
6074
result << reachable_vertices_mask @ intersection
61-
print_matrix_to_dot(result, "kron_filtered.dot")
75+
76+
unreachable_vertices_removing_end = time.perf_counter()
77+
print("Removing of unreachable vertices done in ", unreachable_vertices_removing_end - zeroes_removing_from_intersection_end)
78+
79+
#print_matrix_to_dot(result, "kron_filtered.dot")
6280
return result
6381

6482

cfpq_add_context/labels.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import graphblas
22

3-
from graphblas.core.operator import Monoid, BinaryOp
3+
from graphblas.core.operator import Monoid, BinaryOp, SelectOp, UnaryOp
44
from graphblas import binary
55

66
'''
@@ -13,6 +13,7 @@
1313
SIGMA = 0b1111111111111111111111111111111111111111111111111111111111111111
1414
SIGMA_WITHOUT_CONTEXTS = 0b0000000000000000000000000000000000000000001111111111111111111111
1515
ALL_OPEN_CONTEXTS = 0b1111111111111111111110000000000000000000000000000000000000000000
16+
ALL_CLOSE_CONTEXTS = 0b0000000000000000000001111111111111111111110000000000000000000000
1617
SIGMA_WITHOUT_OPEN_CONTEXTS = 0b0000000000000000000001111111111111111111111111111111111111111111
1718
NOTHING = 0b0000000000000000000000000000000000000000000000000000000000000000
1819

@@ -35,6 +36,62 @@ def mk_close_context(x:int) -> int :
3536
def mk_other(x:int) -> int :
3637
return NOTHING | x
3738
def mk_load(i):
38-
return mk_other(2 * i + OFFSET)
39+
return mk_other(4 * i + OFFSET)
40+
def mk_load_r(i):
41+
return mk_other(4 * i + 1+ OFFSET)
3942
def mk_store (i):
40-
return mk_other(2 * i + 1 + OFFSET)
43+
return mk_other(4 * i + 2 + OFFSET)
44+
def mk_store_r (i):
45+
return mk_other(4 * i + 3 + OFFSET)
46+
47+
48+
def select_alloc_op(x,i,j,k):
49+
return x & SIGMA_WITHOUT_CONTEXTS == ALLOC
50+
51+
def select_alloc_r_op(x,i,j,k):
52+
return x & SIGMA_WITHOUT_CONTEXTS == ALLOC_R
53+
54+
def select_assign_op(x,i,j,k):
55+
return x & SIGMA_WITHOUT_CONTEXTS == ASSIGN or (x & ALL_OPEN_CONTEXTS > 0 and x & ALL_OPEN_CONTEXTS % 2 == 1) or (x & ALL_OPEN_CONTEXTS > 0 and x & ALL_CLOSE_CONTEXTS % 2 == 1)
56+
57+
def select_assign_r_op(x,i,j,k):
58+
return x & SIGMA_WITHOUT_CONTEXTS == ASSIGN_R or (x & ALL_OPEN_CONTEXTS > 0 and x & ALL_OPEN_CONTEXTS % 2 == 0) or (x & ALL_OPEN_CONTEXTS > 0 and x & ALL_CLOSE_CONTEXTS % 2 == 0)
59+
60+
def select_load_op(x,i,j,k):
61+
return x & SIGMA_WITHOUT_CONTEXTS >= OFFSET and ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET) % 4 == 0
62+
63+
def select_load_r_op(x,i,j,k):
64+
return x & SIGMA_WITHOUT_CONTEXTS >= OFFSET and ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET) % 4 == 1
65+
66+
def select_store_op(x,i,j,k):
67+
return x & SIGMA_WITHOUT_CONTEXTS >= OFFSET and ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET) % 4 == 2
68+
69+
def select_store_r_op(x,i,j,k):
70+
return x & SIGMA_WITHOUT_CONTEXTS >= OFFSET and ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET) % 4 == 3
71+
72+
SelectOp.register_new("select_alloc", select_alloc_op)
73+
SelectOp.register_new("select_alloc_r", select_alloc_r_op)
74+
SelectOp.register_new("select_assign", select_assign_op)
75+
SelectOp.register_new("select_assign_r", select_assign_r_op)
76+
SelectOp.register_new("select_load", select_load_op)
77+
SelectOp.register_new("select_store", select_store_op)
78+
SelectOp.register_new("select_load_r", select_load_r_op)
79+
SelectOp.register_new("select_store_r", select_store_r_op)
80+
81+
def decode_load_op(x):
82+
return ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET) // 4
83+
84+
def decode_load_r_op(x):
85+
return ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET - 1) // 4
86+
87+
def decode_store_op(x):
88+
return ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET - 2) // 4
89+
90+
def decode_store_r_op(x):
91+
return ((x & SIGMA_WITHOUT_CONTEXTS) - OFFSET - 3) // 4
92+
93+
94+
UnaryOp.register_new("decode_load", decode_load_op)
95+
UnaryOp.register_new("decode_load_r", decode_load_r_op)
96+
UnaryOp.register_new("decode_store", decode_store_op)
97+
UnaryOp.register_new("decode_store_r", decode_store_r_op)

cfpq_add_context/load_graph.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from graphblas.core.matrix import Matrix
44
from graphblas.core.dtypes import UINT64
55

6-
import labels
7-
from utils import print_matrix_to_dot
6+
import cfpq_add_context.labels as labels
7+
from cfpq_add_context.utils import print_matrix_to_dot
88

99

1010

@@ -15,8 +15,12 @@ def get_edge_lbl(data_arr):
1515
_context = 0
1616
nonlocal number_of_contexts
1717
if len(data_arr) == 4:
18-
if "load" in data_arr[2]:
18+
if "load_r" in data_arr[2]:
19+
return labels.mk_load_r(int(data_arr[3]))
20+
elif "load" in data_arr[2]:
1921
return labels.mk_load(int(data_arr[3]))
22+
elif "store_r" in data_arr[2]:
23+
return labels.mk_store_r(int(data_arr[3]))
2024
else:
2125
return labels.mk_store(int(data_arr[3]))
2226
elif data_arr[2] == "assign":
@@ -29,9 +33,9 @@ def get_edge_lbl(data_arr):
2933
return labels.mk_other(labels.ALLOC_R)
3034
elif "open" in data_arr[2]:
3135
if "_r_" in data_arr[2]:
32-
_context = 2 * int(data_arr[2].split('_')[2])
36+
_context = 2 * (1 + int(data_arr[2].split('_')[2]))
3337
else:
34-
_context = 2 * int(data_arr[2].split('_')[1]) + 1
38+
_context = 2 * (1 + int(data_arr[2].split('_')[1])) + 1
3539
number_of_contexts = max(number_of_contexts, _context)
3640
return labels.mk_open_context(_context)
3741
else:
@@ -57,6 +61,6 @@ def handle_line(line):
5761
with open (file_path,'r') as file:
5862
edges = [handle_line(line) for line in file if len(line.strip()) > 0]
5963
result = Matrix.from_edgelist(edges, dtype=UINT64, nrows=nvertices + 1, ncols=nvertices + 1, name="graph")
60-
print_matrix_to_dot(result, "graph.dot")
64+
#print_matrix_to_dot(result, "graph.dot")
6165
return (result, (number_of_contexts // 2) + 1)
6266

cfpq_cli/run_all_pairs_cflr.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,23 @@
1313
from cfpq_cli.time_limit import time_limit, TimeoutException
1414
from cfpq_model.cnf_grammar_template import CnfGrammarTemplate
1515
from cfpq_model.label_decomposed_graph import LabelDecomposedGraph
16+
from cfpq_add_context.add_contexts import add_context
1617

1718

1819
def run_all_pairs_cflr(
1920
algo_name: str,
2021
graph_path: str,
2122
grammar_path: str,
23+
add_contexts: bool,
2224
time_limit_sec: Optional[int],
2325
out_path: Optional[str],
2426
settings: List[AlgoSetting]
2527
):
2628
algo = get_all_pairs_cfl_reachability_algo(algo_name)
27-
graph = LabelDecomposedGraph.read_from_pocr_graph_file(graph_path)
29+
if add_contexts:
30+
graph = add_context(graph_path)
31+
else:
32+
graph = LabelDecomposedGraph.read_from_pocr_graph_file(graph_path)
2833
grammar = CnfGrammarTemplate.read_from_pocr_cnf_file(grammar_path)
2934
graph, grammar = preprocess_graph_and_grammar(graph, grammar, settings)
3035
try:
@@ -78,13 +83,17 @@ def main(raw_args: List[str]):
7883
'to [END_VERTEX], labels along which spell a word from '
7984
'the specified Context-Free Language (CFL).'
8085
)
86+
parser.add_argument('--add_contexts', dest='add_contexts', default=False,
87+
help='Specifies whether approximation of context sensitivity should be added.'
88+
)
8189
settings_manager = AlgoSettingsManager()
8290
settings_manager.add_args(parser)
8391
args = parser.parse_args(raw_args)
8492
run_all_pairs_cflr(
8593
algo_name=args.algo,
8694
graph_path=args.graph,
8795
grammar_path=args.grammar,
96+
add_contexts=args.add_contexts,
8897
time_limit_sec=args.time_limit,
8998
out_path=args.out,
9099
settings=settings_manager.read_args(args)

0 commit comments

Comments
 (0)