From cb0eec606774ab5e07e50c045b1301f3c2f425dd Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 5 Nov 2024 17:01:59 +0100 Subject: [PATCH 001/240] Created SparseMatrix module --- src/cdomains/vectorMatrix.ml | 153 +++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index a3712274ab..5a4b7b644f 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -609,3 +609,156 @@ module ArrayMatrix: AbstractMatrix = let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v end + + +(** Sparse matrix implementation. + It provides a normalization function to reduce a matrix into reduced row echelon form. + Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) +module SparseMatrix: AbstractMatrix = + functor (A: RatOps) (V: AbstractVector) -> + struct + include ConvenienceOps(A) + module V = V(A) + + (*Array of arrays implementation. One array per row containing tuple of column index and value*) + type t = (int * A.t) array array [@@deriving eq, ord, hash] + + let show x = + failwith "TODO" + + let empty () = + Array.make_matrix 0 0 (0, A.zero) + + let num_rows m = + failwith "TODO" + + let is_empty m = + num_rows m = 0 + + let num_cols m = + failwith "TODO" + + let copy m = + failwith "TODO" + + let copy m = + failwith "TODO" + + let add_empty_columns m cols = + failwith "TODO" + + let add_empty_columns m cols = + timing_wrap "add_empty_cols" (add_empty_columns m) cols + + let append_row m row = + failwith "TODO" + + let get_row m n = + failwith "TODO" + + let remove_row m n = + failwith "TODO" + + let get_col m n = + failwith "TODO" + + let get_col m n = + timing_wrap "get_col" (get_col m) n + + let set_col_with m new_col n = + failwith "TODO" + + let set_col_with m new_col n = timing_wrap "set_col" (set_col_with m new_col) n + + let set_col m new_col n = + failwith "TODO" + + let append_matrices m1 m2 = + failwith "TODO" + + let equal m1 m2 = timing_wrap "equal" (equal m1) m2 + + let reduce_col_with m j = + failwith "TODO" + + let reduce_col_with m j = timing_wrap "reduce_col_with" (reduce_col_with m) j + let reduce_col m j = + failwith "TODO" + + let del_col m j = + failwith "TODO" + + let del_cols m cols = + failwith "TODO" + + let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols + + let map2i f m v = + failwith "TODO" + + let remove_zero_rows m = + failwith "TODO" + + let rref_with m = + failwith "TODO" + + let rref_with m = timing_wrap "rref_with" rref_with m + + let init_with_vec v = + failwith "TODO" + + + let reduce_col_with_vec m j v = + failwith "TODO" + + let get_pivot_positions m = + failwith "TODO" + + let rref_vec m pivot_positions v = + failwith "TODO" + + + let rref_vec_with m v = + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*m must be in rref form and contain the same num of cols as v*) + (*If m is empty then v is simply normalized and returned*) + failwith "TODO" + + let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v + + let rref_matrix_with m1 m2 = + (*Similar to rref_vec_with but takes two matrices instead.*) + (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) + failwith "TODO" + + let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 + + let normalize_with m = + failwith "TODO" + + let normalize_with m = timing_wrap "normalize_with" normalize_with m + + let normalize m = + failwith "TODO" + + let is_covered_by m1 m2 = + failwith "TODO" + + let is_covered_by m1 m2 = timing_wrap "is_covered_by" (is_covered_by m1) m2 + + let find_opt f m = + failwith "TODO" + + let map2 f m v = + failwith "TODO" + + let map2_with f m v = + failwith "TODO" + + let map2_with f m v = timing_wrap "map2_with" (map2_with f m) v + + let map2i_with f m v = + failwith "TODO" + + let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v + end \ No newline at end of file From 69cc72f53cb1cc9c41a6c6a42af066d4e25d7373 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 7 Nov 2024 19:36:57 +0100 Subject: [PATCH 002/240] changed type to lists --- src/cdomains/vectorMatrix.ml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 5a4b7b644f..12be213e5c 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -621,13 +621,16 @@ module SparseMatrix: AbstractMatrix = module V = V(A) (*Array of arrays implementation. One array per row containing tuple of column index and value*) - type t = (int * A.t) array array [@@deriving eq, ord, hash] + type t = { + entries : (int * A.t) array array; + column_count : int + } [@@deriving eq, ord, hash] let show x = failwith "TODO" let empty () = - Array.make_matrix 0 0 (0, A.zero) + failwith "TODO" let num_rows m = failwith "TODO" From 1b5f531b7690d909bd39ea7e3ceb2f66330ca868 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 7 Nov 2024 21:52:03 +0100 Subject: [PATCH 003/240] SparseMatrix list and get_col --- src/cdomains/vectorMatrix.ml | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 12be213e5c..62a7b7a67b 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -622,7 +622,7 @@ module SparseMatrix: AbstractMatrix = (*Array of arrays implementation. One array per row containing tuple of column index and value*) type t = { - entries : (int * A.t) array array; + entries : (int * A.t) list list; column_count : int } [@@deriving eq, ord, hash] @@ -630,16 +630,16 @@ module SparseMatrix: AbstractMatrix = failwith "TODO" let empty () = - failwith "TODO" + {entries = []; column_count = 0} let num_rows m = - failwith "TODO" + List.length m.entries let is_empty m = num_rows m = 0 let num_cols m = - failwith "TODO" + m.column_count let copy m = failwith "TODO" @@ -654,7 +654,7 @@ module SparseMatrix: AbstractMatrix = timing_wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - failwith "TODO" + failwith "TODO" let get_row m n = failwith "TODO" @@ -663,7 +663,15 @@ module SparseMatrix: AbstractMatrix = failwith "TODO" let get_col m n = - failwith "TODO" + (* Uses the fact that row is sorted to return Zero when index n is exceeded *) + let rec get_col_from_row row = + match row with + | [] -> A.zero + | (col_idx, value)::_ when col_idx = n -> value + | (col_idx, _)::_ when col_idx > n -> A.zero + | _::cs -> get_col_from_row cs + in + V.of_list @@ List.map (fun row -> get_col_from_row row ) m.entries let get_col m n = timing_wrap "get_col" (get_col m) n @@ -720,7 +728,7 @@ module SparseMatrix: AbstractMatrix = let rref_vec m pivot_positions v = failwith "TODO" - + let rref_vec_with m v = (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) From b1c877aa69d04d0bc9cd66bb991bb21cd7cf8c7b Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 8 Nov 2024 18:57:36 +0100 Subject: [PATCH 004/240] Implement del_col and del_cols for SparseMatrix --- src/cdomains/vectorMatrix.ml | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 62a7b7a67b..71672ab30f 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -697,10 +697,35 @@ module SparseMatrix: AbstractMatrix = failwith "TODO" let del_col m j = - failwith "TODO" - + if is_empty m then m else + let del_col_from_row row = + List.filter_map (fun (col_idx, value) -> + if col_idx = j then + None + else if col_idx > j then + Some (col_idx - 1, value) + else + Some (col_idx, value) + ) row + in + let new_entries = List.map (fun row -> del_col_from_row row) m.entries in + {entries = new_entries; column_count = m.column_count - 1} + + (* TODO: Might be more efficient to check for each entry how much to reduce their index and not by recursively calling del_col *) let del_cols m cols = - failwith "TODO" + let cols = Array.to_list cols in (* TODO: Get away from Arrays *) + let to_delete_count = List.length cols in + if to_delete_count = 0 || is_empty m then m + else + if num_cols m = to_delete_count then empty () else + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification)*) + let rec del_cols_aux m cols deleted_col_count = + match cols with + | [] -> m + | col_idx::cs -> + let m' = del_col m (col_idx - deleted_col_count) in (* Taking already deleted cols into account because of new index *) + del_cols_aux m' cs (deleted_col_count + 1) + in del_cols_aux m sorted_cols 0 let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols From bfbd373d8c00cfdf3b1e904cdb36d99aa877da91 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Sun, 10 Nov 2024 13:59:34 +0100 Subject: [PATCH 005/240] added row functions and conversions between vectors and sparse lists --- src/cdomains/vectorMatrix.ml | 40 +++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 71672ab30f..700e32c148 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -114,6 +114,11 @@ sig val of_array: num array -> t val copy: t -> t + + val of_sparse_list: (int * num) list -> int -> t + + val to_sparse_list: t -> (int * num) list + end (** Some functions inside have the suffix _with, which means that the function has side effects. *) @@ -272,6 +277,20 @@ module ArrayVector: AbstractVector = let copy v = Array.copy v let mapi_with f v = Array.iteri (fun i x -> v.(i) <- f i x) v + + let of_sparse_list ls col_count = + let vec = Array.make col_count A.zero in + List.iter (fun (idx, value) -> vec.(idx) <- value) ls; + vec + + let to_sparse_list v = + let rec aux idx acc = + if idx < 0 then acc + else + let value = v.(idx) in + let acc = if value <> A.zero then (idx, value):: acc else acc in + aux (idx - 1) acc + in aux (length v - 1) [] end open Batteries.Array @@ -620,14 +639,14 @@ module SparseMatrix: AbstractMatrix = include ConvenienceOps(A) module V = V(A) - (*Array of arrays implementation. One array per row containing tuple of column index and value*) + (* Array of arrays implementation. One array per row containing tuple of column index and value *) type t = { entries : (int * A.t) list list; column_count : int } [@@deriving eq, ord, hash] let show x = - failwith "TODO" + List.fold_left (^) " " (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) let empty () = {entries = []; column_count = 0} @@ -642,10 +661,10 @@ module SparseMatrix: AbstractMatrix = m.column_count let copy m = - failwith "TODO" + {entries = m.entries; column_count = m.column_count} (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) let copy m = - failwith "TODO" + timing_wrap "copy" (copy) m let add_empty_columns m cols = failwith "TODO" @@ -654,13 +673,20 @@ module SparseMatrix: AbstractMatrix = timing_wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - failwith "TODO" + {entries = m.entries @ [V.to_sparse_list row]; column_count = m.column_count} let get_row m n = - failwith "TODO" + V.of_sparse_list (List.nth m.entries n) m.column_count let remove_row m n = - failwith "TODO" + let rec aux idx entries = match idx, entries with + | i, x :: xs when i = n -> xs + | _, x :: xs -> x :: aux (idx + 1) xs + | _, _ -> failwith "trying to remove out of bounds row" + in + let new_entries = aux 0 m.entries in + let new_col_count = if new_entries = [] then 0 else m.column_count in + {entries = new_entries; column_count = new_col_count} let get_col m n = (* Uses the fact that row is sorted to return Zero when index n is exceeded *) From d0124f9a0c9d91f80babfa02ef6fd14ceab69b15 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Mon, 11 Nov 2024 16:53:58 +0100 Subject: [PATCH 006/240] add_empty_columns untested --- src/cdomains/vectorMatrix.ml | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 62a7b7a67b..68dcecab50 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -637,20 +637,57 @@ module SparseMatrix: AbstractMatrix = let is_empty m = num_rows m = 0 + (*This should be different if the implimentation is sound*) + (*m.column_count = 0*) let num_cols m = m.column_count let copy m = - failwith "TODO" + {entries = m.entries; column_count = m.column_count} let copy m = failwith "TODO" - let add_empty_columns m cols = - failwith "TODO" + let add_empty_columns m (cols : int enumerable) = + let colsL = Array.to_list(cols) in + let emptyT = A.zero in + let rec list_of_all_before_index idx cols = + (*This should return two arrays + all the idices before idx and all those after, but I'm not sure if inclusive or not + e.g. list_of_all_before_index 3 [1,2,3,4] = ([1,2], [3,4]) or = ([1,2,3], [4]) + right now its of the first form! + *) + match cols with + | x::xs -> + if x < idx + then + let (h,t) = list_of_all_before_index idx xs in + (x::h, t) + else ([],x::xs) + | [] -> ([],[]) + in + (*This could easily be abstracted into the above functions, but its nice to have + it here for readability and debugging*) + let rec make_empty_entries_for_idxs idxs = + match idxs with + | x::xs -> (x, emptyT)::(make_empty_entries_for_idxs xs) + | [] -> [] + in + let rec add_column_element r cols = + match r with + | (idx, _)::xs -> + let (bef,aft) = list_of_all_before_index idx cols in + (make_empty_entries_for_idxs bef)@(add_column_element xs aft) + | [] -> [] + in + let rec add_empty_columns_on_list m cols = + match m with + | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) + | [] -> [] + in {entries = add_empty_columns_on_list m.entries colsL; column_count = m.column_count + Array.length cols} - let add_empty_columns m cols = + let add_empty_columns m (cols : int enumerable) = timing_wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = From d78945919ae14da99f0c3030ac20451d8d3e92d8 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 12 Nov 2024 16:58:16 +0100 Subject: [PATCH 007/240] Implement set_col for SparseMatrix --- src/cdomains/vectorMatrix.ml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index a33a08018c..cef4ba83b5 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -656,8 +656,8 @@ module SparseMatrix: AbstractMatrix = let is_empty m = num_rows m = 0 - (*This should be different if the implimentation is sound*) - (*m.column_count = 0*) + (*This should be different if the implimentation is sound*) + (*m.column_count = 0*) let num_cols m = m.column_count @@ -680,14 +680,14 @@ module SparseMatrix: AbstractMatrix = match cols with | x::xs -> if x < idx - then - let (h,t) = list_of_all_before_index idx xs in - (x::h, t) - else ([],x::xs) + then + let (h,t) = list_of_all_before_index idx xs in + (x::h, t) + else ([],x::xs) | [] -> ([],[]) in (*This could easily be abstracted into the above functions, but its nice to have - it here for readability and debugging*) + it here for readability and debugging*) let rec make_empty_entries_for_idxs idxs = match idxs with | x::xs -> (x, emptyT)::(make_empty_entries_for_idxs xs) @@ -745,7 +745,18 @@ module SparseMatrix: AbstractMatrix = let set_col_with m new_col n = timing_wrap "set_col" (set_col_with m new_col) n let set_col m new_col n = - failwith "TODO" + let rec set_col_in_row row value = + match row with + | [] -> if value =: A.zero then [] else [(n, value)] + | (col_idx, v)::cs when col_idx > n -> if value =: A.zero then (col_idx, v)::cs else (n, value)::(col_idx, v)::cs + | (col_idx, v)::cs when col_idx = n -> if value =: A.zero then cs else (n, value)::cs + | (col_idx, v)::cs -> (col_idx, v)::(set_col_in_row cs value) + in + let new_entries = List.mapi (fun row_idx row -> + let value = V.nth new_col row_idx in + set_col_in_row row value + ) m.entries in + {entries = new_entries; column_count = m.column_count} let append_matrices m1 m2 = failwith "TODO" From 8c23838bb90fe3cdffd2e117813234259aa57d0e Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 12 Nov 2024 17:52:34 +0100 Subject: [PATCH 008/240] Add functions without side effects to ArrayVector and Vector interface --- src/cdomains/vectorMatrix.ml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index cef4ba83b5..90ba4f044b 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -83,6 +83,8 @@ sig val map_with: (num -> num) -> t -> unit + val map: (num -> num) -> t -> t + val compare_length_with: t -> int -> int val of_list: num list -> t @@ -99,6 +101,8 @@ sig val rev_with: t -> unit + val rev: t -> t + val map2i: (int -> num -> num -> num) -> t -> t -> t val map2i_with: (int -> num -> num -> num) -> t -> t -> unit @@ -107,6 +111,8 @@ sig val mapi_with: (int -> num -> num) -> t -> unit + val mapi: (int -> num -> num) -> t -> t + val find2i: (num -> num -> bool) -> t -> t -> int val to_array: t -> num array @@ -180,6 +186,8 @@ sig val map2_with: (vec -> num -> vec) -> t -> vec -> unit + val map2: (vec -> num -> vec) -> t -> vec -> t + val map2i: (int -> vec-> num -> vec) -> t -> vec -> t val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit @@ -270,14 +278,26 @@ module ArrayVector: AbstractVector = let rev_with v = Array.rev_in_place v + let rev v = Array.rev v + let map_with f v = Array.modify f v + let map f v = Array.map f v + let map2_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f x y) v1 v2 + let map2 f v1 v2 = + let copy_v1 = copy v1 in + map2_with f copy_v1 v2; copy_v1 + let copy v = Array.copy v let mapi_with f v = Array.iteri (fun i x -> v.(i) <- f i x) v + let mapi f v = + let copy = copy v in + mapi_with f copy; copy + let of_sparse_list ls col_count = let vec = Array.make col_count A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) ls; From fd73a7ca1960ce7b140159d356be15ae67452f20 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 12 Nov 2024 18:32:24 +0100 Subject: [PATCH 009/240] Removed some _with functions from the AffineEqualityDomain --- .../apron/affineEqualityDomain.apron.ml | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 06268130b2..aa64b7f741 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -29,7 +29,7 @@ struct m else ( Array.modifyi (+) ch.dim; - let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col_with y x; y) m ch.dim else m in + let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in remove_zero_rows @@ del_cols m' ch.dim) let dim_remove ch m ~del = VectorMatrix.timing_wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del @@ -59,7 +59,7 @@ struct let open Apron.Texpr1 in let exception NotLinear in let zero_vec = Vector.zero_vec @@ Environment.size t.env + 1 in - let neg v = Vector.map_with Mpqf.neg v; v in + let neg v = Vector.map Mpqf.neg v in let is_const_vec v = Vector.compare_length_with (Vector.filteri (fun i x -> (*Inefficient*) Vector.compare_length_with v (i + 1) > 0 && x <>: Mpqf.zero) v) 1 = 0 in @@ -75,13 +75,13 @@ struct Vector.set_val zero_vec ((Vector.length zero_vec) - 1) (of_union x) | Var x -> let zero_vec_cp = Vector.copy zero_vec in - let entry_only v = Vector.set_val_with v (Environment.dim_of_var t.env x) Mpqf.one; v in + let entry_only v = Vector.set_val v (Environment.dim_of_var t.env x) Mpqf.one in begin match t.d with | Some m -> let row = Matrix.find_opt (fun r -> Vector.nth r (Environment.dim_of_var t.env x) =: Mpqf.one) m in begin match row with | Some v when is_const_vec v -> - Vector.set_val_with zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)); zero_vec_cp + Vector.set_val zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)) | _ -> entry_only zero_vec_cp end | None -> entry_only zero_vec_cp end @@ -91,17 +91,17 @@ struct | Binop (Add, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in - Vector.map2_with (+:) v1 v2; v1 + Vector.map2 (+:) v1 v2 | Binop (Sub, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in - Vector.map2_with (+:) v1 (neg @@ v2); v1 + Vector.map2 (+:) v1 (neg @@ v2) | Binop (Mul, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in begin match to_constant_opt v1, to_constant_opt v2 with - | _, Some c -> Vector.apply_with_c_with ( *:) c v1; v1 - | Some c, _ -> Vector.apply_with_c_with ( *:) c v2; v2 + | _, Some c -> Vector.apply_with_c ( *:) c v1 + | Some c, _ -> Vector.apply_with_c ( *:) c v2 | _, _ -> raise NotLinear end | Binop _ -> raise NotLinear @@ -294,18 +294,17 @@ struct (a, b, max) else ( - Vector.rev_with col_a; - Vector.rev_with col_b; + let col_a = Vector.rev col_a in + let col_b = Vector.rev col_b in let i = Vector.find2i (<>:) col_a col_b in let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in let a_r, b_r = Matrix.get_row a r, Matrix.get_row b r in - Vector.map2_with (-:) col_a col_b; - Vector.rev_with col_a; + let col_a = Vector.map2 (-:) col_a col_b in + let col_a = Vector.rev col_a in let multiply_by_t m t = - Matrix.map2i_with (fun i' x c -> if i' <= max then (let beta = c /: diff in - Vector.map2_with (fun u j -> u -: (beta *: j)) x t); x) m col_a; - m + Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2 (fun u j -> u -: (beta *: j)) x t) else x) m col_a; + in Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) ) From 11e7dcd71733d891e55605150a503d82547ad0d9 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 12 Nov 2024 19:07:36 +0100 Subject: [PATCH 010/240] sparseVector stumb --- src/cdomains/vectorMatrix.ml | 139 +++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 6 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 90ba4f044b..3da2707fe2 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -650,6 +650,138 @@ module ArrayMatrix: AbstractMatrix = end + module SparseVector: AbstractVector = + functor (A: RatOps) -> + struct + include ConvenienceOps (A) + + type t = { + entries: (int * A.t) list ; + len: int + }[@@deriving eq, ord, hash] + + let show v = + failwith "TODO" + + let keep_vals v n = + let rec keep_vals_vec v n = + match v with + | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) + | [] -> [] + in + if n >= v.len then v else (*could be left out but maybe performance??*) + {entries = keep_vals_vec v.entries n; len=n} + + let remove_val v n = + let dec_idx v = + List.map (fun (a,b) -> (a-1, b)) v + in + let rec remove_val_vec v n = + match v with + | x::xs -> + if fst x = n then dec_idx xs else + if fst x > n then dec_idx (x::xs) else + x::(remove_val_vec xs n) + | [] -> [] + in + if n >= v.len then v else (*could be left out but maybe performance??*) + {entries = remove_val_vec v.entries n; len = v.len - 1} + + let set_val v n m = + failwith "TODO" + + let set_val_with v n m = + failwith "TODO" + + let insert_val n m t = + failwith "TODO" + + let apply_with_c f m v = + failwith "TODO" + + let apply_with_c_with f m v = + failwith "TODO" + + let zero_vec n = + failwith "TODO" + + let nth v n = + failwith "TODO" + + let length v = + failwith "TODO" + + let map2 f v v' = + failwith "TODO" + + let map2_with f v v' = + failwith "TODO" + + let findi f v = + failwith "TODO" + + let map f v = + failwith "TODO" + + let map_with f v = + failwith "TODO" + + let compare_length_with v n = + failwith "TODO" + + let of_list l = + failwith "TODO" + + let to_list v = + failwith "TODO" + + let filteri f v = + failwith "TODO" + + let append v v' = + failwith "TODO" + + let exists f v = + failwith "TODO" + + let rev v = + failwith "TODO" + + let rev_with v = + failwith "TODO" + + let map2i f v v' = + failwith "TODO" + + let map2i_with f v v' = + failwith "TODO" + + let mapi f v = + failwith "TODO" + + let mapi_with f v = + failwith "TODO" + + let find2i f v v' = + failwith "TODO" + + let to_array v = + failwith "TODO" + + let of_array a = + failwith "TODO" + + let copy v = v + + let of_sparse_list ls col_count = + failwith "TODO" + + let to_sparse_list v = + failwith "TODO" + + end + + (** Sparse matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) @@ -689,14 +821,9 @@ module SparseMatrix: AbstractMatrix = timing_wrap "copy" (copy) m let add_empty_columns m (cols : int enumerable) = - let colsL = Array.to_list(cols) in + let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in let emptyT = A.zero in let rec list_of_all_before_index idx cols = - (*This should return two arrays - all the idices before idx and all those after, but I'm not sure if inclusive or not - e.g. list_of_all_before_index 3 [1,2,3,4] = ([1,2], [3,4]) or = ([1,2,3], [4]) - right now its of the first form! - *) match cols with | x::xs -> if x < idx From d3b4072a38eedff421ebee33793f84ba132da113 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 14 Nov 2024 16:18:40 +0100 Subject: [PATCH 011/240] Extracted operations --- src/cdomains/affineEquality/convenienceOps.ml | 18 +++++ src/cdomains/affineEquality/ratOps.ml | 18 +++++ .../apron/affineEqualityDomain.apron.ml | 2 + .../apron/linearTwoVarEqualityDomain.apron.ml | 2 + src/cdomains/vectorMatrix.ml | 65 +++++-------------- 5 files changed, 56 insertions(+), 49 deletions(-) create mode 100644 src/cdomains/affineEquality/convenienceOps.ml create mode 100644 src/cdomains/affineEquality/ratOps.ml diff --git a/src/cdomains/affineEquality/convenienceOps.ml b/src/cdomains/affineEquality/convenienceOps.ml new file mode 100644 index 0000000000..39aeeeb5e8 --- /dev/null +++ b/src/cdomains/affineEquality/convenienceOps.ml @@ -0,0 +1,18 @@ +open RatOps + +(** It provides more readable infix operators for the functions of RatOps. + It is designed to be included by modules that make use of RatOps's functions. *) +module ConvenienceOps (A: RatOps) = +struct + let ( *: ) = A.mul + let (+:) = A.add + let (-:) = A.sub + let (/:) = A.div + let (=:) x y = A.equal x y + let (<>:) x y = not (A.equal x y) + let (<:) x y = A.compare x y < 0 + let (>:) x y = A.compare x y > 0 + let (<=:) x y = A.compare x y <= 0 + let (>=:) x y = A.compare x y >= 0 + let of_int x = A.of_int x +end diff --git a/src/cdomains/affineEquality/ratOps.ml b/src/cdomains/affineEquality/ratOps.ml new file mode 100644 index 0000000000..c8d8017693 --- /dev/null +++ b/src/cdomains/affineEquality/ratOps.ml @@ -0,0 +1,18 @@ +(** Abstracts the functions of the Mpqf module for rationals from Apron that implements multi-precision rationals. + One could later exchange "Mpqf" with a different module that provides the functions specified by this interface. *) +module type RatOps = +sig + type t [@@deriving eq, ord, hash] + val add : t -> t -> t + val sub : t -> t -> t + val mul : t -> t -> t + val div : t -> t -> t + val neg : t -> t + val abs : t -> t + val to_string: t -> string + val of_int: int -> t + val zero: t + val one: t + val get_den: t -> Z.t + val get_num: t -> Z.t +end \ No newline at end of file diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 06268130b2..5850568e5b 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -10,7 +10,9 @@ open GoblintCil open Pretty module M = Messages open GobApron + open VectorMatrix +open ConvenienceOps module Mpqf = SharedFunctions.Mpqf diff --git a/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml b/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml index c1ca3661a5..62118a9134 100644 --- a/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml +++ b/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml @@ -12,7 +12,9 @@ open GoblintCil open Pretty module M = Messages open GobApron + open VectorMatrix +open ConvenienceOps module Mpqf = SharedFunctions.Mpqf diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 3da2707fe2..b1fa41fb5e 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -4,47 +4,14 @@ open Batteries module Array = Batteries.Array module M = Messages +open RatOps +open ConvenienceOps + (* let timing_wrap = Timing.wrap *) (* Disable timing of VectorMatrix and AffineEqualityDomain. This is cleaner than a timing functor because the timed functions also call each other. *) let timing_wrap _ f x = f x -(** Abstracts the functions of the Mpqf module for rationals from Apron that implements multi-precision rationals. - One could later exchange "Mpqf" with a different module that provides the functions specified by this interface. *) -module type RatOps = -sig - type t [@@deriving eq, ord, hash] - val add : t -> t -> t - val sub : t -> t -> t - val mul : t -> t -> t - val div : t -> t -> t - val neg : t -> t - val abs : t -> t - val to_string: t -> string - val of_int: int -> t - val zero: t - val one: t - val get_den: t -> Z.t - val get_num: t -> Z.t -end - -(** It provides more readable infix operators for the functions of RatOps. - It is designed to be included by modules that make use of RatOps's functions. *) -module ConvenienceOps (A: RatOps) = -struct - let ( *: ) = A.mul - let (+:) = A.add - let (-:) = A.sub - let (/:) = A.div - let (=:) x y = A.equal x y - let (<>:) x y = not (A.equal x y) - let (<:) x y = A.compare x y < 0 - let (>:) x y = A.compare x y > 0 - let (<=:) x y = A.compare x y <= 0 - let (>=:) x y = A.compare x y >= 0 - let of_int x = A.of_int x -end - (** High-level abstraction of a vector. *) module type Vector = sig @@ -650,11 +617,11 @@ module ArrayMatrix: AbstractMatrix = end - module SparseVector: AbstractVector = +module SparseVector: AbstractVector = functor (A: RatOps) -> struct include ConvenienceOps (A) - + type t = { entries: (int * A.t) list ; len: int @@ -662,15 +629,15 @@ module ArrayMatrix: AbstractMatrix = let show v = failwith "TODO" - + let keep_vals v n = let rec keep_vals_vec v n = - match v with - | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) - | [] -> [] + match v with + | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) + | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = keep_vals_vec v.entries n; len=n} + {entries = keep_vals_vec v.entries n; len=n} let remove_val v n = let dec_idx v = @@ -681,15 +648,15 @@ module ArrayMatrix: AbstractMatrix = | x::xs -> if fst x = n then dec_idx xs else if fst x > n then dec_idx (x::xs) else - x::(remove_val_vec xs n) + x::(remove_val_vec xs n) | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_val_vec v.entries n; len = v.len - 1} + {entries = remove_val_vec v.entries n; len = v.len - 1} let set_val v n m = failwith "TODO" - + let set_val_with v n m = failwith "TODO" @@ -710,7 +677,7 @@ module ArrayMatrix: AbstractMatrix = let length v = failwith "TODO" - + let map2 f v v' = failwith "TODO" @@ -742,7 +709,7 @@ module ArrayMatrix: AbstractMatrix = failwith "TODO" let exists f v = - failwith "TODO" + failwith "TODO" let rev v = failwith "TODO" @@ -770,7 +737,7 @@ module ArrayMatrix: AbstractMatrix = let of_array a = failwith "TODO" - + let copy v = v let of_sparse_list ls col_count = From 7141f97d9858188a51956de721e02520806dddcd Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 14 Nov 2024 18:28:06 +0100 Subject: [PATCH 012/240] Implement normalize SparseMatrix --- src/cdomains/vectorMatrix.ml | 81 ++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 3da2707fe2..2c89f7fcd1 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -475,19 +475,19 @@ module ArrayMatrix: AbstractMatrix = for i = 0 to num_rows-1 do let exception Found in try ( - for j = i to num_cols -2 do + for j = i to num_cols -2 do (* Find pivot *) for k = i to num_rows -1 do if m.(k).(j) <>: A.zero then ( if k <> i then swap_rows k i; let piv = m.(i).(j) in - Array.iteri(fun j' x -> m.(i).(j') <- x /: piv) m.(i); - for l = 0 to num_rows-1 do + Array.iteri(fun j' x -> m.(i).(j') <- x /: piv) m.(i); (* Normalize pivot *) + for l = 0 to num_rows-1 do (* Subtract from each row *) if l <> i && m.(l).(j) <>: A.zero then ( let is_only_zero = ref true in let m_lj = m.(l).(j) in for k = 0 to num_cols - 2 do - m.(l).(k) <- m.(l).(k) -: m.(i).(k) *: m_lj /: m.(i).(j); + m.(l).(k) <- m.(l).(k) -: m.(i).(k) *: m_lj /: m.(i).(j); (* Subtraction *) if m.(l).(k) <>: A.zero then is_only_zero := false; done; let k_end = num_cols - 1 in @@ -650,11 +650,11 @@ module ArrayMatrix: AbstractMatrix = end - module SparseVector: AbstractVector = +module SparseVector: AbstractVector = functor (A: RatOps) -> struct include ConvenienceOps (A) - + type t = { entries: (int * A.t) list ; len: int @@ -662,15 +662,15 @@ module ArrayMatrix: AbstractMatrix = let show v = failwith "TODO" - + let keep_vals v n = let rec keep_vals_vec v n = - match v with - | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) - | [] -> [] + match v with + | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) + | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = keep_vals_vec v.entries n; len=n} + {entries = keep_vals_vec v.entries n; len=n} let remove_val v n = let dec_idx v = @@ -681,15 +681,15 @@ module ArrayMatrix: AbstractMatrix = | x::xs -> if fst x = n then dec_idx xs else if fst x > n then dec_idx (x::xs) else - x::(remove_val_vec xs n) + x::(remove_val_vec xs n) | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_val_vec v.entries n; len = v.len - 1} + {entries = remove_val_vec v.entries n; len = v.len - 1} let set_val v n m = failwith "TODO" - + let set_val_with v n m = failwith "TODO" @@ -710,7 +710,7 @@ module ArrayMatrix: AbstractMatrix = let length v = failwith "TODO" - + let map2 f v v' = failwith "TODO" @@ -742,7 +742,7 @@ module ArrayMatrix: AbstractMatrix = failwith "TODO" let exists f v = - failwith "TODO" + failwith "TODO" let rev v = failwith "TODO" @@ -770,7 +770,7 @@ module ArrayMatrix: AbstractMatrix = let of_array a = failwith "TODO" - + let copy v = v let of_sparse_list ls col_count = @@ -996,6 +996,53 @@ module SparseMatrix: AbstractMatrix = let normalize_with m = timing_wrap "normalize_with" normalize_with m let normalize m = + let entries = m.entries in + let col_count = m.column_count in + let swap_rows m r1_idx r2_idx = + List.mapi (fun i row -> + if i = r1_idx then List.nth m r2_idx + else if i = r2_idx then List.nth m r1_idx + else row + ) entries + in + let sub_rows row pivot_row : (int * A.t) list = + failwith "TODO" + in + let div_row row pivot = + List.map (fun (idx, value) -> (idx, value /: pivot)) row + in + let dec_mat_2D m = + m + in + let rec find_pivot_in_col m row_idx col_idx = + match m with + | ((idx, value)::_)::xs -> if idx = col_idx then Some (row_idx, value) else find_pivot_in_col xs (row_idx + 1) col_idx + | ([])::xs -> find_pivot_in_col xs (row_idx + 1) col_idx + | [] -> None + in + (* let rec find_pivot m col_idx row_idx = + if col_idx >= col_count then None else + match find_pivot_in_col m col_idx row_idx with + | Some (row_idx, value) -> Some (row_idx, value) + | None -> find_pivot m (col_idx + 1) row_idx + in *) + let rec main_loop m m' row_idx col_idx : (int * A.t) list list = + match find_pivot_in_col m' row_idx col_idx with + | None -> ( + if col_idx = (col_count - 1) + then m + else main_loop m m' row_idx (col_idx + 1) + ) + | Some (piv_row_idx, piv_val) -> ( + let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in + let m = List.map (fun row -> div_row row piv_val) m in + let piv_row = (List.nth m row_idx) in + let m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) m in + let m' = dec_mat_2D m in + failwith "TODO" + ) + + in failwith "TODO" let is_covered_by m1 m2 = From 7c2cb083bdb2b6eae2ac206d12c99bdc44b485f9 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 12 Nov 2024 19:07:36 +0100 Subject: [PATCH 013/240] sparseVector stumb --- src/cdomains/vectorMatrix.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 2c89f7fcd1..d71f29e926 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -672,6 +672,7 @@ module SparseVector: AbstractVector = if n >= v.len then v else (*could be left out but maybe performance??*) {entries = keep_vals_vec v.entries n; len=n} + let remove_val v n = let dec_idx v = List.map (fun (a,b) -> (a-1, b)) v @@ -681,15 +682,15 @@ module SparseVector: AbstractVector = | x::xs -> if fst x = n then dec_idx xs else if fst x > n then dec_idx (x::xs) else - x::(remove_val_vec xs n) + x::(remove_val_vec xs n) | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_val_vec v.entries n; len = v.len - 1} + {entries = remove_val_vec v.entries n; len = v.len - 1} let set_val v n m = failwith "TODO" - + let set_val_with v n m = failwith "TODO" @@ -711,7 +712,7 @@ module SparseVector: AbstractVector = let length v = failwith "TODO" - let map2 f v v' = + let map2 f v v' = failwith "TODO" let map2_with f v v' = From 37d1bc0ccc11316a6658795da6515f9a9503aa08 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 12 Nov 2024 18:32:24 +0100 Subject: [PATCH 014/240] Removed some _with functions from the AffineEqualityDomain --- .../apron/affineEqualityDomain.apron.ml | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 06268130b2..aa64b7f741 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -29,7 +29,7 @@ struct m else ( Array.modifyi (+) ch.dim; - let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col_with y x; y) m ch.dim else m in + let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in remove_zero_rows @@ del_cols m' ch.dim) let dim_remove ch m ~del = VectorMatrix.timing_wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del @@ -59,7 +59,7 @@ struct let open Apron.Texpr1 in let exception NotLinear in let zero_vec = Vector.zero_vec @@ Environment.size t.env + 1 in - let neg v = Vector.map_with Mpqf.neg v; v in + let neg v = Vector.map Mpqf.neg v in let is_const_vec v = Vector.compare_length_with (Vector.filteri (fun i x -> (*Inefficient*) Vector.compare_length_with v (i + 1) > 0 && x <>: Mpqf.zero) v) 1 = 0 in @@ -75,13 +75,13 @@ struct Vector.set_val zero_vec ((Vector.length zero_vec) - 1) (of_union x) | Var x -> let zero_vec_cp = Vector.copy zero_vec in - let entry_only v = Vector.set_val_with v (Environment.dim_of_var t.env x) Mpqf.one; v in + let entry_only v = Vector.set_val v (Environment.dim_of_var t.env x) Mpqf.one in begin match t.d with | Some m -> let row = Matrix.find_opt (fun r -> Vector.nth r (Environment.dim_of_var t.env x) =: Mpqf.one) m in begin match row with | Some v when is_const_vec v -> - Vector.set_val_with zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)); zero_vec_cp + Vector.set_val zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)) | _ -> entry_only zero_vec_cp end | None -> entry_only zero_vec_cp end @@ -91,17 +91,17 @@ struct | Binop (Add, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in - Vector.map2_with (+:) v1 v2; v1 + Vector.map2 (+:) v1 v2 | Binop (Sub, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in - Vector.map2_with (+:) v1 (neg @@ v2); v1 + Vector.map2 (+:) v1 (neg @@ v2) | Binop (Mul, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in begin match to_constant_opt v1, to_constant_opt v2 with - | _, Some c -> Vector.apply_with_c_with ( *:) c v1; v1 - | Some c, _ -> Vector.apply_with_c_with ( *:) c v2; v2 + | _, Some c -> Vector.apply_with_c ( *:) c v1 + | Some c, _ -> Vector.apply_with_c ( *:) c v2 | _, _ -> raise NotLinear end | Binop _ -> raise NotLinear @@ -294,18 +294,17 @@ struct (a, b, max) else ( - Vector.rev_with col_a; - Vector.rev_with col_b; + let col_a = Vector.rev col_a in + let col_b = Vector.rev col_b in let i = Vector.find2i (<>:) col_a col_b in let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in let a_r, b_r = Matrix.get_row a r, Matrix.get_row b r in - Vector.map2_with (-:) col_a col_b; - Vector.rev_with col_a; + let col_a = Vector.map2 (-:) col_a col_b in + let col_a = Vector.rev col_a in let multiply_by_t m t = - Matrix.map2i_with (fun i' x c -> if i' <= max then (let beta = c /: diff in - Vector.map2_with (fun u j -> u -: (beta *: j)) x t); x) m col_a; - m + Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2 (fun u j -> u -: (beta *: j)) x t) else x) m col_a; + in Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) ) From 3e159ad5ee2ba7269d90a9b401496c2c1fdf2d13 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 14 Nov 2024 18:28:56 +0100 Subject: [PATCH 015/240] Some Vector Functions --- src/cdomains/vectorMatrix.ml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index d71f29e926..b1aff09538 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -689,8 +689,16 @@ module SparseVector: AbstractVector = {entries = remove_val_vec v.entries n; len = v.len - 1} let set_val v n m = - failwith "TODO" - + let rec set_val_vec v n m = + match v with + | x::xs -> if fst x = n then (n, m)::xs else + if fst x < n then x::(set_val_vec xs n m) + else v + | [] -> [] + in + if n >= v.len then failwith "Out of bounds" else + {entries=set_val_vec v.entries n m; len=v.len} + let set_val_with v n m = failwith "TODO" From 9acc346a2483b5a350afaae27d19beab9a862333 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 15 Nov 2024 15:08:11 +0100 Subject: [PATCH 016/240] Implement some more SparseMatrix functions --- src/cdomains/vectorMatrix.ml | 58 ++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index b1aff09538..bd981b05ae 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -896,7 +896,7 @@ module SparseMatrix: AbstractMatrix = timing_wrap "get_col" (get_col m) n let set_col_with m new_col n = - failwith "TODO" + failwith "Do not use!" let set_col_with m new_col n = timing_wrap "set_col" (set_col_with m new_col) n @@ -915,12 +915,13 @@ module SparseMatrix: AbstractMatrix = {entries = new_entries; column_count = m.column_count} let append_matrices m1 m2 = - failwith "TODO" + let new_entries = List.append m1.entries m2.entries in + {entries = new_entries; column_count = m1.column_count} let equal m1 m2 = timing_wrap "equal" (equal m1) m2 let reduce_col_with m j = - failwith "TODO" + failwith "Do not use!" let reduce_col_with m j = timing_wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = @@ -960,13 +961,26 @@ module SparseMatrix: AbstractMatrix = let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols let map2i f m v = - failwith "TODO" + let f' index row num = V.to_sparse_list @@ f index (V.of_sparse_list row m.column_count) num in + (* TODO: Do we need to consider different lengths here? + let vector_length = List.length (V.to_list v) in + let new_entries = + List.mapi (fun index row -> + if index < vector_length then + let num = V.nth v index in + f' index row num + else row + ) m.entries + in + *) + let new_entries = List.map2i f' m.entries (V.to_list v) in + {entries = new_entries; column_count = m.column_count} let remove_zero_rows m = failwith "TODO" let rref_with m = - failwith "TODO" + failwith "Do not use!" let rref_with m = timing_wrap "rref_with" rref_with m @@ -988,19 +1002,19 @@ module SparseMatrix: AbstractMatrix = (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) - failwith "TODO" + failwith "Do not use!" let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - failwith "TODO" + failwith "Do not use!" let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 let normalize_with m = - failwith "TODO" + failwith "Do not use!" let normalize_with m = timing_wrap "normalize_with" normalize_with m @@ -1054,24 +1068,44 @@ module SparseMatrix: AbstractMatrix = in failwith "TODO" + let is_covered_by m1 m2 = failwith "TODO" let is_covered_by m1 m2 = timing_wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = - failwith "TODO" + let rec find_opt_vec_list f m = + match m with + | [] -> None + | x::xs -> if f x then Some x else find_opt_vec_list f xs + in + let m_vector = List.map (fun row -> V.of_sparse_list row m.column_count) m.entries in + find_opt_vec_list f m_vector let map2 f m v = - failwith "TODO" + let f' row num = V.to_sparse_list @@ f (V.of_sparse_list row m.column_count) num in + (* TODO: Do we need to consider different lengths here? + let vector_length = List.length (V.to_list v) in + let new_entries = + List.mapi (fun index row -> + if index < vector_length then + let num = V.nth v index in + f' row num + else row + ) m.entries + in + *) + let new_entries = List.map2 f' m.entries (V.to_list v) in + {entries = new_entries; column_count = m.column_count} let map2_with f m v = - failwith "TODO" + failwith "Do not use!" let map2_with f m v = timing_wrap "map2_with" (map2_with f m) v let map2i_with f m v = - failwith "TODO" + failwith "Do not use!" let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v end \ No newline at end of file From 128d3680f680b9186c38ab878ecda732f9ac183d Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Mon, 18 Nov 2024 16:38:15 +0100 Subject: [PATCH 017/240] added rref_vec und rref_matrix ohne _with --- src/cdomains/vectorMatrix.ml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index bd981b05ae..34524db06f 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -176,8 +176,12 @@ sig val normalize_with: t -> bool + val rref_vec: t -> vec -> t Option.t (* added to remove side effects in affineEqualityDomain*) + val rref_vec_with: t -> vec -> t Option.t + val rref_matrix: t -> t -> t Option.t (* this as well *) + val rref_matrix_with: t -> t -> t Option.t val find_opt: (vec -> bool) -> t -> vec option @@ -186,7 +190,7 @@ sig val map2_with: (vec -> num -> vec) -> t -> vec -> unit - val map2: (vec -> num -> vec) -> t -> vec -> t + val map2: (vec -> num -> vec) -> t -> vec -> t (* why is this here twice??*) val map2i: (int -> vec-> num -> vec) -> t -> vec -> t @@ -523,7 +527,7 @@ module ArrayMatrix: AbstractMatrix = let pivot_elements = Array.make (num_rows m) 0 in Array.iteri (fun i x -> pivot_elements.(i) <- Array.findi (fun z -> z =: A.one) x) m; pivot_elements - let rref_vec m pivot_positions v = + let rref_vec_helper m pivot_positions v = let insert = ref (-1) in for j = 0 to Array.length v -2 do if v.(j) <>: A.zero then @@ -561,10 +565,15 @@ module ArrayMatrix: AbstractMatrix = Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) else let pivot_elements = get_pivot_positions m in - rref_vec m pivot_elements v + rref_vec_helper m pivot_elements v let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v + let rref_vec m v = (* !! There was another rref_vec function that has been renamed to rref_vec_helper !!*) + let m' = copy m in + let v' = V.copy v in + rref_vec_with m' v' + let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) @@ -574,7 +583,7 @@ module ArrayMatrix: AbstractMatrix = try ( for i = 0 to num_rows s_m - 1 do let pivot_elements = get_pivot_positions !b in - let res = rref_vec !b pivot_elements s_m.(i) in + let res = rref_vec_helper !b pivot_elements s_m.(i) in match res with | None -> raise Unsolvable | Some res -> b := res @@ -585,6 +594,11 @@ module ArrayMatrix: AbstractMatrix = let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 + let rref_matrix m1 m2 = + let m1' = copy m1 in + let m2' = copy m2 in + rref_matrix_with m1' m2' + let normalize_with m = rref_with m From 89588abeaa283c3bfc6c94003664625436d39a0a Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Mon, 18 Nov 2024 16:40:03 +0100 Subject: [PATCH 018/240] added new interface functions to sparsematrix --- src/cdomains/vectorMatrix.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 34524db06f..03ce545ef4 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -1020,6 +1020,8 @@ module SparseMatrix: AbstractMatrix = let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v + let rref_vec m v = failwith "TODO" + let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) @@ -1027,6 +1029,8 @@ module SparseMatrix: AbstractMatrix = let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 + let rref_matrix m1 m2 = failwith "TODO" + let normalize_with m = failwith "Do not use!" From d3477c0f3eebcf1e45528bb5c489b6ee079f6d75 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 19 Nov 2024 15:55:36 +0100 Subject: [PATCH 019/240] implemented reduce_col and remove_zero_rows and fixed some bugs --- src/cdomains/vectorMatrix.ml | 62 +++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 03ce545ef4..8e1bcf8a82 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -696,22 +696,22 @@ module SparseVector: AbstractVector = | x::xs -> if fst x = n then dec_idx xs else if fst x > n then dec_idx (x::xs) else - x::(remove_val_vec xs n) + x::(remove_val_vec xs n) | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_val_vec v.entries n; len = v.len - 1} + {entries = remove_val_vec v.entries n; len = v.len - 1} let set_val v n m = let rec set_val_vec v n m = match v with | x::xs -> if fst x = n then (n, m)::xs else - if fst x < n then x::(set_val_vec xs n m) - else v + if fst x < n then x::(set_val_vec xs n m) + else v | [] -> [] in - if n >= v.len then failwith "Out of bounds" else - {entries=set_val_vec v.entries n m; len=v.len} + if n >= v.len then failwith "Out of bounds" else + {entries=set_val_vec v.entries n m; len=v.len} let set_val_with v n m = failwith "TODO" @@ -734,7 +734,7 @@ module SparseVector: AbstractVector = let length v = failwith "TODO" - let map2 f v v' = + let map2 f v v' = failwith "TODO" let map2_with f v v' = @@ -821,7 +821,7 @@ module SparseMatrix: AbstractMatrix = } [@@deriving eq, ord, hash] let show x = - List.fold_left (^) " " (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) + List.fold_left (^) "" (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) let empty () = {entries = []; column_count = 0} @@ -880,7 +880,7 @@ module SparseMatrix: AbstractMatrix = timing_wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - {entries = m.entries @ [V.to_sparse_list row]; column_count = m.column_count} + {entries = m.entries @ [V.to_sparse_list row]; column_count = V.length row} let get_row m n = V.of_sparse_list (List.nth m.entries n) m.column_count @@ -939,7 +939,43 @@ module SparseMatrix: AbstractMatrix = let reduce_col_with m j = timing_wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = - failwith "TODO" + if is_empty m then m + else + let rec find_pivot idx entries = (* Finds non-zero element in row j and return pair of row idx and the pivot value *) + match entries with + | [] -> None + | row :: rest -> match (List.assoc_opt j row) with + | None -> find_pivot (idx - 1) rest + | Some value -> Some (idx, value) + in + match (find_pivot (num_rows m - 1) (List.rev m.entries)) with + | None -> m (* column is already filled with zeroes *) + | Some (row_idx, pivot) -> + let pivot_row = List.nth m.entries row_idx in + let entries' = + List.mapi(fun idx row -> + if idx = row_idx then + [] + else + match (List.assoc_opt j row) with (* Find column element in row and, if it exists, subtract row *) + | None -> row + | Some row_value -> (let s = row_value /: pivot in + let rec merge acc piv_row cur_row = + match piv_row, cur_row with + | [], [] -> acc + | [], (i, value) :: rest -> merge ((i, value) :: acc) piv_row rest + | (i, value) :: rest, [] -> let new_value = A.zero -: s *: value in merge ((i, new_value) :: acc) rest cur_row + | (i, piv_val) :: piv_rest, (j, cur_val) :: cur_rest -> + if i = j then + let new_value = cur_val -: s *: piv_val in merge ((i, new_value) :: acc) piv_rest cur_rest + else if i < j then + let new_value = A.zero -: s *: piv_val in merge ((i, new_value) :: acc) piv_rest cur_row + else + merge ((j, cur_val) :: acc) piv_row cur_rest + in List.rev @@ merge [] pivot_row row) + ) m.entries + in + {entries = entries'; column_count = m.column_count} let del_col m j = if is_empty m then m else @@ -991,7 +1027,9 @@ module SparseMatrix: AbstractMatrix = {entries = new_entries; column_count = m.column_count} let remove_zero_rows m = - failwith "TODO" + let entries' = List.filter (fun row -> row <> []) m.entries in + if List.length entries' = 0 then empty() else + {entries = entries'; column_count = m.column_count} let rref_with m = failwith "Do not use!" @@ -1002,7 +1040,7 @@ module SparseMatrix: AbstractMatrix = failwith "TODO" - let reduce_col_with_vec m j v = + let reduce_col_with_vec m j v = failwith "TODO" let get_pivot_positions m = From 5a28e34242c084c3b27063c5f77c8b9f0ca97582 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 19 Nov 2024 16:30:47 +0100 Subject: [PATCH 020/240] matrix_normalize_stub --- src/cdomains/vectorMatrix.ml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index b1aff09538..5a4e48e4c2 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -1014,8 +1014,21 @@ module SparseMatrix: AbstractMatrix = else row ) entries in - let sub_rows row pivot_row : (int * A.t) list = - failwith "TODO" + let rec sub_rows minu subt : (int * A.t) list = + match (minu, subt) with + | ((xidx, xv)::xs, (yidx,yv)::ys) -> + if xidx = yidx && xv <> yv + then (xidx, xv -: yv)::(sub_rows xs ys) + else + if xidx < yidx + then (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) + else + if xidx > yidx + then (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) + else sub_rows xs ys + | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) + | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) + | ([],[]) -> [] in let div_row row pivot = List.map (fun (idx, value) -> (idx, value /: pivot)) row From 225c730f658cbaf0f7f389929bce517576d0d10a Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 19 Nov 2024 17:40:05 +0100 Subject: [PATCH 021/240] sexier sub function --- src/cdomains/vectorMatrix.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 6d0be02274..bb992da3da 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -713,8 +713,8 @@ module SparseVector: AbstractVector = if n >= v.len then failwith "Out of bounds" else {entries=set_val_vec v.entries n m; len=v.len} - let set_val_with v n m = - failwith "TODO" + let set_val_with = + failwith "deprecated" let insert_val n m t = failwith "TODO" @@ -800,7 +800,7 @@ module SparseVector: AbstractVector = failwith "TODO" let to_sparse_list v = - failwith "TODO" + v.entries end @@ -1085,19 +1085,15 @@ module SparseMatrix: AbstractMatrix = ) entries in let rec sub_rows minu subt : (int * A.t) list = - match (minu, subt) with - | ((xidx, xv)::xs, (yidx,yv)::ys) -> - if xidx = yidx && xv <> yv - then (xidx, xv -: yv)::(sub_rows xs ys) - else - if xidx < yidx - then (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) - else - if xidx > yidx - then (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) - else sub_rows xs ys - | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) - | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) + match minu, subt with + | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( + match xidx - yidx with + | d when d = 0 && xv <> yv -> (xidx, xv -: yv)::(sub_rows xs ys) + | d when d < 0 -> (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) + | d when d > 0 -> (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) + | _ -> sub_rows xs ys ) (* remove row when is (0, 0) *) + | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) + | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) | ([],[]) -> [] in let div_row row pivot = From 420bde890ec3da76fea21bf81f6e4097ea6f6c6e Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 19 Nov 2024 18:13:42 +0100 Subject: [PATCH 022/240] toMatrix vec funcs --- src/cdomains/vectorMatrix.ml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index bb992da3da..28b89156e9 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -718,6 +718,28 @@ module SparseVector: AbstractVector = let insert_val n m t = failwith "TODO" + + let mul_vec_scal v s = + {entries= (List.map (fun (idx, va) -> (idx, va *: s)) v.entries); len=v.len} + + let add_vec v1 v2 = + let rec add_vec m s = + match m, s with + | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( + match xidx - yidx with + | d when d = 0 && (xv +: yv = A.zero) -> (xidx, xv +: yv)::(add_vec xs ys) + | d when d < 0 -> (xidx, xv)::(add_vec xs ((yidx, yv)::ys)) + | d when d > 0 -> (yidx, yv)::(add_vec ((xidx, xv)::xs) ys) + | _ -> add_vec xs ys ) (* remove row when is (0, 0) *) + | ([], y::ys) -> y::(add_vec [] ys) + | (x::xs, []) -> x::(add_vec xs []) + | ([],[]) -> [] + in + if v1.len <> v2.len then failwith "Different Vector length" else + {entries= add_vec v1.entries v2.entries; len=v1.len} + + let sub_vec v1 v2 = (*change to duplicate def of add if performance*) + add_vec v1 ({entries= (List.map (fun (idx, va) -> (idx, A.zero -: va)) v2.entries); len=v2.len}) let apply_with_c f m v = failwith "TODO" @@ -820,6 +842,8 @@ module SparseMatrix: AbstractMatrix = column_count : int } [@@deriving eq, ord, hash] + let tM e l = {entries= e; column_count=l} + let show x = List.fold_left (^) "" (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) @@ -838,7 +862,7 @@ module SparseMatrix: AbstractMatrix = m.column_count let copy m = - {entries = m.entries; column_count = m.column_count} (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + m (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) let copy m = timing_wrap "copy" (copy) m @@ -874,7 +898,7 @@ module SparseMatrix: AbstractMatrix = match m with | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) | [] -> [] - in {entries = add_empty_columns_on_list m.entries colsL; column_count = m.column_count + Array.length cols} + in tM (add_empty_columns_on_list m.entries colsL) (m.column_count + Array.length cols) let add_empty_columns m (cols : int enumerable) = timing_wrap "add_empty_cols" (add_empty_columns m) cols From 4dbc81f98e527dceb5f312bd28681fe6d9e4189c Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 19 Nov 2024 18:20:11 +0100 Subject: [PATCH 023/240] toVector --- src/cdomains/vectorMatrix.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 28b89156e9..b57b908bc1 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -674,6 +674,7 @@ module SparseVector: AbstractVector = len: int }[@@deriving eq, ord, hash] + let tV e l = {entries=e; len=l} let show v = failwith "TODO" @@ -721,6 +722,7 @@ module SparseVector: AbstractVector = let mul_vec_scal v s = {entries= (List.map (fun (idx, va) -> (idx, va *: s)) v.entries); len=v.len} + let add_vec v1 v2 = let rec add_vec m s = From af2fc0fcd6657d7a6f59ec7434d62a6954a6be21 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 19 Nov 2024 21:13:25 +0100 Subject: [PATCH 024/240] Change of_sparse_list param order and continued normalize function --- src/cdomains/vectorMatrix.ml | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index b57b908bc1..31b33348b8 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -121,7 +121,7 @@ sig val copy: t -> t - val of_sparse_list: (int * num) list -> int -> t + val of_sparse_list: int -> (int * num) list -> t val to_sparse_list: t -> (int * num) list @@ -302,7 +302,7 @@ module ArrayVector: AbstractVector = let copy = copy v in mapi_with f copy; copy - let of_sparse_list ls col_count = + let of_sparse_list col_count ls = let vec = Array.make col_count A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) ls; vec @@ -719,26 +719,26 @@ module SparseVector: AbstractVector = let insert_val n m t = failwith "TODO" - + let mul_vec_scal v s = {entries= (List.map (fun (idx, va) -> (idx, va *: s)) v.entries); len=v.len} - - + + let add_vec v1 v2 = let rec add_vec m s = - match m, s with + match m, s with | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( - match xidx - yidx with - | d when d = 0 && (xv +: yv = A.zero) -> (xidx, xv +: yv)::(add_vec xs ys) - | d when d < 0 -> (xidx, xv)::(add_vec xs ((yidx, yv)::ys)) - | d when d > 0 -> (yidx, yv)::(add_vec ((xidx, xv)::xs) ys) - | _ -> add_vec xs ys ) (* remove row when is (0, 0) *) + match xidx - yidx with + | d when d = 0 && (xv +: yv = A.zero) -> (xidx, xv +: yv)::(add_vec xs ys) + | d when d < 0 -> (xidx, xv)::(add_vec xs ((yidx, yv)::ys)) + | d when d > 0 -> (yidx, yv)::(add_vec ((xidx, xv)::xs) ys) + | _ -> add_vec xs ys ) (* remove row when is (0, 0) *) | ([], y::ys) -> y::(add_vec [] ys) | (x::xs, []) -> x::(add_vec xs []) | ([],[]) -> [] in - if v1.len <> v2.len then failwith "Different Vector length" else - {entries= add_vec v1.entries v2.entries; len=v1.len} + if v1.len <> v2.len then failwith "Different Vector length" else + {entries= add_vec v1.entries v2.entries; len=v1.len} let sub_vec v1 v2 = (*change to duplicate def of add if performance*) add_vec v1 ({entries= (List.map (fun (idx, va) -> (idx, A.zero -: va)) v2.entries); len=v2.len}) @@ -820,8 +820,8 @@ module SparseVector: AbstractVector = let copy v = v - let of_sparse_list ls col_count = - failwith "TODO" + let of_sparse_list col_count ls = + {entries = ls; len = col_count} let to_sparse_list v = v.entries @@ -847,7 +847,7 @@ module SparseMatrix: AbstractMatrix = let tM e l = {entries= e; column_count=l} let show x = - List.fold_left (^) "" (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) + List.fold_left (^) "" (List.map (fun row -> V.show @@ V.of_sparse_list x.column_count row) x.entries) let empty () = {entries = []; column_count = 0} @@ -909,7 +909,7 @@ module SparseMatrix: AbstractMatrix = {entries = m.entries @ [V.to_sparse_list row]; column_count = V.length row} let get_row m n = - V.of_sparse_list (List.nth m.entries n) m.column_count + V.of_sparse_list m.column_count (List.nth m.entries n) let remove_row m n = let rec aux idx entries = match idx, entries with @@ -1037,7 +1037,7 @@ module SparseMatrix: AbstractMatrix = let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols let map2i f m v = - let f' index row num = V.to_sparse_list @@ f index (V.of_sparse_list row m.column_count) num in + let f' index row num = V.to_sparse_list @@ f index (V.of_sparse_list m.column_count row) num in (* TODO: Do we need to consider different lengths here? let vector_length = List.length (V.to_list v) in let new_entries = @@ -1113,11 +1113,11 @@ module SparseMatrix: AbstractMatrix = let rec sub_rows minu subt : (int * A.t) list = match minu, subt with | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( - match xidx - yidx with - | d when d = 0 && xv <> yv -> (xidx, xv -: yv)::(sub_rows xs ys) - | d when d < 0 -> (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) - | d when d > 0 -> (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) - | _ -> sub_rows xs ys ) (* remove row when is (0, 0) *) + match xidx - yidx with + | d when d = 0 && xv <> yv -> (xidx, xv -: yv)::(sub_rows xs ys) + | d when d < 0 -> (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) + | d when d > 0 -> (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) + | _ -> sub_rows xs ys ) (* remove row when is (0, 0) *) | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) | ([],[]) -> [] @@ -1141,23 +1141,23 @@ module SparseMatrix: AbstractMatrix = | None -> find_pivot m (col_idx + 1) row_idx in *) let rec main_loop m m' row_idx col_idx : (int * A.t) list list = - match find_pivot_in_col m' row_idx col_idx with - | None -> ( - if col_idx = (col_count - 1) - then m - else main_loop m m' row_idx (col_idx + 1) - ) - | Some (piv_row_idx, piv_val) -> ( - let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in - let m = List.map (fun row -> div_row row piv_val) m in - let piv_row = (List.nth m row_idx) in - let m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) m in - let m' = dec_mat_2D m in - failwith "TODO" - ) + if col_idx = (col_count - 1) (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) + then m + else + match find_pivot_in_col m' row_idx col_idx with + | None -> main_loop m m' row_idx (col_idx + 1) + | Some (piv_row_idx, piv_val) -> ( + let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in + let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in + let piv_row = (List.nth normalized_m row_idx) in + let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in + let m' = dec_mat_2D m in + main_loop subtracted_m m' (row_idx + 1) (col_idx + 1) + ) in - failwith "TODO" + let e' = main_loop m.entries m.entries 0 0 in + Some {entries = e'; column_count = m.column_count} let is_covered_by m1 m2 = @@ -1171,11 +1171,11 @@ module SparseMatrix: AbstractMatrix = | [] -> None | x::xs -> if f x then Some x else find_opt_vec_list f xs in - let m_vector = List.map (fun row -> V.of_sparse_list row m.column_count) m.entries in + let m_vector = List.map (fun row -> V.of_sparse_list m.column_count row) m.entries in find_opt_vec_list f m_vector let map2 f m v = - let f' row num = V.to_sparse_list @@ f (V.of_sparse_list row m.column_count) num in + let f' row num = V.to_sparse_list @@ f (V.of_sparse_list m.column_count row) num in (* TODO: Do we need to consider different lengths here? let vector_length = List.length (V.to_list v) in let new_entries = From acf5851a89fcfbe878e08e58ae36297ad6f66ce9 Mon Sep 17 00:00:00 2001 From: Havercake Date: Wed, 20 Nov 2024 21:04:06 +0100 Subject: [PATCH 025/240] Split up vectorMatrix into multiple files; Removed VectorMatrix from goblint_lib.ml; Reintroduced Timing.wrap; --- .../apron/affineEqualityAnalysis.apron.ml | 5 +- .../affineEqualityMatrices/abstractMatrix.ml | 11 + .../affineEqualityMatrices/abstractVector.ml | 10 + .../arrayImplementation/arrayMatrix.ml | 341 ++++++ .../arrayImplementation/arrayVector.ml | 106 ++ .../convenienceOps.ml | 0 src/cdomains/affineEqualityMatrices/matrix.ml | 70 ++ .../ratOps.ml | 0 .../sparseImplementation/sparseMatrix.ml | 242 +++++ .../sparseImplementation/sparseVector.ml | 134 +++ src/cdomains/affineEqualityMatrices/vector.ml | 81 ++ .../apron/affineEqualityDomain.apron.ml | 41 +- .../apron/linearTwoVarEqualityDomain.apron.ml | 27 +- src/cdomains/apron/sharedFunctions.apron.ml | 15 +- src/cdomains/vectorMatrix.ml | 988 ------------------ src/goblint_lib.ml | 2 +- 16 files changed, 1044 insertions(+), 1029 deletions(-) create mode 100644 src/cdomains/affineEqualityMatrices/abstractMatrix.ml create mode 100644 src/cdomains/affineEqualityMatrices/abstractVector.ml create mode 100644 src/cdomains/affineEqualityMatrices/arrayImplementation/arrayMatrix.ml create mode 100644 src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml rename src/cdomains/{affineEquality => affineEqualityMatrices}/convenienceOps.ml (100%) create mode 100644 src/cdomains/affineEqualityMatrices/matrix.ml rename src/cdomains/{affineEquality => affineEqualityMatrices}/ratOps.ml (100%) create mode 100644 src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml create mode 100644 src/cdomains/affineEqualityMatrices/sparseImplementation/sparseVector.ml create mode 100644 src/cdomains/affineEqualityMatrices/vector.ml delete mode 100644 src/cdomains/vectorMatrix.ml diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index d4a1e5be2e..73ad59162f 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -4,11 +4,14 @@ open Analyses +open ArrayVector +open ArrayMatrix + include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (VectorMatrix.ArrayVector) (VectorMatrix.ArrayMatrix) in + let module AD = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEqualityMatrices/abstractMatrix.ml b/src/cdomains/affineEqualityMatrices/abstractMatrix.ml new file mode 100644 index 0000000000..64181c1a2b --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/abstractMatrix.ml @@ -0,0 +1,11 @@ +open RatOps +open AbstractVector +open Matrix + +(** Some functions inside have the suffix _with, which means that the function has side effects. *) +module type AbstractMatrix = + functor (A: RatOps) (V: AbstractVector) -> + sig + include Matrix with type vec := V(A).t and type num := A.t + end + diff --git a/src/cdomains/affineEqualityMatrices/abstractVector.ml b/src/cdomains/affineEqualityMatrices/abstractVector.ml new file mode 100644 index 0000000000..e5d7cd40e6 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/abstractVector.ml @@ -0,0 +1,10 @@ +open RatOps +open Vector + +(** Some functions inside have the suffix _with, which means that the function has side effects. *) +module type AbstractVector = + functor (A: RatOps) -> + sig + include Vector with type num:= A.t + end + diff --git a/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayMatrix.ml new file mode 100644 index 0000000000..882e897813 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayMatrix.ml @@ -0,0 +1,341 @@ +open AbstractVector +open RatOps +open ConvenienceOps +open AbstractMatrix + +open Batteries +module Array = Batteries.Array + +(** Array-based matrix implementation. + It provides a normalization function to reduce a matrix into reduced row echelon form. + Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) +module ArrayMatrix: AbstractMatrix = + functor (A: RatOps) (V: AbstractVector) -> + struct + include ConvenienceOps(A) + module V = V(A) + + type t = A.t array array [@@deriving eq, ord, hash] + + let show x = + Array.fold_left (^) "" (Array.map (fun v -> V.show @@ V.of_array v) x) + + let empty () = + Array.make_matrix 0 0 A.zero + + let num_rows m = + Array.length m + + let is_empty m = + (num_rows m = 0) + + let num_cols m = + if is_empty m then 0 else Array.length m.(0) + + let copy m = + let cp = Array.make_matrix (num_rows m) (num_cols m) A.zero in + Array.iteri (fun i x -> Array.blit x 0 cp.(i) 0 (num_cols m)) m; cp + + let copy m = Timing.wrap "copy" (copy) m + + let add_empty_columns m cols = + let nnc = Array.length cols in + if is_empty m || nnc = 0 then m else + let nr, nc = num_rows m, num_cols m in + let m' = Array.make_matrix nr (nc + nnc) A.zero in + for i = 0 to nr - 1 do + let offset = ref 0 in + for j = 0 to nc - 1 do + while !offset < nnc && !offset + j = cols.(!offset) do incr offset done; + m'.(i).(j + !offset) <- m.(i).(j); + done + done; + m' + + let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols + + let append_row m row = + let size = num_rows m in + let new_matrix = Array.make_matrix (size + 1) (num_cols m) A.zero in + for i = 0 to size - 1 do + new_matrix.(i) <- m.(i) + done; + new_matrix.(size) <- V.to_array row; + new_matrix + + let get_row m n = + V.of_array m.(n) + + let remove_row m n = + let new_matrix = Array.make_matrix (num_rows m - 1) (num_cols m) A.zero in + if not @@ is_empty new_matrix then + if n = 0 then + Array.blit m 1 new_matrix 0 (num_rows m - 1) + else + (Array.blit m 0 new_matrix 0 n; + if n <> (num_rows m - 1) then + Array.blit m (n + 1) new_matrix n (num_rows new_matrix - n)); new_matrix + + let get_col m n = + V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)) + + let get_col m n = Timing.wrap "get_col" (get_col m) n + + let set_col_with m new_col n = + for i = 0 to num_rows m - 1 do + m.(i).(n) <- V.nth new_col i + done; m + + let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n + + let set_col m new_col n = + let copy = copy m in + set_col_with copy new_col n + + let append_matrices m1 m2 = + Array.append m1 m2 + + let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 + + let reduce_col_with m j = + if not @@ is_empty m then + (let r = ref (-1) in + for i' = 0 to num_rows m - 1 do + let rev_i' = num_rows m - i' - 1 in + if !r < 0 && m.(rev_i').(j) <>: A.zero then r := rev_i'; + if !r <> rev_i' then + let g = m.(rev_i').(j) in + if g <>: A.zero then + let s = g /: m.(!r).(j) in + for j' = 0 to num_cols m - 1 do + m.(rev_i').(j') <- m.(rev_i').(j') -: s *: m.(!r).(j') + done + done; + if !r >= 0 then Array.fill m.(!r) 0 (num_cols m) A.zero) + + let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j + let reduce_col m j = + let copy = copy m in + reduce_col_with copy j; + copy + + let del_col m j = + if is_empty m then m else + let new_matrix = Array.make_matrix (num_rows m) (num_cols m - 1) A.zero in + for i = 0 to num_rows m - 1 do + new_matrix.(i) <- Array.remove_at j m.(i) + done; new_matrix + + let del_cols m cols = + let n_c = Array.length cols in + if n_c = 0 || is_empty m then m + else + let m_r, m_c = num_rows m, num_cols m in + if m_c = n_c then empty () else + let m' = Array.make_matrix m_r (m_c - n_c) A.zero in + for i = 0 to m_r - 1 do + let offset = ref 0 in + for j = 0 to (m_c - n_c) - 1 do + while !offset < n_c && !offset + j = cols.(!offset) do incr offset done; + m'.(i).(j) <- m.(i).(j + !offset); + done + done; + m' + + let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols + + let map2i f m v = + let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in + let range_array = Array.init (V.length v) Fun.id in + Array.map2 f' m (Array.combine range_array (V.to_array v)) + + let remove_zero_rows m = + Array.filter (fun x -> Array.exists (fun y -> y <>: A.zero) x) m + + let rref_with m = + (*Based on Cousot - Principles of Abstract Interpretation (2021)*) + let swap_rows i1 i2 = + let tmp = m.(i1) in + m.(i1) <- m.(i2); + m.(i2) <- tmp; + in + let exception Unsolvable in + let num_rows = num_rows m in + let num_cols = num_cols m in + try ( + for i = 0 to num_rows-1 do + let exception Found in + try ( + for j = i to num_cols -2 do + for k = i to num_rows -1 do + if m.(k).(j) <>: A.zero then + ( + if k <> i then swap_rows k i; + let piv = m.(i).(j) in + Array.iteri(fun j' x -> m.(i).(j') <- x /: piv) m.(i); + for l = 0 to num_rows-1 do + if l <> i && m.(l).(j) <>: A.zero then ( + let is_only_zero = ref true in + let m_lj = m.(l).(j) in + for k = 0 to num_cols - 2 do + m.(l).(k) <- m.(l).(k) -: m.(i).(k) *: m_lj /: m.(i).(j); + if m.(l).(k) <>: A.zero then is_only_zero := false; + done; + let k_end = num_cols - 1 in + m.(l).(k_end) <- m.(l).(k_end) -: m.(i).(k_end) *: m_lj /: m.(i).(j); + if !is_only_zero && m.(l).(k_end) <>: A.zero then raise Unsolvable; + ) + done; + raise Found + ) + done; + done; + ) + with Found -> () + done; + true) + with Unsolvable -> false + + let rref_with m = Timing.wrap "rref_with" rref_with m + + let init_with_vec v = + let new_matrix = Array.make_matrix 1 (V.length v) A.zero in + new_matrix.(0) <- (V.to_array v); new_matrix + + + let reduce_col_with_vec m j v = + for i = 0 to num_rows m - 1 do + if m.(i).(j) <>: A.zero then + let beta = m.(i).(j) /: v.(j) in + Array.iteri (fun j' x -> m.(i).(j') <- x -: beta *: v.(j')) m.(i) + done + + let get_pivot_positions m = + let pivot_elements = Array.make (num_rows m) 0 + in Array.iteri (fun i x -> pivot_elements.(i) <- Array.findi (fun z -> z =: A.one) x) m; pivot_elements + + let rref_vec m pivot_positions v = + let insert = ref (-1) in + for j = 0 to Array.length v -2 do + if v.(j) <>: A.zero then + match Array.bsearch Int.ord pivot_positions j with + | `At i -> let beta = v.(j) /: m.(i).(j) in + Array.iteri (fun j' x -> v.(j') <- x -: beta *: m.(i).(j')) v + | _ -> if !insert < 0 then (let v_i = v.(j) in + Array.iteri (fun j' x -> v.(j') <- x /: v_i) v; insert := j; + reduce_col_with_vec m j v) + + done; + if !insert < 0 then ( + if v.(Array.length v - 1) <>: A.zero then None + else Some m + ) + else + let new_m = Array.make_matrix (num_rows m + 1) (num_cols m) A.zero + in let (i, j) = Array.pivot_split Int.ord pivot_positions !insert in + if i = 0 && j = 0 then (new_m.(0) <- v; Array.blit m 0 new_m 1 (num_rows m)) + else if i = num_rows m && j = num_rows m then (Array.blit m 0 new_m 0 j; new_m.(j) <- v) + else (Array.blit m 0 new_m 0 i; new_m.(i) <- v; Array.blit m i new_m (i + 1) (Array.length m - j)); + Some new_m + + + let rref_vec_with m v = + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*m must be in rref form and contain the same num of cols as v*) + (*If m is empty then v is simply normalized and returned*) + let v = V.to_array v in + if is_empty m then + match Array.findi (fun x -> x <>: A.zero) v with + | exception Not_found -> None + | i -> if i = Array.length v - 1 then None else + let v_i = v.(i) in + Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) + else + let pivot_elements = get_pivot_positions m in + rref_vec m pivot_elements v + + let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v + + let rref_matrix_with m1 m2 = + (*Similar to rref_vec_with but takes two matrices instead.*) + (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) + let b_m, s_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in + let b = ref b_m in + let exception Unsolvable in + try ( + for i = 0 to num_rows s_m - 1 do + let pivot_elements = get_pivot_positions !b in + let res = rref_vec !b pivot_elements s_m.(i) in + match res with + | None -> raise Unsolvable + | Some res -> b := res + done; + Some !b + ) + with Unsolvable -> None + + let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 + + let normalize_with m = + rref_with m + + let normalize_with m = Timing.wrap "normalize_with" normalize_with m + + let normalize m = + let copy = copy m in + if normalize_with copy then + Some copy + else + None + + let is_covered_by m1 m2 = + (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) + (*Both input matrices must be in rref form!*) + if num_rows m1 > num_rows m2 then false else + let p2 = lazy (get_pivot_positions m2) in + try ( + for i = 0 to num_rows m1 - 1 do + if Array.exists2 (<>:) m1.(i) m2.(i) then + let m1_i = Array.copy m1.(i) in + for j = 0 to Array.length m1_i - 2 do + if m1_i.(j) <>: A.zero then + match Array.bsearch Int.ord (Lazy.force p2) j with + | `At pos -> let beta = m1_i.(j) in + Array.iteri (fun j' x -> m1_i.(j') <- m1_i.(j') -: beta *: m2.(pos).(j') ) m1_i + | _ -> raise Stdlib.Exit; + done; + if m1_i. (num_cols m1 - 1) <>: A.zero then + raise Stdlib.Exit + done; + true + ) + with Stdlib.Exit -> false;; + + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 + + let find_opt f m = + let f' x = f (V.of_array x) in Option.map V.of_array (Array.find_opt f' m) + + let map2 f m v = + let f' x y = V.to_array @@ f (V.of_array x) y in Array.map2 f' m (V.to_array v) + + let map2_with f m v = + if num_rows m = V.length v then + Array.iter2i (fun i x y -> m.(i) <- V.to_array @@ f (V.of_array x) y) m (V.to_array v) + else + for i = 0 to Stdlib.min (num_rows m) (V.length v) -1 do + m.(i) <- V.to_array @@ f (V.of_array m.(i)) (V.nth v i) + done + + let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v + + let map2i_with f m v = + if num_rows m = V.length v then + Array.iter2i (fun i x y -> m.(i) <- V.to_array @@ f i (V.of_array x) y) m (V.to_array v) + else + for i = 0 to Stdlib.min (num_rows m) (V.length v) -1 do + m.(i) <- V.to_array @@ f i (V.of_array m.(i)) (V.nth v i) + done + + let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v + end \ No newline at end of file diff --git a/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml b/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml new file mode 100644 index 0000000000..ca79d90515 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml @@ -0,0 +1,106 @@ +open AbstractVector +open RatOps +open ConvenienceOps + +open Batteries +module Array = Batteries.Array + + +(** Array-based vector implementation. *) +module ArrayVector: AbstractVector = + functor (A: RatOps) -> + struct + include ConvenienceOps (A) + include Array + type t = A.t array [@@deriving eq, ord, hash] + + let show t = + let t = Array.to_list t in + let rec list_str l = + match l with + | [] -> "]" + | x :: xs -> (A.to_string x) ^" "^(list_str xs) + in + "["^list_str t^"\n" + + let keep_vals v n = + if n >= Array.length v then v else + Array.filteri (fun i x -> i < n) v (* TODO: take? *) + + let compare_length_with v len = + Int.compare (Array.length v) len + + let remove_val v n = + if n >= Array.length v then failwith "n outside of Array range" else + Array.init (Array.length v - 1) (fun i -> if i < n then Array.get v i else Array.get v (i + 1)) (* TODO: remove_at? *) + + let set_val_with v n new_val = + if n >= Array.length v then failwith "n outside of Array range" else + Array.set v n new_val + + let set_val v n new_val = + let copy = copy v in + set_val_with copy n new_val; copy + + let insert_val n new_val v = + if n > Array.length v then failwith "n too large" else + Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then new_val else Array.get v (i -1)) (* insert? *) + + let apply_with_c f c v = + Array.map (fun x -> f x c) v + + let zero_vec n = Array.make n A.zero + + let nth = Array.get + + let map2i f v1 v2 = + let f' i = uncurry (f i) in + Array.mapi f' (Array.combine v1 v2) (* TODO: iter2i? *) + + let map2i_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f i x y) v1 v2 + + let find2i f v1 v2 = + Array.findi (uncurry f) (Array.combine v1 v2) (* TODO: iter2i? *) + + let to_array v = v + + let of_array v = v + + let apply_with_c_with f c v = Array.modify (fun x -> f x c) v + + let rev_with v = Array.rev_in_place v + + let rev v = Array.rev v + + let map_with f v = Array.modify f v + + let map f v = Array.map f v + + let map2_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f x y) v1 v2 + + let map2 f v1 v2 = + let copy_v1 = copy v1 in + map2_with f copy_v1 v2; copy_v1 + + let copy v = Array.copy v + + let mapi_with f v = Array.iteri (fun i x -> v.(i) <- f i x) v + + let mapi f v = + let copy = copy v in + mapi_with f copy; copy + + let of_sparse_list ls col_count = + let vec = Array.make col_count A.zero in + List.iter (fun (idx, value) -> vec.(idx) <- value) ls; + vec + + let to_sparse_list v = + let rec aux idx acc = + if idx < 0 then acc + else + let value = v.(idx) in + let acc = if value <> A.zero then (idx, value):: acc else acc in + aux (idx - 1) acc + in aux (length v - 1) [] + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/convenienceOps.ml b/src/cdomains/affineEqualityMatrices/convenienceOps.ml similarity index 100% rename from src/cdomains/affineEquality/convenienceOps.ml rename to src/cdomains/affineEqualityMatrices/convenienceOps.ml diff --git a/src/cdomains/affineEqualityMatrices/matrix.ml b/src/cdomains/affineEqualityMatrices/matrix.ml new file mode 100644 index 0000000000..fac420c5a7 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/matrix.ml @@ -0,0 +1,70 @@ +(** High-level abstraction of a matrix. *) +module type Matrix = +sig + type num + type vec + type t [@@deriving eq, ord, hash] + + val empty: unit -> t (* TODO: needs unit? *) + + val is_empty: t -> bool + + val show: t -> string + + val add_empty_columns: t -> int array -> t + + val append_row: t -> vec -> t + + val get_row: t -> int -> vec + + val del_col: t -> int -> t + + val del_cols: t -> int array -> t + + val remove_row: t -> int -> t + + val get_col: t -> int -> vec + + val append_matrices: t -> t -> t + + val num_rows: t -> int + + val num_cols: t -> int + + val reduce_col: t -> int -> t + + val reduce_col_with: t -> int -> unit + + val normalize: t -> t Option.t (*Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution*) + + val normalize_with: t -> bool + + val rref_vec_with: t -> vec -> t Option.t + + val rref_matrix_with: t -> t -> t Option.t + + val find_opt: (vec -> bool) -> t -> vec option + + val map2: (vec -> num -> vec) -> t -> vec -> t + + val map2_with: (vec -> num -> vec) -> t -> vec -> unit + + val map2: (vec -> num -> vec) -> t -> vec -> t + + val map2i: (int -> vec-> num -> vec) -> t -> vec -> t + + val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit + + val set_col: t -> vec -> int -> t + + val set_col_with: t -> vec -> int -> t + + val init_with_vec: vec -> t + + val remove_zero_rows: t -> t + + val is_covered_by: t -> t -> bool + + val copy: t -> t + +end \ No newline at end of file diff --git a/src/cdomains/affineEquality/ratOps.ml b/src/cdomains/affineEqualityMatrices/ratOps.ml similarity index 100% rename from src/cdomains/affineEquality/ratOps.ml rename to src/cdomains/affineEqualityMatrices/ratOps.ml diff --git a/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml new file mode 100644 index 0000000000..f17b0d5bc9 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml @@ -0,0 +1,242 @@ +open AbstractMatrix +open AbstractVector +open RatOps +open ConvenienceOps + +(** Sparse matrix implementation. + It provides a normalization function to reduce a matrix into reduced row echelon form. + Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) +module SparseMatrix: AbstractMatrix = + functor (A: RatOps) (V: AbstractVector) -> + struct + include ConvenienceOps(A) + module V = V(A) + + (* Array of arrays implementation. One array per row containing tuple of column index and value *) + type t = { + entries : (int * A.t) list list; + column_count : int + } [@@deriving eq, ord, hash] + + let show x = + List.fold_left (^) " " (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) + + let empty () = + {entries = []; column_count = 0} + + let num_rows m = + List.length m.entries + + let is_empty m = + num_rows m = 0 + (*This should be different if the implimentation is sound*) + (*m.column_count = 0*) + + let num_cols m = + m.column_count + + let copy m = + {entries = m.entries; column_count = m.column_count} (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + + let copy m = + Timing.wrap "copy" (copy) m + + let add_empty_columns m cols = + let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in + let emptyT = A.zero in + let rec list_of_all_before_index idx cols = + match cols with + | x::xs -> + if x < idx + then + let (h,t) = list_of_all_before_index idx xs in + (x::h, t) + else ([],x::xs) + | [] -> ([],[]) + in + (*This could easily be abstracted into the above functions, but its nice to have + it here for readability and debugging*) + let rec make_empty_entries_for_idxs idxs = + match idxs with + | x::xs -> (x, emptyT)::(make_empty_entries_for_idxs xs) + | [] -> [] + in + let rec add_column_element r cols = + match r with + | (idx, _)::xs -> + let (bef,aft) = list_of_all_before_index idx cols in + (make_empty_entries_for_idxs bef)@(add_column_element xs aft) + | [] -> [] + in + let rec add_empty_columns_on_list m cols = + match m with + | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) + | [] -> [] + in {entries = add_empty_columns_on_list m.entries colsL; column_count = m.column_count + Array.length cols} + + let add_empty_columns m cols = + Timing.wrap "add_empty_cols" (add_empty_columns m) cols + + let append_row m row = + {entries = m.entries @ [V.to_sparse_list row]; column_count = m.column_count} + + let get_row m n = + V.of_sparse_list (List.nth m.entries n) m.column_count + + let remove_row m n = + let rec aux idx entries = match idx, entries with + | i, x :: xs when i = n -> xs + | _, x :: xs -> x :: aux (idx + 1) xs + | _, _ -> failwith "trying to remove out of bounds row" + in + let new_entries = aux 0 m.entries in + let new_col_count = if new_entries = [] then 0 else m.column_count in + {entries = new_entries; column_count = new_col_count} + + let get_col m n = + (* Uses the fact that row is sorted to return Zero when index n is exceeded *) + let rec get_col_from_row row = + match row with + | [] -> A.zero + | (col_idx, value)::_ when col_idx = n -> value + | (col_idx, _)::_ when col_idx > n -> A.zero + | _::cs -> get_col_from_row cs + in + V.of_list @@ List.map (fun row -> get_col_from_row row ) m.entries + + let get_col m n = + Timing.wrap "get_col" (get_col m) n + + let set_col_with m new_col n = + failwith "TODO" + + let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n + + let set_col m new_col n = + let rec set_col_in_row row value = + match row with + | [] -> if value =: A.zero then [] else [(n, value)] + | (col_idx, v)::cs when col_idx > n -> if value =: A.zero then (col_idx, v)::cs else (n, value)::(col_idx, v)::cs + | (col_idx, v)::cs when col_idx = n -> if value =: A.zero then cs else (n, value)::cs + | (col_idx, v)::cs -> (col_idx, v)::(set_col_in_row cs value) + in + let new_entries = List.mapi (fun row_idx row -> + let value = V.nth new_col row_idx in + set_col_in_row row value + ) m.entries in + {entries = new_entries; column_count = m.column_count} + + let append_matrices m1 m2 = + failwith "TODO" + + let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 + + let reduce_col_with m j = + failwith "TODO" + + let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j + let reduce_col m j = + failwith "TODO" + + let del_col m j = + if is_empty m then m else + let del_col_from_row row = + List.filter_map (fun (col_idx, value) -> + if col_idx = j then + None + else if col_idx > j then + Some (col_idx - 1, value) + else + Some (col_idx, value) + ) row + in + let new_entries = List.map (fun row -> del_col_from_row row) m.entries in + {entries = new_entries; column_count = m.column_count - 1} + + (* TODO: Might be more efficient to check for each entry how much to reduce their index and not by recursively calling del_col *) + let del_cols m cols = + let cols = Array.to_list cols in (* TODO: Get away from Arrays *) + let to_delete_count = List.length cols in + if to_delete_count = 0 || is_empty m then m + else + if num_cols m = to_delete_count then empty () else + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification)*) + let rec del_cols_aux m cols deleted_col_count = + match cols with + | [] -> m + | col_idx::cs -> + let m' = del_col m (col_idx - deleted_col_count) in (* Taking already deleted cols into account because of new index *) + del_cols_aux m' cs (deleted_col_count + 1) + in del_cols_aux m sorted_cols 0 + + let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols + + let map2i f m v = + failwith "TODO" + + let remove_zero_rows m = + failwith "TODO" + + let rref_with m = + failwith "TODO" + + let rref_with m = Timing.wrap "rref_with" rref_with m + + let init_with_vec v = + failwith "TODO" + + + let reduce_col_with_vec m j v = + failwith "TODO" + + let get_pivot_positions m = + failwith "TODO" + + let rref_vec m pivot_positions v = + failwith "TODO" + + + let rref_vec_with m v = + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*m must be in rref form and contain the same num of cols as v*) + (*If m is empty then v is simply normalized and returned*) + failwith "TODO" + + let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v + + let rref_matrix_with m1 m2 = + (*Similar to rref_vec_with but takes two matrices instead.*) + (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) + failwith "TODO" + + let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 + + let normalize_with m = + failwith "TODO" + + let normalize_with m = Timing.wrap "normalize_with" normalize_with m + + let normalize m = + failwith "TODO" + + let is_covered_by m1 m2 = + failwith "TODO" + + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 + + let find_opt f m = + failwith "TODO" + + let map2 f m v = + failwith "TODO" + + let map2_with f m v = + failwith "TODO" + + let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v + + let map2i_with f m v = + failwith "TODO" + + let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v + end \ No newline at end of file diff --git a/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseVector.ml b/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseVector.ml new file mode 100644 index 0000000000..7a2d579b23 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseVector.ml @@ -0,0 +1,134 @@ +open AbstractVector +open RatOps +open ConvenienceOps + +module SparseVector: AbstractVector = + functor (A: RatOps) -> + struct + include ConvenienceOps (A) + + type t = { + entries: (int * A.t) list ; + len: int + }[@@deriving eq, ord, hash] + + let show v = + failwith "TODO" + + let keep_vals v n = + let rec keep_vals_vec v n = + match v with + | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) + | [] -> [] + in + if n >= v.len then v else (*could be left out but maybe performance??*) + {entries = keep_vals_vec v.entries n; len=n} + + let remove_val v n = + let dec_idx v = + List.map (fun (a,b) -> (a-1, b)) v + in + let rec remove_val_vec v n = + match v with + | x::xs -> + if fst x = n then dec_idx xs else + if fst x > n then dec_idx (x::xs) else + x::(remove_val_vec xs n) + | [] -> [] + in + if n >= v.len then v else (*could be left out but maybe performance??*) + {entries = remove_val_vec v.entries n; len = v.len - 1} + + let set_val v n m = + failwith "TODO" + + let set_val_with v n m = + failwith "TODO" + + let insert_val n m t = + failwith "TODO" + + let apply_with_c f m v = + failwith "TODO" + + let apply_with_c_with f m v = + failwith "TODO" + + let zero_vec n = + failwith "TODO" + + let nth v n = + failwith "TODO" + + let length v = + failwith "TODO" + + let map2 f v v' = + failwith "TODO" + + let map2_with f v v' = + failwith "TODO" + + let findi f v = + failwith "TODO" + + let map f v = + failwith "TODO" + + let map_with f v = + failwith "TODO" + + let compare_length_with v n = + failwith "TODO" + + let of_list l = + failwith "TODO" + + let to_list v = + failwith "TODO" + + let filteri f v = + failwith "TODO" + + let append v v' = + failwith "TODO" + + let exists f v = + failwith "TODO" + + let rev v = + failwith "TODO" + + let rev_with v = + failwith "TODO" + + let map2i f v v' = + failwith "TODO" + + let map2i_with f v v' = + failwith "TODO" + + let mapi f v = + failwith "TODO" + + let mapi_with f v = + failwith "TODO" + + let find2i f v v' = + failwith "TODO" + + let to_array v = + failwith "TODO" + + let of_array a = + failwith "TODO" + + let copy v = v + + let of_sparse_list ls col_count = + failwith "TODO" + + let to_sparse_list v = + failwith "TODO" + + end \ No newline at end of file diff --git a/src/cdomains/affineEqualityMatrices/vector.ml b/src/cdomains/affineEqualityMatrices/vector.ml new file mode 100644 index 0000000000..8c9b8a4e33 --- /dev/null +++ b/src/cdomains/affineEqualityMatrices/vector.ml @@ -0,0 +1,81 @@ +(** High-level abstraction of a vector. *) +module type Vector = +sig + type num + type t [@@deriving eq, ord, hash] + + val show: t -> string + + val keep_vals: t -> int -> t + + val remove_val: t -> int -> t + + val set_val: t -> int -> num -> t + + val set_val_with: t -> int -> num -> unit + + val insert_val: int -> num -> t -> t + + val apply_with_c: (num -> num -> num) -> num -> t -> t + + val apply_with_c_with: (num -> num -> num) -> num -> t -> unit + + val zero_vec: int -> t + + val nth: t -> int -> num + + val length: t -> int + + val map2: (num -> num -> num) -> t -> t -> t + + val map2_with: (num -> num -> num) -> t -> t -> unit + + val findi: (num -> bool) -> t -> int + + val map: (num -> num) -> t -> t + + val map_with: (num -> num) -> t -> unit + + val map: (num -> num) -> t -> t + + val compare_length_with: t -> int -> int + + val of_list: num list -> t + + val to_list: t -> num list + + val filteri: (int -> num -> bool) -> t -> t + + val append: t -> t -> t + + val exists: (num -> bool) -> t -> bool + + val rev: t -> t + + val rev_with: t -> unit + + val rev: t -> t + + val map2i: (int -> num -> num -> num) -> t -> t -> t + + val map2i_with: (int -> num -> num -> num) -> t -> t -> unit + + val mapi: (int -> num -> num) -> t -> t + + val mapi_with: (int -> num -> num) -> t -> unit + + val mapi: (int -> num -> num) -> t -> t + + val find2i: (num -> num -> bool) -> t -> t -> int + + val to_array: t -> num array + + val of_array: num array -> t + + val copy: t -> t + + val of_sparse_list: (int * num) list -> int -> t + + val to_sparse_list: t -> (int * num) list + +end \ No newline at end of file diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 5850568e5b..531f914248 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -8,11 +8,16 @@ open GoblintCil open Pretty + module M = Messages open GobApron -open VectorMatrix open ConvenienceOps +open AbstractVector +open AbstractMatrix + +open Batteries +module Array = Batteries.Array module Mpqf = SharedFunctions.Mpqf @@ -23,7 +28,7 @@ struct Array.modifyi (+) ch.dim; add_empty_columns m ch.dim - let dim_add ch m = timing_wrap "dim add" (dim_add ch) m + let dim_add ch m = Timing.wrap "dim add" (dim_add ch) m let dim_remove (ch: Apron.Dim.change) m ~del = @@ -34,7 +39,7 @@ struct let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col_with y x; y) m ch.dim else m in remove_zero_rows @@ del_cols m' ch.dim) - let dim_remove ch m ~del = VectorMatrix.timing_wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del + let dim_remove ch m ~del = Timing.wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del end (** It defines the type t of the affine equality domain (a struct that contains an optional matrix and an apron environment) and provides the functions needed for handling variables (which are defined by RelationDomain.D2) such as add_vars remove_vars. @@ -112,7 +117,7 @@ struct Some (convert_texpr texp) with NotLinear -> None - let get_coeff_vec t texp = timing_wrap "coeff_vec" (get_coeff_vec t) texp + let get_coeff_vec t texp = Timing.wrap "coeff_vec" (get_coeff_vec t) texp end (** As it is specifically used for the new affine equality domain, it can only provide bounds if the expression contains known constants only and in that case, min and max are the same. *) @@ -139,7 +144,7 @@ struct res - let bound_texpr d texpr1 = timing_wrap "bounds calculation" (bound_texpr d) texpr1 + let bound_texpr d texpr1 = Timing.wrap "bounds calculation" (bound_texpr d) texpr1 end module D(Vc: AbstractVector) (Mx: AbstractMatrix) = @@ -194,7 +199,7 @@ struct in let res = (String.concat "" @@ Array.to_list @@ Array.map dim_to_str vars) ^ (const_to_str arr.(Array.length arr - 1)) ^ "=0" in - if String.starts_with res ~prefix:"+" then + if String.starts_with res "+" then Str.string_after res 1 else res @@ -254,7 +259,7 @@ struct if M.tracing then M.tracel "meet" "meet a: %s b: %s -> %s " (show t1) (show t2) (show res) ; res - let meet t1 t2 = timing_wrap "meet" (meet t1) t2 + let meet t1 t2 = Timing.wrap "meet" (meet t1) t2 let leq t1 t2 = let env_comp = Environment.cmp t1.env t2.env in (* Apron's Environment.cmp has defined return values. *) @@ -273,7 +278,7 @@ struct let m1' = if env_comp = 0 then m1 else dim_add (Environment.dimchange t1.env t2.env) m1 in Matrix.is_covered_by m2 m1' - let leq a b = timing_wrap "leq" (leq a) b + let leq a b = Timing.wrap "leq" (leq a) b let leq t1 t2 = let res = leq t1 t2 in @@ -342,7 +347,7 @@ struct | x, y when Matrix.equal x y -> {d = Some x; env = a.env} | x, y -> {d = Some(lin_disjunc 0 0 (Matrix.copy x) (Matrix.copy y)); env = a.env} - let join a b = timing_wrap "join" (join a) b + let join a b = Timing.wrap "join" (join a) b let join a b = let res = join a b in @@ -367,7 +372,7 @@ struct else Matrix.reduce_col x j0 - let remove_rels_with_var x var env inplace = timing_wrap "remove_rels_with_var" (remove_rels_with_var x var env) inplace + let remove_rels_with_var x var env inplace = Timing.wrap "remove_rels_with_var" (remove_rels_with_var x var env) inplace let forget_vars t vars = if is_bot t || is_top_env t || vars = [] then @@ -382,7 +387,7 @@ struct if M.tracing then M.tracel "ops" "forget_vars %s -> %s" (show t) (show res); res - let forget_vars t vars = timing_wrap "forget_vars" (forget_vars t) vars + let forget_vars t vars = Timing.wrap "forget_vars" (forget_vars t) vars let assign_texpr (t: VarManagement(Vc)(Mx).t) var texp = let assign_invertible_rels x var b env = @@ -398,7 +403,7 @@ struct recalc_entries x a_j0; if Matrix.normalize_with x then {d = Some x; env = env} else bot () in - let assign_invertible_rels x var b env = timing_wrap "assign_invertible" (assign_invertible_rels x var b) env in + let assign_invertible_rels x var b env = Timing.wrap "assign_invertible" (assign_invertible_rels x var b) env in let assign_uninvertible_rel x var b env = let b_length = Vector.length b in Vector.mapi_with (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b; @@ -407,7 +412,7 @@ struct if Option.is_none opt_m then bot () else {d = opt_m; env = env} in - (* let assign_uninvertible_rel x var b env = timing_wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) + (* let assign_uninvertible_rel x var b env = Timing.wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) let is_invertible v = Vector.nth v @@ Environment.dim_of_var t.env var <>: Mpqf.zero in let affineEq_vec = get_coeff_vec t texp in if is_bot t then t else let m = Option.get t.d in @@ -418,7 +423,7 @@ struct in assign_uninvertible_rel new_m var v t.env | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env false); env = t.env} - let assign_texpr t var texp = timing_wrap "assign_texpr" (assign_texpr t var) texp + let assign_texpr t var texp = Timing.wrap "assign_texpr" (assign_texpr t var) texp let assign_exp ask (t: VarManagement(Vc)(Mx).t) var exp (no_ov: bool Lazy.t) = let t = if not @@ Environment.mem_var t.env var then add_vars t [var] else t in @@ -472,7 +477,7 @@ struct if M.tracing then M.tracel "ops" "assign_var parallel: %s -> %s " (show t) (show res); res - let assign_var_parallel t vv's = timing_wrap "var_parallel" (assign_var_parallel t) vv's + let assign_var_parallel t vv's = Timing.wrap "var_parallel" (assign_var_parallel t) vv's let assign_var_parallel_with t vv's = let t' = assign_var_parallel t vv's in @@ -502,7 +507,7 @@ struct if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %a \n exp: %a \n -> \n %s" (show t) Var.pretty var d_exp exp (show res); res - let substitute_exp ask t var exp no_ov = timing_wrap "substitution" (substitute_exp ask t var exp) no_ov + let substitute_exp ask t var exp no_ov = Timing.wrap "substitution" (substitute_exp ask t var exp) no_ov (** Assert a constraint expression. @@ -547,7 +552,7 @@ struct end | None -> t - let meet_tcons t tcons expr = timing_wrap "meet_tcons" (meet_tcons t tcons) expr + let meet_tcons t tcons expr = Timing.wrap "meet_tcons" (meet_tcons t tcons) expr let unify a b = meet a b @@ -563,7 +568,7 @@ struct | tcons1 -> meet_tcons ask d tcons1 e | exception Convert.Unsupported_CilExp _ -> d - let assert_constraint ask d e negate no_ov = timing_wrap "assert_constraint" (assert_constraint ask d e negate) no_ov + let assert_constraint ask d e negate no_ov = Timing.wrap "assert_constraint" (assert_constraint ask d e negate) no_ov let relift t = t diff --git a/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml b/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml index 62118a9134..72f24610c6 100644 --- a/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml +++ b/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml @@ -13,7 +13,6 @@ open Pretty module M = Messages open GobApron -open VectorMatrix open ConvenienceOps module Mpqf = SharedFunctions.Mpqf @@ -175,7 +174,7 @@ module EqualitiesConjunction = struct let dim_add (ch: Apron.Dim.change) m = modify_variables_in_domain m ch.dim (+) - let dim_add ch m = timing_wrap "dim add" (dim_add ch) m + let dim_add ch m = Timing.wrap "dim add" (dim_add ch) m let dim_remove (ch: Apron.Dim.change) m = if Array.length ch.dim = 0 || is_empty m then @@ -186,7 +185,7 @@ module EqualitiesConjunction = struct let m' = Array.fold_lefti (fun y i x -> forget_variable y (x)) m cpy in (* clear m' from relations concerning ch.dim *) modify_variables_in_domain m' cpy (-)) - let dim_remove ch m = VectorMatrix.timing_wrap "dim remove" (fun m -> dim_remove ch m) m + let dim_remove ch m = Timing.wrap "dim remove" (fun m -> dim_remove ch m) m let dim_remove ch m ~del = let res = dim_remove ch m in if M.tracing then M.tracel "dim_remove" "dim remove at positions [%s] in { %s } -> { %s }" @@ -345,7 +344,7 @@ struct | [(coeff,var,divi)] -> Some (Rhs.canonicalize (Some (Z.mul divisor coeff,var), Z.mul constant divi,Z.mul divisor divi)) |_ -> None)) - let simplify_to_ref_and_offset t texp = timing_wrap "coeff_vec" (simplify_to_ref_and_offset t) texp + let simplify_to_ref_and_offset t texp = Timing.wrap "coeff_vec" (simplify_to_ref_and_offset t) texp let assign_const t var const divi = match t.d with | None -> t @@ -367,7 +366,7 @@ struct Some res, Some res) | _ -> None, None - let bound_texpr d texpr1 = timing_wrap "bounds calculation" (bound_texpr d) texpr1 + let bound_texpr d texpr1 = Timing.wrap "bounds calculation" (bound_texpr d) texpr1 end module D = @@ -458,7 +457,7 @@ struct if M.tracing then M.tracel "meet" "meet a: %s\n U \n b: %s \n -> %s" (show t1) (show t2) (show res) ; res - let meet t1 t2 = timing_wrap "meet" (meet t1) t2 + let meet t1 t2 = Timing.wrap "meet" (meet t1) t2 let leq t1 t2 = let env_comp = Environment.cmp t1.env t2.env in (* Apron's Environment.cmp has defined return values. *) @@ -477,7 +476,7 @@ struct let m1' = if env_comp = 0 then m1 else VarManagement.dim_add (Environment.dimchange t1.env t2.env) m1 in EConj.IntMap.for_all (implies m1') (snd m2) (* even on sparse m2, it suffices to check the non-trivial equalities, still present in sparse m2 *) - let leq a b = timing_wrap "leq" (leq a) b + let leq a b = Timing.wrap "leq" (leq a) b let leq t1 t2 = let res = leq t1 t2 in @@ -553,7 +552,7 @@ struct | Some x, Some y when EConj.equal x y -> {d = Some x; env = a.env} | Some x, Some y -> {d = join_d x y; env = a.env} - let join a b = timing_wrap "join" (join a) b + let join a b = Timing.wrap "join" (join a) b let join a b = let res = join a b in @@ -595,7 +594,7 @@ struct if M.tracing then M.tracel "ops" "forget_vars %s -> %s" (show t) (show res); res - let forget_vars t vars = timing_wrap "forget_vars" (forget_vars t) vars + let forget_vars t vars = Timing.wrap "forget_vars" (forget_vars t) vars (** implemented as described on page 10 in the paper about Fast Interprocedural Linear Two-Variable Equalities in the Section "Abstract Effect of Statements" This makes a copy of the data structure, it doesn't change it in-place. *) @@ -619,7 +618,7 @@ struct end | None -> bot_env - let assign_texpr t var texp = timing_wrap "assign_texpr" (assign_texpr t var) texp + let assign_texpr t var texp = Timing.wrap "assign_texpr" (assign_texpr t var) texp (* no_ov -> no overflow if it's true then there is no overflow @@ -666,7 +665,7 @@ struct if M.tracing then M.tracel "ops" "assign_var parallel: %s -> %s" (show t) (show res); res - let assign_var_parallel t vv's = timing_wrap "var_parallel" (assign_var_parallel t) vv's + let assign_var_parallel t vv's = Timing.wrap "var_parallel" (assign_var_parallel t) vv's let assign_var_parallel_with t vv's = (* TODO: If we are angling for more performance, this might be a good place ot try. `assign_var_parallel_with` is used whenever a function is entered (body), @@ -698,7 +697,7 @@ struct if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %a \n exp: %a \n -> \n %s" (show t) Var.pretty var d_exp exp (show res); res - let substitute_exp ask t var exp no_ov = timing_wrap "substitution" (substitute_exp ask t var exp) no_ov + let substitute_exp ask t var exp no_ov = Timing.wrap "substitution" (substitute_exp ask t var exp) no_ov (** Assert a constraint expression. @@ -753,7 +752,7 @@ struct if M.tracing then M.tracel "meet_tcons" "meet_tcons with expr: %a no_ov:%b" d_exp original_expr (Lazy.force no_ov); meet_tcons ask t tcons original_expr no_ov - let meet_tcons t tcons expr = timing_wrap "meet_tcons" (meet_tcons t tcons) expr + let meet_tcons t tcons expr = Timing.wrap "meet_tcons" (meet_tcons t tcons) expr let unify a b = meet a b @@ -779,7 +778,7 @@ struct | tcons1 -> meet_tcons ask d tcons1 e no_ov | exception Convert.Unsupported_CilExp _ -> d - let assert_constraint ask d e negate no_ov = timing_wrap "assert_constraint" (assert_constraint ask d e negate) no_ov + let assert_constraint ask d e negate no_ov = Timing.wrap "assert_constraint" (assert_constraint ask d e negate) no_ov let relift t = t diff --git a/src/cdomains/apron/sharedFunctions.apron.ml b/src/cdomains/apron/sharedFunctions.apron.ml index 86b5f2770f..bda88a3f62 100644 --- a/src/cdomains/apron/sharedFunctions.apron.ml +++ b/src/cdomains/apron/sharedFunctions.apron.ml @@ -4,6 +4,7 @@ open Batteries open GobApron + module M = Messages @@ -402,7 +403,7 @@ struct in {d = Some (if add then RelDomain.dim_add dim_change m else RelDomain.dim_remove dim_change m ~del:del); env = new_env} - let change_d t new_env ~add ~del = VectorMatrix.timing_wrap "dimension change" (fun del -> change_d t new_env ~add:add ~del:del) del + let change_d t new_env ~add ~del = Timing.wrap "dimension change" (fun del -> change_d t new_env ~add:add ~del:del) del let vars x = Environment.ivars_only x.env @@ -411,18 +412,18 @@ struct let env' = Environment.add_vars t.env vars in change_d t env' ~add:true ~del:false - let add_vars t vars = VectorMatrix.timing_wrap "add_vars" (add_vars t) vars + let add_vars t vars = Timing.wrap "add_vars" (add_vars t) vars let drop_vars t vars ~del = let t = copy t in let env' = Environment.remove_vars t.env vars in change_d t env' ~add:false ~del:del - let drop_vars t vars = VectorMatrix.timing_wrap "drop_vars" (drop_vars t) vars + let drop_vars t vars = Timing.wrap "drop_vars" (drop_vars t) vars let remove_vars t vars = drop_vars t vars ~del:false - let remove_vars t vars = VectorMatrix.timing_wrap "remove_vars" (remove_vars t) vars + let remove_vars t vars = Timing.wrap "remove_vars" (remove_vars t) vars let remove_vars_with t vars = let t' = remove_vars t vars in @@ -433,7 +434,7 @@ struct let env' = Environment.remove_filter t.env f in change_d t env' ~add:false ~del:false - let remove_filter t f = VectorMatrix.timing_wrap "remove_filter" (remove_filter t) f + let remove_filter t f = Timing.wrap "remove_filter" (remove_filter t) f let remove_filter_with t f = let t' = remove_filter t f in @@ -445,14 +446,14 @@ struct let env' = Environment.keep_filter t.env f in change_d t env' ~add:false ~del:false - let keep_filter t f = VectorMatrix.timing_wrap "keep_filter" (keep_filter t) f + let keep_filter t f = Timing.wrap "keep_filter" (keep_filter t) f let keep_vars t vs = let t = copy t in let env' = Environment.keep_vars t.env vs in change_d t env' ~add:false ~del:false - let keep_vars t vs = VectorMatrix.timing_wrap "keep_vars" (keep_vars t) vs + let keep_vars t vs = Timing.wrap "keep_vars" (keep_vars t) vs let mem_var t var = Environment.mem_var t.env var diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml deleted file mode 100644 index b1fa41fb5e..0000000000 --- a/src/cdomains/vectorMatrix.ml +++ /dev/null @@ -1,988 +0,0 @@ -(** OCaml implementations of vectors and matrices. *) - -open Batteries -module Array = Batteries.Array -module M = Messages - -open RatOps -open ConvenienceOps - -(* let timing_wrap = Timing.wrap *) -(* Disable timing of VectorMatrix and AffineEqualityDomain. - This is cleaner than a timing functor because the timed functions also call each other. *) -let timing_wrap _ f x = f x - -(** High-level abstraction of a vector. *) -module type Vector = -sig - type num - type t [@@deriving eq, ord, hash] - - val show: t -> string - - val keep_vals: t -> int -> t - - val remove_val: t -> int -> t - - val set_val: t -> int -> num -> t - - val set_val_with: t -> int -> num -> unit - - val insert_val: int -> num -> t -> t - - val apply_with_c: (num -> num -> num) -> num -> t -> t - - val apply_with_c_with: (num -> num -> num) -> num -> t -> unit - - val zero_vec: int -> t - - val nth: t -> int -> num - - val length: t -> int - - val map2: (num -> num -> num) -> t -> t -> t - - val map2_with: (num -> num -> num) -> t -> t -> unit - - val findi: (num -> bool) -> t -> int - - val map: (num -> num) -> t -> t - - val map_with: (num -> num) -> t -> unit - - val map: (num -> num) -> t -> t - - val compare_length_with: t -> int -> int - - val of_list: num list -> t - - val to_list: t -> num list - - val filteri: (int -> num -> bool) -> t -> t - - val append: t -> t -> t - - val exists: (num -> bool) -> t -> bool - - val rev: t -> t - - val rev_with: t -> unit - - val rev: t -> t - - val map2i: (int -> num -> num -> num) -> t -> t -> t - - val map2i_with: (int -> num -> num -> num) -> t -> t -> unit - - val mapi: (int -> num -> num) -> t -> t - - val mapi_with: (int -> num -> num) -> t -> unit - - val mapi: (int -> num -> num) -> t -> t - - val find2i: (num -> num -> bool) -> t -> t -> int - - val to_array: t -> num array - - val of_array: num array -> t - - val copy: t -> t - - val of_sparse_list: (int * num) list -> int -> t - - val to_sparse_list: t -> (int * num) list - -end - -(** Some functions inside have the suffix _with, which means that the function has side effects. *) -module type AbstractVector = - functor (A: RatOps) -> - sig - include Vector with type num:= A.t - end - - -(** High-level abstraction of a matrix. *) -module type Matrix = -sig - type num - type vec - type t [@@deriving eq, ord, hash] - - val empty: unit -> t (* TODO: needs unit? *) - - val is_empty: t -> bool - - val show: t -> string - - val add_empty_columns: t -> int array -> t - - val append_row: t -> vec -> t - - val get_row: t -> int -> vec - - val del_col: t -> int -> t - - val del_cols: t -> int array -> t - - val remove_row: t -> int -> t - - val get_col: t -> int -> vec - - val append_matrices: t -> t -> t - - val num_rows: t -> int - - val num_cols: t -> int - - val reduce_col: t -> int -> t - - val reduce_col_with: t -> int -> unit - - val normalize: t -> t Option.t (*Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution*) - - val normalize_with: t -> bool - - val rref_vec_with: t -> vec -> t Option.t - - val rref_matrix_with: t -> t -> t Option.t - - val find_opt: (vec -> bool) -> t -> vec option - - val map2: (vec -> num -> vec) -> t -> vec -> t - - val map2_with: (vec -> num -> vec) -> t -> vec -> unit - - val map2: (vec -> num -> vec) -> t -> vec -> t - - val map2i: (int -> vec-> num -> vec) -> t -> vec -> t - - val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit - - val set_col: t -> vec -> int -> t - - val set_col_with: t -> vec -> int -> t - - val init_with_vec: vec -> t - - val remove_zero_rows: t -> t - - val is_covered_by: t -> t -> bool - - val copy: t -> t - -end - -(** Some functions inside have the suffix _with, which means that the function has side effects. *) -module type AbstractMatrix = - functor (A: RatOps) (V: AbstractVector) -> - sig - include Matrix with type vec := V(A).t and type num := A.t - end - - -(** Array-based vector implementation. *) -module ArrayVector: AbstractVector = - functor (A: RatOps) -> - struct - include ConvenienceOps (A) - include Array - type t = A.t array [@@deriving eq, ord, hash] - - let show t = - let t = Array.to_list t in - let rec list_str l = - match l with - | [] -> "]" - | x :: xs -> (A.to_string x) ^" "^(list_str xs) - in - "["^list_str t^"\n" - - let keep_vals v n = - if n >= Array.length v then v else - Array.filteri (fun i x -> i < n) v (* TODO: take? *) - - let compare_length_with v len = - Int.compare (Array.length v) len - - let remove_val v n = - if n >= Array.length v then failwith "n outside of Array range" else - Array.init (Array.length v - 1) (fun i -> if i < n then Array.get v i else Array.get v (i + 1)) (* TODO: remove_at? *) - - let set_val_with v n new_val = - if n >= Array.length v then failwith "n outside of Array range" else - Array.set v n new_val - - let set_val v n new_val = - let copy = copy v in - set_val_with copy n new_val; copy - - let insert_val n new_val v = - if n > Array.length v then failwith "n too large" else - Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then new_val else Array.get v (i -1)) (* insert? *) - - let apply_with_c f c v = - Array.map (fun x -> f x c) v - - let zero_vec n = Array.make n A.zero - - let nth = Array.get - - let map2i f v1 v2 = - let f' i = uncurry (f i) in - Array.mapi f' (Array.combine v1 v2) (* TODO: iter2i? *) - - let map2i_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f i x y) v1 v2 - - let find2i f v1 v2 = - Array.findi (uncurry f) (Array.combine v1 v2) (* TODO: iter2i? *) - - let to_array v = v - - let of_array v = v - - let apply_with_c_with f c v = Array.modify (fun x -> f x c) v - - let rev_with v = Array.rev_in_place v - - let rev v = Array.rev v - - let map_with f v = Array.modify f v - - let map f v = Array.map f v - - let map2_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f x y) v1 v2 - - let map2 f v1 v2 = - let copy_v1 = copy v1 in - map2_with f copy_v1 v2; copy_v1 - - let copy v = Array.copy v - - let mapi_with f v = Array.iteri (fun i x -> v.(i) <- f i x) v - - let mapi f v = - let copy = copy v in - mapi_with f copy; copy - - let of_sparse_list ls col_count = - let vec = Array.make col_count A.zero in - List.iter (fun (idx, value) -> vec.(idx) <- value) ls; - vec - - let to_sparse_list v = - let rec aux idx acc = - if idx < 0 then acc - else - let value = v.(idx) in - let acc = if value <> A.zero then (idx, value):: acc else acc in - aux (idx - 1) acc - in aux (length v - 1) [] - end - -open Batteries.Array - -(** Array-based matrix implementation. - It provides a normalization function to reduce a matrix into reduced row echelon form. - Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) -module ArrayMatrix: AbstractMatrix = - functor (A: RatOps) (V: AbstractVector) -> - struct - include ConvenienceOps(A) - module V = V(A) - - type t = A.t array array [@@deriving eq, ord, hash] - - let show x = - Array.fold_left (^) "" (Array.map (fun v -> V.show @@ V.of_array v) x) - - let empty () = - Array.make_matrix 0 0 A.zero - - let num_rows m = - Array.length m - - let is_empty m = - (num_rows m = 0) - - let num_cols m = - if is_empty m then 0 else Array.length m.(0) - - let copy m = - let cp = Array.make_matrix (num_rows m) (num_cols m) A.zero in - Array.iteri (fun i x -> Array.blit x 0 cp.(i) 0 (num_cols m)) m; cp - - let copy m = timing_wrap "copy" (copy) m - - let add_empty_columns m cols = - let nnc = Array.length cols in - if is_empty m || nnc = 0 then m else - let nr, nc = num_rows m, num_cols m in - let m' = make_matrix nr (nc + nnc) A.zero in - for i = 0 to nr - 1 do - let offset = ref 0 in - for j = 0 to nc - 1 do - while !offset < nnc && !offset + j = cols.(!offset) do incr offset done; - m'.(i).(j + !offset) <- m.(i).(j); - done - done; - m' - - let add_empty_columns m cols = timing_wrap "add_empty_cols" (add_empty_columns m) cols - - let append_row m row = - let size = num_rows m in - let new_matrix = make_matrix (size + 1) (num_cols m) A.zero in - for i = 0 to size - 1 do - new_matrix.(i) <- m.(i) - done; - new_matrix.(size) <- V.to_array row; - new_matrix - - let get_row m n = - V.of_array m.(n) - - let remove_row m n = - let new_matrix = make_matrix (num_rows m - 1) (num_cols m) A.zero in - if not @@ is_empty new_matrix then - if n = 0 then - Array.blit m 1 new_matrix 0 (num_rows m - 1) - else - (Array.blit m 0 new_matrix 0 n; - if n <> (num_rows m - 1) then - Array.blit m (n + 1) new_matrix n (num_rows new_matrix - n)); new_matrix - - let get_col m n = - V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)) - - let get_col m n = timing_wrap "get_col" (get_col m) n - - let set_col_with m new_col n = - for i = 0 to num_rows m - 1 do - m.(i).(n) <- V.nth new_col i - done; m - - let set_col_with m new_col n = timing_wrap "set_col" (set_col_with m new_col) n - - let set_col m new_col n = - let copy = copy m in - set_col_with copy new_col n - - let append_matrices m1 m2 = - Array.append m1 m2 - - let equal m1 m2 = timing_wrap "equal" (equal m1) m2 - - let reduce_col_with m j = - if not @@ is_empty m then - (let r = ref (-1) in - for i' = 0 to num_rows m - 1 do - let rev_i' = num_rows m - i' - 1 in - if !r < 0 && m.(rev_i').(j) <>: A.zero then r := rev_i'; - if !r <> rev_i' then - let g = m.(rev_i').(j) in - if g <>: A.zero then - let s = g /: m.(!r).(j) in - for j' = 0 to num_cols m - 1 do - m.(rev_i').(j') <- m.(rev_i').(j') -: s *: m.(!r).(j') - done - done; - if !r >= 0 then Array.fill m.(!r) 0 (num_cols m) A.zero) - - let reduce_col_with m j = timing_wrap "reduce_col_with" (reduce_col_with m) j - let reduce_col m j = - let copy = copy m in - reduce_col_with copy j; - copy - - let del_col m j = - if is_empty m then m else - let new_matrix = Array.make_matrix (num_rows m) (num_cols m - 1) A.zero in - for i = 0 to num_rows m - 1 do - new_matrix.(i) <- Array.remove_at j m.(i) - done; new_matrix - - let del_cols m cols = - let n_c = Array.length cols in - if n_c = 0 || is_empty m then m - else - let m_r, m_c = num_rows m, num_cols m in - if m_c = n_c then empty () else - let m' = Array.make_matrix m_r (m_c - n_c) A.zero in - for i = 0 to m_r - 1 do - let offset = ref 0 in - for j = 0 to (m_c - n_c) - 1 do - while !offset < n_c && !offset + j = cols.(!offset) do incr offset done; - m'.(i).(j) <- m.(i).(j + !offset); - done - done; - m' - - let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols - - let map2i f m v = - let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in - let range_array = Array.init (V.length v) Fun.id in - Array.map2 f' m (Array.combine range_array (V.to_array v)) - - let remove_zero_rows m = - Array.filter (fun x -> Array.exists (fun y -> y <>: A.zero) x) m - - let rref_with m = - (*Based on Cousot - Principles of Abstract Interpretation (2021)*) - let swap_rows i1 i2 = - let tmp = m.(i1) in - m.(i1) <- m.(i2); - m.(i2) <- tmp; - in - let exception Unsolvable in - let num_rows = num_rows m in - let num_cols = num_cols m in - try ( - for i = 0 to num_rows-1 do - let exception Found in - try ( - for j = i to num_cols -2 do - for k = i to num_rows -1 do - if m.(k).(j) <>: A.zero then - ( - if k <> i then swap_rows k i; - let piv = m.(i).(j) in - Array.iteri(fun j' x -> m.(i).(j') <- x /: piv) m.(i); - for l = 0 to num_rows-1 do - if l <> i && m.(l).(j) <>: A.zero then ( - let is_only_zero = ref true in - let m_lj = m.(l).(j) in - for k = 0 to num_cols - 2 do - m.(l).(k) <- m.(l).(k) -: m.(i).(k) *: m_lj /: m.(i).(j); - if m.(l).(k) <>: A.zero then is_only_zero := false; - done; - let k_end = num_cols - 1 in - m.(l).(k_end) <- m.(l).(k_end) -: m.(i).(k_end) *: m_lj /: m.(i).(j); - if !is_only_zero && m.(l).(k_end) <>: A.zero then raise Unsolvable; - ) - done; - raise Found - ) - done; - done; - ) - with Found -> () - done; - true) - with Unsolvable -> false - - let rref_with m = timing_wrap "rref_with" rref_with m - - let init_with_vec v = - let new_matrix = Array.make_matrix 1 (V.length v) A.zero in - new_matrix.(0) <- (V.to_array v); new_matrix - - - let reduce_col_with_vec m j v = - for i = 0 to num_rows m - 1 do - if m.(i).(j) <>: A.zero then - let beta = m.(i).(j) /: v.(j) in - Array.iteri (fun j' x -> m.(i).(j') <- x -: beta *: v.(j')) m.(i) - done - - let get_pivot_positions m = - let pivot_elements = Array.make (num_rows m) 0 - in Array.iteri (fun i x -> pivot_elements.(i) <- Array.findi (fun z -> z =: A.one) x) m; pivot_elements - - let rref_vec m pivot_positions v = - let insert = ref (-1) in - for j = 0 to Array.length v -2 do - if v.(j) <>: A.zero then - match Array.bsearch Int.ord pivot_positions j with - | `At i -> let beta = v.(j) /: m.(i).(j) in - Array.iteri (fun j' x -> v.(j') <- x -: beta *: m.(i).(j')) v - | _ -> if !insert < 0 then (let v_i = v.(j) in - Array.iteri (fun j' x -> v.(j') <- x /: v_i) v; insert := j; - reduce_col_with_vec m j v) - - done; - if !insert < 0 then ( - if v.(Array.length v - 1) <>: A.zero then None - else Some m - ) - else - let new_m = Array.make_matrix (num_rows m + 1) (num_cols m) A.zero - in let (i, j) = Array.pivot_split Int.ord pivot_positions !insert in - if i = 0 && j = 0 then (new_m.(0) <- v; Array.blit m 0 new_m 1 (num_rows m)) - else if i = num_rows m && j = num_rows m then (Array.blit m 0 new_m 0 j; new_m.(j) <- v) - else (Array.blit m 0 new_m 0 i; new_m.(i) <- v; Array.blit m i new_m (i + 1) (Array.length m - j)); - Some new_m - - - let rref_vec_with m v = - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) - (*m must be in rref form and contain the same num of cols as v*) - (*If m is empty then v is simply normalized and returned*) - let v = V.to_array v in - if is_empty m then - match Array.findi (fun x -> x <>: A.zero) v with - | exception Not_found -> None - | i -> if i = Array.length v - 1 then None else - let v_i = v.(i) in - Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) - else - let pivot_elements = get_pivot_positions m in - rref_vec m pivot_elements v - - let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v - - let rref_matrix_with m1 m2 = - (*Similar to rref_vec_with but takes two matrices instead.*) - (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - let b_m, s_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in - let b = ref b_m in - let exception Unsolvable in - try ( - for i = 0 to num_rows s_m - 1 do - let pivot_elements = get_pivot_positions !b in - let res = rref_vec !b pivot_elements s_m.(i) in - match res with - | None -> raise Unsolvable - | Some res -> b := res - done; - Some !b - ) - with Unsolvable -> None - - let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 - - let normalize_with m = - rref_with m - - let normalize_with m = timing_wrap "normalize_with" normalize_with m - - let normalize m = - let copy = copy m in - if normalize_with copy then - Some copy - else - None - - let is_covered_by m1 m2 = - (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) - (*Both input matrices must be in rref form!*) - if num_rows m1 > num_rows m2 then false else - let p2 = lazy (get_pivot_positions m2) in - try ( - for i = 0 to num_rows m1 - 1 do - if Array.exists2 (<>:) m1.(i) m2.(i) then - let m1_i = Array.copy m1.(i) in - for j = 0 to Array.length m1_i - 2 do - if m1_i.(j) <>: A.zero then - match Array.bsearch Int.ord (Lazy.force p2) j with - | `At pos -> let beta = m1_i.(j) in - Array.iteri (fun j' x -> m1_i.(j') <- m1_i.(j') -: beta *: m2.(pos).(j') ) m1_i - | _ -> raise Stdlib.Exit; - done; - if m1_i. (num_cols m1 - 1) <>: A.zero then - raise Stdlib.Exit - done; - true - ) - with Stdlib.Exit -> false;; - - let is_covered_by m1 m2 = timing_wrap "is_covered_by" (is_covered_by m1) m2 - - let find_opt f m = - let f' x = f (V.of_array x) in Option.map V.of_array (Array.find_opt f' m) - - let map2 f m v = - let f' x y = V.to_array @@ f (V.of_array x) y in Array.map2 f' m (V.to_array v) - - let map2_with f m v = - if num_rows m = V.length v then - Array.iter2i (fun i x y -> m.(i) <- V.to_array @@ f (V.of_array x) y) m (V.to_array v) - else - for i = 0 to Stdlib.min (num_rows m) (V.length v) -1 do - m.(i) <- V.to_array @@ f (V.of_array m.(i)) (V.nth v i) - done - - let map2_with f m v = timing_wrap "map2_with" (map2_with f m) v - - let map2i_with f m v = - if num_rows m = V.length v then - Array.iter2i (fun i x y -> m.(i) <- V.to_array @@ f i (V.of_array x) y) m (V.to_array v) - else - for i = 0 to Stdlib.min (num_rows m) (V.length v) -1 do - m.(i) <- V.to_array @@ f i (V.of_array m.(i)) (V.nth v i) - done - - let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v - end - - -module SparseVector: AbstractVector = - functor (A: RatOps) -> - struct - include ConvenienceOps (A) - - type t = { - entries: (int * A.t) list ; - len: int - }[@@deriving eq, ord, hash] - - let show v = - failwith "TODO" - - let keep_vals v n = - let rec keep_vals_vec v n = - match v with - | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) - | [] -> [] - in - if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = keep_vals_vec v.entries n; len=n} - - let remove_val v n = - let dec_idx v = - List.map (fun (a,b) -> (a-1, b)) v - in - let rec remove_val_vec v n = - match v with - | x::xs -> - if fst x = n then dec_idx xs else - if fst x > n then dec_idx (x::xs) else - x::(remove_val_vec xs n) - | [] -> [] - in - if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_val_vec v.entries n; len = v.len - 1} - - let set_val v n m = - failwith "TODO" - - let set_val_with v n m = - failwith "TODO" - - let insert_val n m t = - failwith "TODO" - - let apply_with_c f m v = - failwith "TODO" - - let apply_with_c_with f m v = - failwith "TODO" - - let zero_vec n = - failwith "TODO" - - let nth v n = - failwith "TODO" - - let length v = - failwith "TODO" - - let map2 f v v' = - failwith "TODO" - - let map2_with f v v' = - failwith "TODO" - - let findi f v = - failwith "TODO" - - let map f v = - failwith "TODO" - - let map_with f v = - failwith "TODO" - - let compare_length_with v n = - failwith "TODO" - - let of_list l = - failwith "TODO" - - let to_list v = - failwith "TODO" - - let filteri f v = - failwith "TODO" - - let append v v' = - failwith "TODO" - - let exists f v = - failwith "TODO" - - let rev v = - failwith "TODO" - - let rev_with v = - failwith "TODO" - - let map2i f v v' = - failwith "TODO" - - let map2i_with f v v' = - failwith "TODO" - - let mapi f v = - failwith "TODO" - - let mapi_with f v = - failwith "TODO" - - let find2i f v v' = - failwith "TODO" - - let to_array v = - failwith "TODO" - - let of_array a = - failwith "TODO" - - let copy v = v - - let of_sparse_list ls col_count = - failwith "TODO" - - let to_sparse_list v = - failwith "TODO" - - end - - -(** Sparse matrix implementation. - It provides a normalization function to reduce a matrix into reduced row echelon form. - Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) -module SparseMatrix: AbstractMatrix = - functor (A: RatOps) (V: AbstractVector) -> - struct - include ConvenienceOps(A) - module V = V(A) - - (* Array of arrays implementation. One array per row containing tuple of column index and value *) - type t = { - entries : (int * A.t) list list; - column_count : int - } [@@deriving eq, ord, hash] - - let show x = - List.fold_left (^) " " (List.map (fun row -> V.show @@ V.of_sparse_list row x.column_count) x.entries) - - let empty () = - {entries = []; column_count = 0} - - let num_rows m = - List.length m.entries - - let is_empty m = - num_rows m = 0 - (*This should be different if the implimentation is sound*) - (*m.column_count = 0*) - - let num_cols m = - m.column_count - - let copy m = - {entries = m.entries; column_count = m.column_count} (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) - - let copy m = - timing_wrap "copy" (copy) m - - let add_empty_columns m (cols : int enumerable) = - let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in - let emptyT = A.zero in - let rec list_of_all_before_index idx cols = - match cols with - | x::xs -> - if x < idx - then - let (h,t) = list_of_all_before_index idx xs in - (x::h, t) - else ([],x::xs) - | [] -> ([],[]) - in - (*This could easily be abstracted into the above functions, but its nice to have - it here for readability and debugging*) - let rec make_empty_entries_for_idxs idxs = - match idxs with - | x::xs -> (x, emptyT)::(make_empty_entries_for_idxs xs) - | [] -> [] - in - let rec add_column_element r cols = - match r with - | (idx, _)::xs -> - let (bef,aft) = list_of_all_before_index idx cols in - (make_empty_entries_for_idxs bef)@(add_column_element xs aft) - | [] -> [] - in - let rec add_empty_columns_on_list m cols = - match m with - | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) - | [] -> [] - in {entries = add_empty_columns_on_list m.entries colsL; column_count = m.column_count + Array.length cols} - - let add_empty_columns m (cols : int enumerable) = - timing_wrap "add_empty_cols" (add_empty_columns m) cols - - let append_row m row = - {entries = m.entries @ [V.to_sparse_list row]; column_count = m.column_count} - - let get_row m n = - V.of_sparse_list (List.nth m.entries n) m.column_count - - let remove_row m n = - let rec aux idx entries = match idx, entries with - | i, x :: xs when i = n -> xs - | _, x :: xs -> x :: aux (idx + 1) xs - | _, _ -> failwith "trying to remove out of bounds row" - in - let new_entries = aux 0 m.entries in - let new_col_count = if new_entries = [] then 0 else m.column_count in - {entries = new_entries; column_count = new_col_count} - - let get_col m n = - (* Uses the fact that row is sorted to return Zero when index n is exceeded *) - let rec get_col_from_row row = - match row with - | [] -> A.zero - | (col_idx, value)::_ when col_idx = n -> value - | (col_idx, _)::_ when col_idx > n -> A.zero - | _::cs -> get_col_from_row cs - in - V.of_list @@ List.map (fun row -> get_col_from_row row ) m.entries - - let get_col m n = - timing_wrap "get_col" (get_col m) n - - let set_col_with m new_col n = - failwith "TODO" - - let set_col_with m new_col n = timing_wrap "set_col" (set_col_with m new_col) n - - let set_col m new_col n = - let rec set_col_in_row row value = - match row with - | [] -> if value =: A.zero then [] else [(n, value)] - | (col_idx, v)::cs when col_idx > n -> if value =: A.zero then (col_idx, v)::cs else (n, value)::(col_idx, v)::cs - | (col_idx, v)::cs when col_idx = n -> if value =: A.zero then cs else (n, value)::cs - | (col_idx, v)::cs -> (col_idx, v)::(set_col_in_row cs value) - in - let new_entries = List.mapi (fun row_idx row -> - let value = V.nth new_col row_idx in - set_col_in_row row value - ) m.entries in - {entries = new_entries; column_count = m.column_count} - - let append_matrices m1 m2 = - failwith "TODO" - - let equal m1 m2 = timing_wrap "equal" (equal m1) m2 - - let reduce_col_with m j = - failwith "TODO" - - let reduce_col_with m j = timing_wrap "reduce_col_with" (reduce_col_with m) j - let reduce_col m j = - failwith "TODO" - - let del_col m j = - if is_empty m then m else - let del_col_from_row row = - List.filter_map (fun (col_idx, value) -> - if col_idx = j then - None - else if col_idx > j then - Some (col_idx - 1, value) - else - Some (col_idx, value) - ) row - in - let new_entries = List.map (fun row -> del_col_from_row row) m.entries in - {entries = new_entries; column_count = m.column_count - 1} - - (* TODO: Might be more efficient to check for each entry how much to reduce their index and not by recursively calling del_col *) - let del_cols m cols = - let cols = Array.to_list cols in (* TODO: Get away from Arrays *) - let to_delete_count = List.length cols in - if to_delete_count = 0 || is_empty m then m - else - if num_cols m = to_delete_count then empty () else - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification)*) - let rec del_cols_aux m cols deleted_col_count = - match cols with - | [] -> m - | col_idx::cs -> - let m' = del_col m (col_idx - deleted_col_count) in (* Taking already deleted cols into account because of new index *) - del_cols_aux m' cs (deleted_col_count + 1) - in del_cols_aux m sorted_cols 0 - - let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols - - let map2i f m v = - failwith "TODO" - - let remove_zero_rows m = - failwith "TODO" - - let rref_with m = - failwith "TODO" - - let rref_with m = timing_wrap "rref_with" rref_with m - - let init_with_vec v = - failwith "TODO" - - - let reduce_col_with_vec m j v = - failwith "TODO" - - let get_pivot_positions m = - failwith "TODO" - - let rref_vec m pivot_positions v = - failwith "TODO" - - - let rref_vec_with m v = - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) - (*m must be in rref form and contain the same num of cols as v*) - (*If m is empty then v is simply normalized and returned*) - failwith "TODO" - - let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v - - let rref_matrix_with m1 m2 = - (*Similar to rref_vec_with but takes two matrices instead.*) - (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - failwith "TODO" - - let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 - - let normalize_with m = - failwith "TODO" - - let normalize_with m = timing_wrap "normalize_with" normalize_with m - - let normalize m = - failwith "TODO" - - let is_covered_by m1 m2 = - failwith "TODO" - - let is_covered_by m1 m2 = timing_wrap "is_covered_by" (is_covered_by m1) m2 - - let find_opt f m = - failwith "TODO" - - let map2 f m v = - failwith "TODO" - - let map2_with f m v = - failwith "TODO" - - let map2_with f m v = timing_wrap "map2_with" (map2_with f m) v - - let map2i_with f m v = - failwith "TODO" - - let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v - end \ No newline at end of file diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 91f9837419..91207ba617 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -430,7 +430,7 @@ module BaseInvariant = BaseInvariant module CommonPriv = CommonPriv module WideningThresholds = WideningThresholds -module VectorMatrix = VectorMatrix +(*module VectorMatrix = VectorMatrix (*Why is this needed anyway?*)*) module SharedFunctions = SharedFunctions module GobApron = GobApron From 5ce5ee82655a10df87db861f5c1f86126356aff3 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 21 Nov 2024 15:48:27 +0100 Subject: [PATCH 026/240] Bugfix Matrix.map2i without side effects (different length lists) --- src/cdomains/vectorMatrix.ml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/cdomains/vectorMatrix.ml b/src/cdomains/vectorMatrix.ml index 31b33348b8..178e8ab1f0 100644 --- a/src/cdomains/vectorMatrix.ml +++ b/src/cdomains/vectorMatrix.ml @@ -456,11 +456,8 @@ module ArrayMatrix: AbstractMatrix = m' let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols - - let map2i f m v = - let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in - let range_array = Array.init (V.length v) Fun.id in - Array.map2 f' m (Array.combine range_array (V.to_array v)) + + let remove_zero_rows m = Array.filter (fun x -> Array.exists (fun y -> y <>: A.zero) x) m @@ -661,6 +658,18 @@ module ArrayMatrix: AbstractMatrix = done let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v + + + (* Deprecated + let map2i f m v = + let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in + let range_array = Array.init (V.length v) Fun.id in + Array.map2 f' m (Array.combine range_array (V.to_array v)) + *) + let map2i f m v = + let m' = copy m in + map2i_with f m' v; + m' end From 7643899a2a5fff2cf082b76a55a442531dbd94e0 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 21 Nov 2024 16:29:39 +0100 Subject: [PATCH 027/240] added missing module BatList --- .../arrayImplementation/arrayVector.ml | 2 +- .../sparseImplementation/sparseMatrix.ml | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml b/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml index ca79d90515..a65892f2eb 100644 --- a/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml @@ -90,7 +90,7 @@ module ArrayVector: AbstractVector = let copy = copy v in mapi_with f copy; copy - let of_sparse_list ls col_count = + let of_sparse_list col_count ls = let vec = Array.make col_count A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) ls; vec diff --git a/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml index 36b38322d4..916513ece9 100644 --- a/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml @@ -3,6 +3,9 @@ open AbstractVector open RatOps open ConvenienceOps +open BatList +module List = BatList + (** Sparse matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) @@ -43,7 +46,7 @@ module SparseMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m - let add_empty_columns m (cols : int enumerable) = + let add_empty_columns m cols = let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in let emptyT = A.zero in let rec list_of_all_before_index idx cols = @@ -76,7 +79,7 @@ module SparseMatrix: AbstractMatrix = | [] -> [] in tM (add_empty_columns_on_list m.entries colsL) (m.column_count + Array.length cols) - let add_empty_columns m (cols : int enumerable) = + let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = From 41bb6ed012bc27b48da700cb097c2e2633760d36 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 21 Nov 2024 16:37:18 +0100 Subject: [PATCH 028/240] RenamedFolder; Revealed modules to goblint_lib --- .../abstractMatrix.ml | 0 .../abstractVector.ml | 0 src/cdomains/affineEquality/affineEquality.ml | 10 ++++++++++ .../arrayImplementation/arrayMatrix.ml | 0 .../arrayImplementation/arrayVector.ml | 0 .../convenienceOps.ml | 0 .../matrix.ml | 0 .../ratOps.ml | 0 .../sparseImplementation/sparseMatrix.ml | 0 .../sparseImplementation/sparseVector.ml | 0 .../vector.ml | 0 src/goblint_lib.ml | 2 +- 12 files changed, 11 insertions(+), 1 deletion(-) rename src/cdomains/{affineEqualityMatrices => affineEquality}/abstractMatrix.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/abstractVector.ml (100%) create mode 100644 src/cdomains/affineEquality/affineEquality.ml rename src/cdomains/{affineEqualityMatrices => affineEquality}/arrayImplementation/arrayMatrix.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/arrayImplementation/arrayVector.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/convenienceOps.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/matrix.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/ratOps.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/sparseImplementation/sparseMatrix.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/sparseImplementation/sparseVector.ml (100%) rename src/cdomains/{affineEqualityMatrices => affineEquality}/vector.ml (100%) diff --git a/src/cdomains/affineEqualityMatrices/abstractMatrix.ml b/src/cdomains/affineEquality/abstractMatrix.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/abstractMatrix.ml rename to src/cdomains/affineEquality/abstractMatrix.ml diff --git a/src/cdomains/affineEqualityMatrices/abstractVector.ml b/src/cdomains/affineEquality/abstractVector.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/abstractVector.ml rename to src/cdomains/affineEquality/abstractVector.ml diff --git a/src/cdomains/affineEquality/affineEquality.ml b/src/cdomains/affineEquality/affineEquality.ml new file mode 100644 index 0000000000..71846bf0d7 --- /dev/null +++ b/src/cdomains/affineEquality/affineEquality.ml @@ -0,0 +1,10 @@ +(** This module is used to reveal modules to goblint_lib *) +module AbstractVector = AbstractVector +module ArrayMatrix = ArrayMatrix +module SparseMatrix = SparseMatrix +module Matrix = Matrix +module AbstractMatrix = AbstractMatrix +module ConvenienceOps = ConvenienceOps +module SparseVector = SparseVector +module RatOps = RatOps +module Vector = Vector \ No newline at end of file diff --git a/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/arrayImplementation/arrayMatrix.ml rename to src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml diff --git a/src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/arrayImplementation/arrayVector.ml rename to src/cdomains/affineEquality/arrayImplementation/arrayVector.ml diff --git a/src/cdomains/affineEqualityMatrices/convenienceOps.ml b/src/cdomains/affineEquality/convenienceOps.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/convenienceOps.ml rename to src/cdomains/affineEquality/convenienceOps.ml diff --git a/src/cdomains/affineEqualityMatrices/matrix.ml b/src/cdomains/affineEquality/matrix.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/matrix.ml rename to src/cdomains/affineEquality/matrix.ml diff --git a/src/cdomains/affineEqualityMatrices/ratOps.ml b/src/cdomains/affineEquality/ratOps.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/ratOps.ml rename to src/cdomains/affineEquality/ratOps.ml diff --git a/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/sparseImplementation/sparseMatrix.ml rename to src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml diff --git a/src/cdomains/affineEqualityMatrices/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/sparseImplementation/sparseVector.ml rename to src/cdomains/affineEquality/sparseImplementation/sparseVector.ml diff --git a/src/cdomains/affineEqualityMatrices/vector.ml b/src/cdomains/affineEquality/vector.ml similarity index 100% rename from src/cdomains/affineEqualityMatrices/vector.ml rename to src/cdomains/affineEquality/vector.ml diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 91207ba617..b52cc94293 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -430,7 +430,7 @@ module BaseInvariant = BaseInvariant module CommonPriv = CommonPriv module WideningThresholds = WideningThresholds -(*module VectorMatrix = VectorMatrix (*Why is this needed anyway?*)*) +module AffineEquality = AffineEquality module SharedFunctions = SharedFunctions module GobApron = GobApron From 6602d75b65ef1b13d81fea88b56a5ec6ef6d3b79 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 21 Nov 2024 16:39:46 +0100 Subject: [PATCH 029/240] Directly revealed modules to goblint_lib --- src/cdomains/affineEquality/affineEquality.ml | 10 ---------- src/goblint_lib.ml | 12 +++++++++++- 2 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 src/cdomains/affineEquality/affineEquality.ml diff --git a/src/cdomains/affineEquality/affineEquality.ml b/src/cdomains/affineEquality/affineEquality.ml deleted file mode 100644 index 71846bf0d7..0000000000 --- a/src/cdomains/affineEquality/affineEquality.ml +++ /dev/null @@ -1,10 +0,0 @@ -(** This module is used to reveal modules to goblint_lib *) -module AbstractVector = AbstractVector -module ArrayMatrix = ArrayMatrix -module SparseMatrix = SparseMatrix -module Matrix = Matrix -module AbstractMatrix = AbstractMatrix -module ConvenienceOps = ConvenienceOps -module SparseVector = SparseVector -module RatOps = RatOps -module Vector = Vector \ No newline at end of file diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index b52cc94293..7792588864 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -430,7 +430,17 @@ module BaseInvariant = BaseInvariant module CommonPriv = CommonPriv module WideningThresholds = WideningThresholds -module AffineEquality = AffineEquality +(* There might be a more elegant solution. *) +module AbstractVector = AbstractVector +module ArrayMatrix = ArrayMatrix +module SparseMatrix = SparseMatrix +module Matrix = Matrix +module AbstractMatrix = AbstractMatrix +module ConvenienceOps = ConvenienceOps +module SparseVector = SparseVector +module RatOps = RatOps +module Vector = Vector + module SharedFunctions = SharedFunctions module GobApron = GobApron From b7d5c1ace4bbe16805463d54b86fd0b71127c399 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 21 Nov 2024 16:49:39 +0100 Subject: [PATCH 030/240] Added missing ArrayVector module to goblint_lib --- src/goblint_lib.ml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 7792588864..a5fe9230fe 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -431,15 +431,16 @@ module CommonPriv = CommonPriv module WideningThresholds = WideningThresholds (* There might be a more elegant solution. *) -module AbstractVector = AbstractVector -module ArrayMatrix = ArrayMatrix -module SparseMatrix = SparseMatrix +module Vector = Vector module Matrix = Matrix +module AbstractVector = AbstractVector module AbstractMatrix = AbstractMatrix -module ConvenienceOps = ConvenienceOps +module ArrayVector = ArrayVector +module ArrayMatrix = ArrayMatrix module SparseVector = SparseVector +module SparseMatrix = SparseMatrix module RatOps = RatOps -module Vector = Vector +module ConvenienceOps = ConvenienceOps module SharedFunctions = SharedFunctions module GobApron = GobApron From 8476f95212324b5c3b34956158b9455ca65f3bd8 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 26 Nov 2024 16:16:17 +0100 Subject: [PATCH 031/240] Vector List --- .../affineEquality/sparseImplementation/sparseMatrix.ml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 916513ece9..851706a685 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -9,17 +9,14 @@ module List = BatList (** Sparse matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) -module SparseMatrix: AbstractMatrix = +module ListMatrix: AbstractMatrix = functor (A: RatOps) (V: AbstractVector) -> struct include ConvenienceOps(A) module V = V(A) - (* Array of arrays implementation. One array per row containing tuple of column index and value *) - type t = { - entries : (int * A.t) list list; - column_count : int - } [@@deriving eq, ord, hash] + type t = V.t list (*List of rows*) + [@@deriving eq, ord, hash] let tM e l = {entries= e; column_count=l} From 5fb804134f6fa0e79ed1a231ad7451553227d65f Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 26 Nov 2024 16:47:37 +0100 Subject: [PATCH 032/240] someMatFuncs --- .../sparseImplementation/sparseMatrix.ml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 851706a685..ccc88ca7d1 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -18,27 +18,22 @@ module ListMatrix: AbstractMatrix = type t = V.t list (*List of rows*) [@@deriving eq, ord, hash] - let tM e l = {entries= e; column_count=l} - let show x = - List.fold_left (^) "" (List.map (fun row -> V.show @@ V.of_sparse_list x.column_count row) x.entries) + List.fold_left (^) "" (List.map (fun x -> (V.show x) ^ "\n") x) - let empty () = - {entries = []; column_count = 0} + let empty () = [] - let num_rows m = - List.length m.entries + let num_rows = List.length let is_empty m = num_rows m = 0 (*This should be different if the implimentation is sound*) (*m.column_count = 0*) - let num_cols m = - m.column_count + let num_cols m = if m = [] then 0 else V.length (hd m) - let copy m = - m (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + let copy m = m + (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) let copy m = Timing.wrap "copy" (copy) m From 8c3824f2f9c922a0ba1e29178553125cc45a4cbb Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 26 Nov 2024 16:56:22 +0100 Subject: [PATCH 033/240] some functions changed to use vectors --- .../sparseImplementation/sparseMatrix.ml | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 851706a685..904c87e37e 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -80,20 +80,13 @@ module ListMatrix: AbstractMatrix = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - {entries = m.entries @ [V.to_sparse_list row]; column_count = V.length row} + m @ [row] let get_row m n = - V.of_sparse_list m.column_count (List.nth m.entries n) + List.nth m n let remove_row m n = - let rec aux idx entries = match idx, entries with - | i, x :: xs when i = n -> xs - | _, x :: xs -> x :: aux (idx + 1) xs - | _, _ -> failwith "trying to remove out of bounds row" - in - let new_entries = aux 0 m.entries in - let new_col_count = if new_entries = [] then 0 else m.column_count in - {entries = new_entries; column_count = new_col_count} + List.remove_at n m let get_col m n = (* Uses the fact that row is sorted to return Zero when index n is exceeded *) @@ -128,9 +121,8 @@ module ListMatrix: AbstractMatrix = ) m.entries in {entries = new_entries; column_count = m.column_count} - let append_matrices m1 m2 = - let new_entries = List.append m1.entries m2.entries in - {entries = new_entries; column_count = m1.column_count} + let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) + m1 @ m2 let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 @@ -227,9 +219,7 @@ module ListMatrix: AbstractMatrix = {entries = new_entries; column_count = m.column_count} let remove_zero_rows m = - let entries' = List.filter (fun row -> row <> []) m.entries in - if List.length entries' = 0 then empty() else - {entries = entries'; column_count = m.column_count} + List.filter (fun row -> not (V.is_zero_vec row)) m let rref_with m = failwith "Do not use!" @@ -237,7 +227,7 @@ module ListMatrix: AbstractMatrix = let rref_with m = Timing.wrap "rref_with" rref_with m let init_with_vec v = - failwith "TODO" + [v] let reduce_col_with_vec m j v = From 3234896086e8332d98f6969654496206f01be3c0 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 26 Nov 2024 16:57:14 +0100 Subject: [PATCH 034/240] again --- src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 904c87e37e..08ca44d2dc 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -229,7 +229,6 @@ module ListMatrix: AbstractMatrix = let init_with_vec v = [v] - let reduce_col_with_vec m j v = failwith "TODO" From 251f1c993b909d17c4dfd9c6306c66023e55a7af Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 26 Nov 2024 16:57:31 +0100 Subject: [PATCH 035/240] Reimplemented some matrix functions to vector --- .../sparseImplementation/sparseMatrix.ml | 40 +++---------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 14bf26234a..f4d3e3bfe1 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -198,20 +198,8 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols let map2i f m v = - let f' index row num = V.to_sparse_list @@ f index (V.of_sparse_list m.column_count row) num in - (* TODO: Do we need to consider different lengths here? - let vector_length = List.length (V.to_list v) in - let new_entries = - List.mapi (fun index row -> - if index < vector_length then - let num = V.nth v index in - f' index row num - else row - ) m.entries - in - *) - let new_entries = List.map2i f' m.entries (V.to_list v) in - {entries = new_entries; column_count = m.column_count} + let vector_length = V.length v in + List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row) m let remove_zero_rows m = List.filter (fun row -> not (V.is_zero_vec row)) m @@ -324,29 +312,11 @@ module ListMatrix: AbstractMatrix = let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = - let rec find_opt_vec_list f m = - match m with - | [] -> None - | x::xs -> if f x then Some x else find_opt_vec_list f xs - in - let m_vector = List.map (fun row -> V.of_sparse_list m.column_count row) m.entries in - find_opt_vec_list f m_vector + List.find_opt f m let map2 f m v = - let f' row num = V.to_sparse_list @@ f (V.of_sparse_list m.column_count row) num in - (* TODO: Do we need to consider different lengths here? - let vector_length = List.length (V.to_list v) in - let new_entries = - List.mapi (fun index row -> - if index < vector_length then - let num = V.nth v index in - f' row num - else row - ) m.entries - in - *) - let new_entries = List.map2 f' m.entries (V.to_list v) in - {entries = new_entries; column_count = m.column_count} + let vector_length = V.length v in + List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m let map2_with f m v = failwith "Do not use!" From 67c9ef4dec1d515d9d23b5c64acf04f43e6c0a74 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 26 Nov 2024 17:10:54 +0100 Subject: [PATCH 036/240] Added find_opt and remove_nth to vector interface --- .../affineEquality/arrayImplementation/arrayVector.ml | 6 ++++++ .../affineEquality/sparseImplementation/sparseVector.ml | 6 ++++++ src/cdomains/affineEquality/vector.ml | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index a65892f2eb..492fa7cb14 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -103,4 +103,10 @@ module ArrayVector: AbstractVector = let acc = if value <> A.zero then (idx, value):: acc else acc in aux (idx - 1) acc in aux (length v - 1) [] + + let remove_nth v n = + failwith "TODO" + + let find_opt f v = + failwith "TODO" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6ec6bb834a..ac68ac249b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -164,4 +164,10 @@ module SparseVector: AbstractVector = let to_sparse_list v = v.entries + let remove_nth v n = + failwith "TODO" + + let find_opt f v = + failwith "TODO" + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 81014bcf24..9b2801e667 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -24,6 +24,8 @@ sig val nth: t -> int -> num + val remove_nth: t -> int -> t + val length: t -> int val map2: (num -> num -> num) -> t -> t -> t @@ -32,6 +34,8 @@ sig val findi: (num -> bool) -> t -> int + val find_opt: (num -> bool) -> t -> t Option.t + val map: (num -> num) -> t -> t val map_with: (num -> num) -> t -> unit From 19ac2dbdc4656941d6c4f871b778afa6e3ef5748 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 26 Nov 2024 17:12:47 +0100 Subject: [PATCH 037/240] pushing is_zero_vec --- src/cdomains/affineEquality/arrayImplementation/arrayVector.ml | 2 ++ .../affineEquality/sparseImplementation/sparseMatrix.ml | 2 +- .../affineEquality/sparseImplementation/sparseVector.ml | 2 ++ src/cdomains/affineEquality/vector.ml | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index a65892f2eb..bd78e7e453 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -51,6 +51,8 @@ module ArrayVector: AbstractVector = let zero_vec n = Array.make n A.zero + let is_zero_vec v = not (Array.exists (fun x -> x <>: A.zero) v) + let nth = Array.get let map2i f v1 v2 = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 14bf26234a..4cb3e85fa5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -128,7 +128,7 @@ module ListMatrix: AbstractMatrix = let reduce_col m j = if is_empty m then m else - let rec find_pivot idx entries = (* Finds non-zero element in row j and return pair of row idx and the pivot value *) + let rec find_pivot idx entries = (* Finds non-zero element in column j and returns pair of row idx and the pivot value *) match entries with | [] -> None | row :: rest -> match (List.assoc_opt j row) with diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6ec6bb834a..e7db344e26 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -90,6 +90,8 @@ module SparseVector: AbstractVector = let zero_vec n = failwith "TODO" + let is_zero_vec v = (v.entries = []) + let nth v n = failwith "TODO" diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 81014bcf24..e16eb00be0 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -22,6 +22,8 @@ sig val zero_vec: int -> t + val is_zero_vec: t -> bool + val nth: t -> int -> num val length: t -> int From a0e0f1b40151906f7337ae3e7be79e5c891f9d4b Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 26 Nov 2024 17:47:23 +0100 Subject: [PATCH 038/240] Formatting --- .../arrayImplementation/arrayVector.ml | 12 ++++---- .../sparseImplementation/sparseMatrix.ml | 30 +++---------------- .../sparseImplementation/sparseVector.ml | 20 ++++++------- src/cdomains/affineEquality/vector.ml | 10 +++---- 4 files changed, 23 insertions(+), 49 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 12b162fbb7..650b908b6c 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -30,19 +30,19 @@ module ArrayVector: AbstractVector = let compare_length_with v len = Int.compare (Array.length v) len - let remove_val v n = + let remove_nth v n = if n >= Array.length v then failwith "n outside of Array range" else Array.init (Array.length v - 1) (fun i -> if i < n then Array.get v i else Array.get v (i + 1)) (* TODO: remove_at? *) - let set_val_with v n new_val = + let set_nth_with v n new_val = if n >= Array.length v then failwith "n outside of Array range" else Array.set v n new_val - let set_val v n new_val = + let set_nth v n new_val = let copy = copy v in - set_val_with copy n new_val; copy + set_nth_with copy n new_val; copy - let insert_val n new_val v = + let insert_val_at n new_val v = if n > Array.length v then failwith "n too large" else Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then new_val else Array.get v (i -1)) (* insert? *) @@ -106,8 +106,6 @@ module ArrayVector: AbstractVector = aux (idx - 1) acc in aux (length v - 1) [] - let remove_nth v n = - failwith "TODO" let find_opt f v = failwith "TODO" diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index a702229c51..5518c45e99 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -33,7 +33,7 @@ module ListMatrix: AbstractMatrix = let num_cols m = if m = [] then 0 else V.length (hd m) let copy m = m - (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) let copy m = Timing.wrap "copy" (copy) m @@ -103,18 +103,7 @@ module ListMatrix: AbstractMatrix = let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n let set_col m new_col n = - let rec set_col_in_row row value = - match row with - | [] -> if value =: A.zero then [] else [(n, value)] - | (col_idx, v)::cs when col_idx > n -> if value =: A.zero then (col_idx, v)::cs else (n, value)::(col_idx, v)::cs - | (col_idx, v)::cs when col_idx = n -> if value =: A.zero then cs else (n, value)::cs - | (col_idx, v)::cs -> (col_idx, v)::(set_col_in_row cs value) - in - let new_entries = List.mapi (fun row_idx row -> - let value = V.nth new_col row_idx in - set_col_in_row row value - ) m.entries in - {entries = new_entries; column_count = m.column_count} + List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) m1 @ m2 @@ -165,19 +154,8 @@ module ListMatrix: AbstractMatrix = {entries = entries'; column_count = m.column_count} let del_col m j = - if is_empty m then m else - let del_col_from_row row = - List.filter_map (fun (col_idx, value) -> - if col_idx = j then - None - else if col_idx > j then - Some (col_idx - 1, value) - else - Some (col_idx, value) - ) row - in - let new_entries = List.map (fun row -> del_col_from_row row) m.entries in - {entries = new_entries; column_count = m.column_count - 1} + List.map (fun row -> V.remove_nth row j) m + (* TODO: Might be more efficient to check for each entry how much to reduce their index and not by recursively calling del_col *) let del_cols m cols = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 4f5df2eac7..3a04d9a86d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -26,36 +26,36 @@ module SparseVector: AbstractVector = {entries = keep_vals_vec v.entries n; len=n} - let remove_val v n = + let remove_nth v n = let dec_idx v = List.map (fun (a,b) -> (a-1, b)) v in - let rec remove_val_vec v n = + let rec remove_nth_vec v n = match v with | x::xs -> if fst x = n then dec_idx xs else if fst x > n then dec_idx (x::xs) else - x::(remove_val_vec xs n) + x::(remove_nth_vec xs n) | [] -> [] in if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_val_vec v.entries n; len = v.len - 1} + {entries = remove_nth_vec v.entries n; len = v.len - 1} - let set_val v n m = - let rec set_val_vec v n m = + let set_nth v n m = + let rec set_nth_vec v n m = match v with | x::xs -> if fst x = n then (n, m)::xs else - if fst x < n then x::(set_val_vec xs n m) + if fst x < n then x::(set_nth_vec xs n m) else v | [] -> [] in if n >= v.len then failwith "Out of bounds" else - {entries=set_val_vec v.entries n m; len=v.len} + {entries=set_nth_vec v.entries n m; len=v.len} - let set_val_with = + let set_nth_with = failwith "deprecated" - let insert_val n m t = + let insert_val_at n m t = failwith "TODO" let mul_vec_scal v s = diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 90f61baa94..3a7431629f 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -8,13 +8,13 @@ sig val keep_vals: t -> int -> t - val remove_val: t -> int -> t + val remove_nth: t -> int -> t - val set_val: t -> int -> num -> t + val set_nth: t -> int -> num -> t - val set_val_with: t -> int -> num -> unit + val set_nth_with: t -> int -> num -> unit - val insert_val: int -> num -> t -> t + val insert_val_at: int -> num -> t -> t val apply_with_c: (num -> num -> num) -> num -> t -> t @@ -26,8 +26,6 @@ sig val nth: t -> int -> num - val remove_nth: t -> int -> t - val length: t -> int val map2: (num -> num -> num) -> t -> t -> t From d768b46c949612cf4970b3bfc81b00b6a6138f8d Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 26 Nov 2024 17:48:58 +0100 Subject: [PATCH 039/240] vector functions --- .../sparseImplementation/sparseMatrix.ml | 10 +--------- .../sparseImplementation/sparseVector.ml | 8 +++++++- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index a702229c51..e32f71da2c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -84,15 +84,7 @@ module ListMatrix: AbstractMatrix = List.remove_at n m let get_col m n = - (* Uses the fact that row is sorted to return Zero when index n is exceeded *) - let rec get_col_from_row row = - match row with - | [] -> A.zero - | (col_idx, value)::_ when col_idx = n -> value - | (col_idx, _)::_ when col_idx > n -> A.zero - | _::cs -> get_col_from_row cs - in - V.of_list @@ List.map (fun row -> get_col_from_row row ) m.entries + V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) let get_col m n = Timing.wrap "get_col" (get_col m) n diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 4f5df2eac7..67cc85c11f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -93,7 +93,13 @@ module SparseVector: AbstractVector = let is_zero_vec v = (v.entries = []) let nth v n = - failwith "TODO" + if n >= v.len then failwith "V.nth out of bounds" + else + let rec nth v = match v with + | [] -> A.zero + | (col_idx, value) :: xs when col_idx = n -> value + | (col_idx, value) :: xs -> nth xs + in nth v.entries let length v = failwith "TODO" From 422dd549c11d26e77984c4138413e6f116acdd88 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 26 Nov 2024 18:19:01 +0100 Subject: [PATCH 040/240] Removed some _with functions from the AffineEqualityDomain --- .../apron/affineEqualityDomain.apron.ml | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index aa64b7f741..9a2999c021 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -240,11 +240,9 @@ struct else if is_top_env t2 then {d = Some (dim_add (Environment.dimchange t1.env sup_env) m1); env = sup_env} else - let rref_matr = Matrix.rref_matrix_with (Matrix.copy m1) (Matrix.copy m2) in - if Option.is_none rref_matr then - bot () - else - {d = rref_matr; env = sup_env} + match Matrix.rref_matrix m1 m2 with + | None -> bot () + | rref_matr -> {d = rref_matr; env = sup_env} let meet t1 t2 = @@ -283,8 +281,7 @@ struct if s >= Matrix.num_cols a then a else let case_two a r col_b = let a_r = Matrix.get_row a r in - Matrix.map2i_with (fun i x y -> if i < r then - Vector.map2_with (fun u j -> u +: y *: j) x a_r; x) a col_b; + let a = Matrix.map2i (fun i x y -> if i < r then Vector.map2 (fun u j -> u +: y *: j) x a_r else x) a col_b; in Matrix.remove_row a r in let case_three a b col_a col_b max = @@ -357,21 +354,17 @@ struct let pretty_diff () (x, y) = dprintf "%s: %a not leq %a" (name ()) pretty x pretty y - let remove_rels_with_var x var env inplace = - let j0 = Environment.dim_of_var env var in - if inplace then - (Matrix.reduce_col_with x j0; x) - else - Matrix.reduce_col x j0 + let remove_rels_with_var x var env = + let j0 = Environment.dim_of_var env var in Matrix.reduce_col x j0 - let remove_rels_with_var x var env inplace = timing_wrap "remove_rels_with_var" (remove_rels_with_var x var env) inplace + let remove_rels_with_var x var env = Timing.wrap "remove_rels_with_var" (remove_rels_with_var x var env) inplace let forget_vars t vars = if is_bot t || is_top_env t || vars = [] then t else let m = Option.get t.d in - let rem_from m = List.fold_left (fun m' x -> remove_rels_with_var m' x t.env true) m vars in + let rem_from m = List.fold_left (fun m' x -> remove_rels_with_var m' x t.env) m vars in {d = Some (Matrix.remove_zero_rows @@ rem_from (Matrix.copy m)); env = t.env} let forget_vars t vars = @@ -386,23 +379,25 @@ struct let j0 = Environment.dim_of_var env var in let a_j0 = Matrix.get_col x j0 in (*Corresponds to Axj0*) let b0 = Vector.nth b j0 in - Vector.apply_with_c_with (/:) b0 a_j0; (*Corresponds to Axj0/Bj0*) - let recalc_entries m rd_a = Matrix.map2_with (fun x y -> Vector.map2i_with (fun j z d -> + let a_j0 = Vector.apply_with_c (/:) b0 a_j0 in (*Corresponds to Axj0/Bj0*) + let recalc_entries m rd_a = Matrix.map2 (fun x y -> Vector.map2i (fun j z d -> if j = j0 then y else if Vector.compare_length_with b (j + 1) > 0 then z -: y *: d - else z +: y *: d) x b; x) m rd_a + else z +: y *: d) x b) m rd_a in - recalc_entries x a_j0; - if Matrix.normalize_with x then {d = Some x; env = env} else bot () + let x = recalc_entries x a_j0 in + match Matrix.normalize x with + | None -> bot () + | some_normalized_matrix -> {d = some_normalized_matrix; env = env} in let assign_invertible_rels x var b env = timing_wrap "assign_invertible" (assign_invertible_rels x var b) env in let assign_uninvertible_rel x var b env = let b_length = Vector.length b in - Vector.mapi_with (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b; - Vector.set_val_with b (Environment.dim_of_var env var) Mpqf.one; - let opt_m = Matrix.rref_vec_with x b in - if Option.is_none opt_m then bot () else - {d = opt_m; env = env} + let b = Vector.mapi (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b in + let b = Vector.set_val b (Environment.dim_of_var env var) Mpqf.one in + match Matrix.rref_vec x b with + | None -> bot () + | some_matrix -> {d = some_matrix; env = env} in (* let assign_uninvertible_rel x var b env = timing_wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) let is_invertible v = Vector.nth v @@ Environment.dim_of_var t.env var <>: Mpqf.zero @@ -411,9 +406,9 @@ struct match affineEq_vec with | Some v when is_top_env t -> if is_invertible v then t else assign_uninvertible_rel m var v t.env | Some v -> if is_invertible v then let t' = assign_invertible_rels (Matrix.copy m) var v t.env in {d = t'.d; env = t'.env} - else let new_m = Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env false + else let new_m = Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env in assign_uninvertible_rel new_m var v t.env - | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env false); env = t.env} + | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env); env = t.env} let assign_texpr t var texp = timing_wrap "assign_texpr" (assign_texpr t var) texp @@ -452,16 +447,15 @@ struct let replace_col m x y = let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in let col_x = Matrix.get_col m dim_x in - Matrix.set_col_with m col_x dim_y + Matrix.set_col m col_x dim_y in let m_cp = Matrix.copy m in let switched_m = List.fold_left2 replace_col m_cp primed_vars assigned_vars in let res = drop_vars {d = Some switched_m; env = multi_t.env} primed_vars ~del:true in let x = Option.get res.d in - if Matrix.normalize_with x then - {d = Some x; env = res.env} - else - bot () + (match Matrix.normalize x with + | None -> bot () + | some_matrix -> {d = some_matrix; env = res.env}) | _ -> t let assign_var_parallel t vv's = @@ -513,13 +507,13 @@ struct let meet_vec e = (* Flip the sign of the const. val in coeff vec *) let coeff = Vector.nth e (Vector.length e - 1) in - Vector.set_val_with e (Vector.length e - 1) (Mpqf.neg coeff); + let e = Vector.set_val e (Vector.length e - 1) (Mpqf.neg coeff) in if is_bot t then bot () else - let opt_m = Matrix.rref_vec_with (Matrix.copy @@ Option.get t.d) e in - if Option.is_none opt_m then bot () else {d = opt_m; env = t.env} - + match Matrix.rref_vec (Option.get t.d) e with + | None -> bot () + | some_matrix -> {d = some_matrix; env = t.env} in match get_coeff_vec t (Texpr1.to_expr @@ Tcons1.get_texpr1 tcons) with | Some v -> From 6afcb81e51045a57c72454f1331d1901af0e7298 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 26 Nov 2024 18:21:50 +0100 Subject: [PATCH 041/240] Implement inefficient rref functions --- .../sparseImplementation/sparseMatrix.ml | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 5518c45e99..2b66de2b24 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -98,7 +98,7 @@ module ListMatrix: AbstractMatrix = Timing.wrap "get_col" (get_col m) n let set_col_with m new_col n = - failwith "Do not use!" + failwith "deprecated" let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n @@ -111,7 +111,7 @@ module ListMatrix: AbstractMatrix = let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 let reduce_col_with m j = - failwith "Do not use!" + failwith "deprecated" let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = @@ -183,7 +183,7 @@ module ListMatrix: AbstractMatrix = List.filter (fun row -> not (V.is_zero_vec row)) m let rref_with m = - failwith "Do not use!" + failwith "deprecated" let rref_with m = Timing.wrap "rref_with" rref_with m @@ -196,31 +196,8 @@ module ListMatrix: AbstractMatrix = let get_pivot_positions m = failwith "TODO" - let rref_vec m pivot_positions v = - failwith "TODO" - - - let rref_vec_with m v = - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) - (*m must be in rref form and contain the same num of cols as v*) - (*If m is empty then v is simply normalized and returned*) - failwith "Do not use!" - - let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v - - let rref_vec m v = failwith "TODO" - - let rref_matrix_with m1 m2 = - (*Similar to rref_vec_with but takes two matrices instead.*) - (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - failwith "Do not use!" - - let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 - - let rref_matrix m1 m2 = failwith "TODO" - let normalize_with m = - failwith "Do not use!" + failwith "deprecated" let normalize_with m = Timing.wrap "normalize_with" normalize_with m @@ -283,6 +260,36 @@ module ListMatrix: AbstractMatrix = let e' = main_loop m.entries m.entries 0 0 in Some {entries = e'; column_count = m.column_count} + let rref_vec_helper m pivot_positions v = + failwith "TODO" + + let rref_vec_with m v = + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*m must be in rref form and contain the same num of cols as v*) + (*If m is empty then v is simply normalized and returned*) + failwith "deprecated" + + let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v + + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*m must be in rref form and contain the same num of cols as v*) + (*If m is empty then v is simply normalized and returned*) + (* TODO: OPTIMIZE! *) + let rref_vec m v = + normalize @@ append_matrices m (init_with_vec v) + + let rref_matrix_with m1 m2 = + (*Similar to rref_vec_with but takes two matrices instead.*) + (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) + failwith "deprecated" + + let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 + + (*Similar to rref_vec_with but takes two matrices instead.*) + (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) + (*TODO: OPTIMIZE!*) + let rref_matrix m1 m2 = + normalize @@ append_matrices m1 m2 let is_covered_by m1 m2 = failwith "TODO" @@ -297,7 +304,7 @@ module ListMatrix: AbstractMatrix = List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m let map2_with f m v = - failwith "Do not use!" + failwith "deprecated" let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v From 7b4173a4314d11061acb7296861dd4c216121757 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 26 Nov 2024 18:23:05 +0100 Subject: [PATCH 042/240] ocp-indent on sparseMatrix.ml --- .../affineEquality/sparseImplementation/sparseMatrix.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index a702229c51..c1509ecd1a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -33,7 +33,7 @@ module ListMatrix: AbstractMatrix = let num_cols m = if m = [] then 0 else V.length (hd m) let copy m = m - (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) let copy m = Timing.wrap "copy" (copy) m From c8db710183f0ca18975a7c8ae5dc972eca0cbf07 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 26 Nov 2024 19:02:38 +0100 Subject: [PATCH 043/240] del_cols and remove_at_indices --- .../arrayImplementation/arrayVector.ml | 2 ++ .../sparseImplementation/sparseMatrix.ml | 24 ++++++------------- .../sparseImplementation/sparseVector.ml | 11 +++++++++ src/cdomains/affineEquality/vector.ml | 2 ++ .../apron/affineEqualityDomain.apron.ml | 10 ++++---- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 650b908b6c..030d397398 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -34,6 +34,8 @@ module ArrayVector: AbstractVector = if n >= Array.length v then failwith "n outside of Array range" else Array.init (Array.length v - 1) (fun i -> if i < n then Array.get v i else Array.get v (i + 1)) (* TODO: remove_at? *) + let remove_at_indices v idx = failwith "TODO" + let set_nth_with v n new_val = if n >= Array.length v then failwith "n outside of Array range" else Array.set v n new_val diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 4b5ca28560..3cee73edc9 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -39,7 +39,7 @@ module ListMatrix: AbstractMatrix = Timing.wrap "copy" (copy) m let add_empty_columns m cols = - let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in + (*let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in let emptyT = A.zero in let rec list_of_all_before_index idx cols = match cols with @@ -69,7 +69,8 @@ module ListMatrix: AbstractMatrix = match m with | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) | [] -> [] - in tM (add_empty_columns_on_list m.entries colsL) (m.column_count + Array.length cols) + in tM (add_empty_columns_on_list m.entries colsL) (m.column_count + Array.length cols)*) + failwith "TODO" let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols @@ -148,22 +149,11 @@ module ListMatrix: AbstractMatrix = let del_col m j = List.map (fun row -> V.remove_nth row j) m - - (* TODO: Might be more efficient to check for each entry how much to reduce their index and not by recursively calling del_col *) let del_cols m cols = - let cols = Array.to_list cols in (* TODO: Get away from Arrays *) - let to_delete_count = List.length cols in - if to_delete_count = 0 || is_empty m then m - else - if num_cols m = to_delete_count then empty () else - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification)*) - let rec del_cols_aux m cols deleted_col_count = - match cols with - | [] -> m - | col_idx::cs -> - let m' = del_col m (col_idx - deleted_col_count) in (* Taking already deleted cols into account because of new index *) - del_cols_aux m' cs (deleted_col_count + 1) - in del_cols_aux m sorted_cols 0 + if (Array.length cols) = num_cols m then empty() else + let cols = Array.to_list cols in + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification), maybe use List instead?*) + List.map (fun row -> V.remove_at_indices row sorted_cols) m let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index fbe81edbd3..c8540cb121 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -41,6 +41,17 @@ module SparseVector: AbstractVector = if n >= v.len then v else (*could be left out but maybe performance??*) {entries = remove_nth_vec v.entries n; len = v.len - 1} + let remove_at_indices v idx = + let rec remove_indices_helper vec idx deleted_count = + match vec, idx with + | [], [] -> [] + | [], (y :: ys) -> failwith "remove at indices: no more columns to delete" + | ((col_idx, value) :: xs), [] -> (col_idx - deleted_count, value) :: remove_indices_helper xs idx deleted_count + | ((col_idx, value) :: xs), (y :: ys) when y = col_idx -> remove_indices_helper xs ys (deleted_count + 1) + | ((col_idx, value) :: xs), (y :: ys) -> (col_idx - deleted_count, value) :: remove_indices_helper xs idx deleted_count + in + {entries = remove_indices_helper v.entries idx 0; len = v.len - List.length idx} + let set_nth v n m = let rec set_nth_vec v n m = match v with diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 3a7431629f..f374853b27 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -10,6 +10,8 @@ sig val remove_nth: t -> int -> t + val remove_at_indices: t -> int list -> t + val set_nth: t -> int -> num -> t val set_nth_with: t -> int -> num -> unit diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 96bca14c26..617549db53 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -79,16 +79,16 @@ struct | Scalar Mpqf x -> x | Scalar Mpfrf x -> Mpfr.to_mpq x in - Vector.set_val zero_vec ((Vector.length zero_vec) - 1) (of_union x) + Vector.set_nth zero_vec ((Vector.length zero_vec) - 1) (of_union x) | Var x -> let zero_vec_cp = Vector.copy zero_vec in - let entry_only v = Vector.set_val v (Environment.dim_of_var t.env x) Mpqf.one in + let entry_only v = Vector.set_nth v (Environment.dim_of_var t.env x) Mpqf.one in begin match t.d with | Some m -> let row = Matrix.find_opt (fun r -> Vector.nth r (Environment.dim_of_var t.env x) =: Mpqf.one) m in begin match row with | Some v when is_const_vec v -> - Vector.set_val zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)) + Vector.set_nth zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)) | _ -> entry_only zero_vec_cp end | None -> entry_only zero_vec_cp end @@ -406,7 +406,7 @@ struct let assign_uninvertible_rel x var b env = let b_length = Vector.length b in Vector.mapi_with (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b; - Vector.set_val_with b (Environment.dim_of_var env var) Mpqf.one; + Vector.set_nth_with b (Environment.dim_of_var env var) Mpqf.one; let opt_m = Matrix.rref_vec_with x b in if Option.is_none opt_m then bot () else {d = opt_m; env = env} @@ -520,7 +520,7 @@ struct let meet_vec e = (* Flip the sign of the const. val in coeff vec *) let coeff = Vector.nth e (Vector.length e - 1) in - Vector.set_val_with e (Vector.length e - 1) (Mpqf.neg coeff); + Vector.set_nth_with e (Vector.length e - 1) (Mpqf.neg coeff); if is_bot t then bot () else From 24fd0576e62ef04f78bb55cdc956469d34b1b497 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 26 Nov 2024 19:05:02 +0100 Subject: [PATCH 044/240] commiting again for indentation --- .../sparseImplementation/sparseMatrix.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 3cee73edc9..4ed70b03b0 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -38,8 +38,8 @@ module ListMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m - let add_empty_columns m cols = - (*let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in + let add_empty_columns m cols = failwith "TODO" + (*let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in let emptyT = A.zero in let rec list_of_all_before_index idx cols = match cols with @@ -70,7 +70,6 @@ module ListMatrix: AbstractMatrix = | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) | [] -> [] in tM (add_empty_columns_on_list m.entries colsL) (m.column_count + Array.length cols)*) - failwith "TODO" let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols @@ -150,10 +149,11 @@ module ListMatrix: AbstractMatrix = List.map (fun row -> V.remove_nth row j) m let del_cols m cols = - if (Array.length cols) = num_cols m then empty() else - let cols = Array.to_list cols in - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification), maybe use List instead?*) - List.map (fun row -> V.remove_at_indices row sorted_cols) m + if (Array.length cols) = num_cols m then empty() + else + let cols = Array.to_list cols in + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification), maybe use List instead?*) + List.map (fun row -> V.remove_at_indices row sorted_cols) m let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols From 0c9eb46b98bdd0ee7ae209df6fabe7df0f551dc3 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 26 Nov 2024 19:40:47 +0100 Subject: [PATCH 045/240] Vector functions --- .../sparseImplementation/sparseMatrix.ml | 4 +- .../sparseImplementation/sparseVector.ml | 39 ++++++++++++------- src/cdomains/affineEquality/vector.ml | 2 +- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index dbaeb5192a..1ba26f2771 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -146,7 +146,9 @@ module ListMatrix: AbstractMatrix = {entries = entries'; column_count = m.column_count} let del_col m j = - List.map (fun row -> V.remove_nth row j) m + if num_cols m = 1 then empty () + else + List.map (fun row -> V.remove_nth row j) m let del_cols m cols = if (Array.length cols) = num_cols m then empty() diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index c8540cb121..4b1754d8f5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -41,6 +41,19 @@ module SparseVector: AbstractVector = if n >= v.len then v else (*could be left out but maybe performance??*) {entries = remove_nth_vec v.entries n; len = v.len - 1} + (* TODO: Which of both remmove_nth should we use *) + let remove_nth v n = + if n >= v.len then failwith "Out of bounds" + else + let new_entries = List.filter_map (fun (col_idx, value) -> + if col_idx = n + then None + else if col_idx > n + then Some (col_idx - 1, value) + else Some (col_idx, value) + ) v.entries in + {entries = new_entries; len = v.len - 1} + let remove_at_indices v idx = let rec remove_indices_helper vec idx deleted_count = match vec, idx with @@ -52,16 +65,14 @@ module SparseVector: AbstractVector = in {entries = remove_indices_helper v.entries idx 0; len = v.len - List.length idx} - let set_nth v n m = - let rec set_nth_vec v n m = - match v with - | x::xs -> if fst x = n then (n, m)::xs else - if fst x < n then x::(set_nth_vec xs n m) - else v - | [] -> [] - in - if n >= v.len then failwith "Out of bounds" else - {entries=set_nth_vec v.entries n m; len=v.len} + let set_nth v n num = + if n >= v.len then failwith "Out of bounds" + else + let new_entries = List.map (fun (col_idx, value) -> + if col_idx = n then (col_idx, num) else (col_idx, value) + ) v.entries + in + {entries= new_entries; len=v.len} let set_nth_with = failwith "deprecated" @@ -108,12 +119,13 @@ module SparseVector: AbstractVector = else let rec nth v = match v with | [] -> A.zero + | (col_idx, value) :: xs when col_idx > n -> A.zero | (col_idx, value) :: xs when col_idx = n -> value | (col_idx, value) :: xs -> nth xs in nth v.entries let length v = - failwith "TODO" + v.len let map2 f v v' = failwith "TODO" @@ -183,10 +195,7 @@ module SparseVector: AbstractVector = let to_sparse_list v = v.entries - let remove_nth v n = - failwith "TODO" - let find_opt f v = - failwith "TODO" + failwith "TODO: Do we need this?" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index f374853b27..a673b820c7 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -36,7 +36,7 @@ sig val findi: (num -> bool) -> t -> int - val find_opt: (num -> bool) -> t -> t Option.t + val find_opt: (num -> bool) -> t -> num Option.t val map: (num -> num) -> t -> t From 0db8b6101cc3863f74f01eb677b6736062a7ab32 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Wed, 27 Nov 2024 16:11:26 +0100 Subject: [PATCH 046/240] some vector functions --- .../sparseImplementation/sparseVector.ml | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 4b1754d8f5..6a792336c4 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -2,6 +2,9 @@ open AbstractVector open RatOps open ConvenienceOps +open BatList +module List = BatList + module SparseVector: AbstractVector = functor (A: RatOps) -> struct @@ -77,8 +80,14 @@ module SparseVector: AbstractVector = let set_nth_with = failwith "deprecated" - let insert_val_at n m t = - failwith "TODO" + let insert_val_at n new_val v = + if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) + let entries' = List.fold_left (fun acc (idx, value) -> + if idx < n then (idx, value) :: acc + else if idx = n then (n, new_val) :: (idx + 1, value) :: acc + else (idx + 1, value) :: acc + ) [] (List.rev v.entries) in + {entries = entries'; len = v.len + 1} let mul_vec_scal v s = {entries= (List.map (fun (idx, va) -> (idx, va *: s)) v.entries); len=v.len} @@ -110,14 +119,14 @@ module SparseVector: AbstractVector = failwith "TODO" let zero_vec n = - failwith "TODO" + {entries = []; len = n} let is_zero_vec v = (v.entries = []) let nth v n = if n >= v.len then failwith "V.nth out of bounds" else - let rec nth v = match v with + let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) | [] -> A.zero | (col_idx, value) :: xs when col_idx > n -> A.zero | (col_idx, value) :: xs when col_idx = n -> value @@ -143,19 +152,22 @@ module SparseVector: AbstractVector = failwith "TODO" let compare_length_with v n = - failwith "TODO" + Int.compare v.len n let of_list l = - failwith "TODO" + let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l + in {entries = entries'; len = List.length l} let to_list v = - failwith "TODO" + let l = List.init v.len (fun _ -> A.zero) in + List.fold_left (fun acc (idx, value) -> (List.modify_at idx (fun _ -> value) acc)) l v.entries let filteri f v = failwith "TODO" let append v v' = - failwith "TODO" + let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in + {entries = entries'; len = v.len + v'.len} let exists f v = failwith "TODO" From d439b20f591beccd6cfc2d9b2627ad87285553e6 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 28 Nov 2024 14:42:10 +0100 Subject: [PATCH 047/240] vector conversion to array --- .../sparseImplementation/sparseVector.ml | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6a792336c4..d4ea9b28fb 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -3,7 +3,9 @@ open RatOps open ConvenienceOps open BatList +open BatArray module List = BatList +module Array = BatArray module SparseVector: AbstractVector = functor (A: RatOps) -> @@ -116,7 +118,7 @@ module SparseVector: AbstractVector = failwith "TODO" let apply_with_c_with f m v = - failwith "TODO" + failwith "deprecated" let zero_vec n = {entries = []; len = n} @@ -173,31 +175,36 @@ module SparseVector: AbstractVector = failwith "TODO" let rev v = - failwith "TODO" + let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - idx, value)) v.entries in + {entries = entries'; len = v.len} let rev_with v = - failwith "TODO" + failwith "deprecated" let map2i f v v' = failwith "TODO" let map2i_with f v v' = - failwith "TODO" + failwith "deprecated" let mapi f v = failwith "TODO" let mapi_with f v = - failwith "TODO" + failwith "deprecated" let find2i f v v' = failwith "TODO" let to_array v = - failwith "TODO" + let vec = Array.make v.len A.zero in + List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; + vec let of_array a = - failwith "TODO" + let len' = Array.length a in + let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in + {entries = entries'; len = len'} let copy v = v From 03fab15a0a2b2d3067dedc1e2e65aee86f398d5d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 15:01:50 +0100 Subject: [PATCH 048/240] Explicit types on normalize --- .../sparseImplementation/sparseMatrix.ml | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 1ba26f2771..d961b2a59c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -184,18 +184,22 @@ module ListMatrix: AbstractMatrix = failwith "deprecated" let normalize_with m = Timing.wrap "normalize_with" normalize_with m - - let normalize m = - let entries = m.entries in - let col_count = m.column_count in - let swap_rows m r1_idx r2_idx = + + let normalize (m : t) : t Option.t = + let entries = m in + let col_count = num_cols m in + let swap_rows (m : t) (r1_idx : int) (r2_idx : int) : t = + failwith "TODO" + (* List.mapi (fun i row -> if i = r1_idx then List.nth m r2_idx else if i = r2_idx then List.nth m r1_idx else row - ) entries + ) entries*) in - let rec sub_rows minu subt : (int * A.t) list = + let rec sub_rows (minu : V.t) (subt : V.t) : (int * A.t) list = + failwith "TODO" + (* match minu, subt with | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( match xidx - yidx with @@ -206,18 +210,25 @@ module ListMatrix: AbstractMatrix = | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) | ([],[]) -> [] + *) in - let div_row row pivot = + let div_row (row : V.t) (pivot : A.t) : V.t = + failwith "TODO" + (* List.map (fun (idx, value) -> (idx, value /: pivot)) row + *) in - let dec_mat_2D m = + let dec_mat_2D (m : t) : t = m in - let rec find_pivot_in_col m row_idx col_idx = + let rec find_pivot_in_col (m : t) (row_idx : int) (col_idx : int) : (int * A.t) Option.t = + failwith "TODO" + (* match m with | ((idx, value)::_)::xs -> if idx = col_idx then Some (row_idx, value) else find_pivot_in_col xs (row_idx + 1) col_idx | ([])::xs -> find_pivot_in_col xs (row_idx + 1) col_idx | [] -> None + *) in (* let rec find_pivot m col_idx row_idx = if col_idx >= col_count then None else @@ -225,7 +236,9 @@ module ListMatrix: AbstractMatrix = | Some (row_idx, value) -> Some (row_idx, value) | None -> find_pivot m (col_idx + 1) row_idx in *) - let rec main_loop m m' row_idx col_idx : (int * A.t) list list = + let rec main_loop (m : t) (m' : t) (row_idx : int) (col_idx : int) : t = + failwith "TODO" + (* if col_idx = (col_count - 1) (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) then m else @@ -239,10 +252,10 @@ module ListMatrix: AbstractMatrix = let m' = dec_mat_2D m in main_loop subtracted_m m' (row_idx + 1) (col_idx + 1) ) - + *) in - let e' = main_loop m.entries m.entries 0 0 in - Some {entries = e'; column_count = m.column_count} + let m' = main_loop m m 0 0 in + Some m' let rref_vec_helper m pivot_positions v = failwith "TODO" From f018a0630b42323d5b3ea35f33c3dae48b2a0bf7 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 28 Nov 2024 14:43:02 +0100 Subject: [PATCH 049/240] map2_preserve_zero --- .../sparseImplementation/sparseVector.ml | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6a792336c4..685fcbd22d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -89,28 +89,31 @@ module SparseVector: AbstractVector = ) [] (List.rev v.entries) in {entries = entries'; len = v.len + 1} - let mul_vec_scal v s = - {entries= (List.map (fun (idx, va) -> (idx, va *: s)) v.entries); len=v.len} - - - let add_vec v1 v2 = - let rec add_vec m s = - match m, s with - | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( - match xidx - yidx with - | d when d = 0 && (xv +: yv = A.zero) -> (xidx, xv +: yv)::(add_vec xs ys) - | d when d < 0 -> (xidx, xv)::(add_vec xs ((yidx, yv)::ys)) - | d when d > 0 -> (yidx, yv)::(add_vec ((xidx, xv)::xs) ys) - | _ -> add_vec xs ys ) (* remove row when is (0, 0) *) - | ([], y::ys) -> y::(add_vec [] ys) - | (x::xs, []) -> x::(add_vec xs []) - | ([],[]) -> [] + let map_preserve_zero f v = tV ((List.map f) v.entries) v.len + + let map2_preserve_zero f v1 v2 = + let rec map2_nonzero_aux v1 v2 = + match v1, v2 with + | [], [] -> [] + | x , y -> + let cons, xtail, ytail = + match x, y with + | (xidx, xv)::xs, (yidx,yv)::ys -> ( + match xidx - yidx with + | d when d < 0 -> (xidx, f xv A.zero), xs, v2 + | d when d > 0 -> (yidx, f A.zero yv), v1, ys + | _ -> (xidx, f xv yv) , xs, ys + ) + | (xidx, xv)::xs, [] -> (xidx, f xv A.zero), xs, [] + | [], (yidx, yv)::ys -> (yidx, f A.zero yv), [], ys + | [],[] -> raise (Failure "Should never be reached") + in + let res = if snd cons = A.zero then [] else [cons] in + res@(map2_nonzero_aux xtail ytail) in - if v1.len <> v2.len then failwith "Different Vector length" else - {entries= add_vec v1.entries v2.entries; len=v1.len} + if v1.len <> v2.len then raise (Invalid_argument "Different lengths") else + tV (map2_nonzero_aux v1.entries v2.entries) v1.len - let sub_vec v1 v2 = (*change to duplicate def of add if performance*) - add_vec v1 ({entries= (List.map (fun (idx, va) -> (idx, A.zero -: va)) v2.entries); len=v2.len}) let apply_with_c f m v = failwith "TODO" From 70dbf4de31d5ca9e4e86a4e7a23116d23bf0fa82 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 28 Nov 2024 15:15:17 +0100 Subject: [PATCH 050/240] exists, vector interface --- .../sparseImplementation/sparseVector.ml | 13 +++++++++---- src/cdomains/affineEquality/vector.ml | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 685fcbd22d..9fffacb57d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -143,7 +143,7 @@ module SparseVector: AbstractVector = failwith "TODO" let map2_with f v v' = - failwith "TODO" + failwith "deprecated" let findi f v = failwith "TODO" @@ -173,9 +173,14 @@ module SparseVector: AbstractVector = {entries = entries'; len = v.len + v'.len} let exists f v = - failwith "TODO" - - let rev v = + let c = v.len in + let rec exists_aux at f v = + match v with + | [] -> if at = 0 then false else f A.zero + | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs + in (exists_aux c f v.entries) + + let rev v = failwith "TODO" let rev_with v = diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index a673b820c7..ce7558c05a 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -18,6 +18,8 @@ sig val insert_val_at: int -> num -> t -> t + val map_preserve_zero: ((int * num) -> (int * num)) -> t -> t + val map2_preserve_zero: ((int * num) -> (int * num) -> (int * num)) -> t -> t -> t val apply_with_c: (num -> num -> num) -> num -> t -> t val apply_with_c_with: (num -> num -> num) -> num -> t -> unit From 215b25eb599b6b94a6c0efb2bc0c52d6c57b126e Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 28 Nov 2024 15:17:01 +0100 Subject: [PATCH 051/240] ups --- src/cdomains/affineEquality/vector.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index ce7558c05a..9da0729cc5 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -18,8 +18,8 @@ sig val insert_val_at: int -> num -> t -> t - val map_preserve_zero: ((int * num) -> (int * num)) -> t -> t - val map2_preserve_zero: ((int * num) -> (int * num) -> (int * num)) -> t -> t -> t + val map_preserve_zero: (num -> num) -> t -> t + val map2_preserve_zero: (num -> num -> num) -> t -> t -> t val apply_with_c: (num -> num -> num) -> num -> t -> t val apply_with_c_with: (num -> num -> num) -> num -> t -> unit From 680e56ba3ba99a8226fa0d5857d58e35ae686e16 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 16:43:01 +0100 Subject: [PATCH 052/240] Reimplemented normalize in SparseMatrix, some TODOs missing --- .../arrayImplementation/arrayMatrix.ml | 3 + src/cdomains/affineEquality/matrix.ml | 2 + .../sparseImplementation/sparseMatrix.ml | 97 ++++++++----------- src/cdomains/affineEquality/vector.ml | 2 + 4 files changed, 45 insertions(+), 59 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index dc24b7f641..9212cf501f 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -355,4 +355,7 @@ module ArrayMatrix: AbstractMatrix = map2i_with f m' v; m' + let swap_rows m j k = + failwith "TODO" + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index 33a622d81a..3b45c12f91 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -71,4 +71,6 @@ sig val copy: t -> t + val swap_rows: t -> int -> int -> t + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index d961b2a59c..658e8b4c7e 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -184,75 +184,54 @@ module ListMatrix: AbstractMatrix = failwith "deprecated" let normalize_with m = Timing.wrap "normalize_with" normalize_with m - + + + let sub_rows (minu : V.t) (subt : V.t) : V.t = + V.map2_preserve_zero (-:) minu subt + + let div_row (row : V.t) (pivot : A.t) : V.t = + V.map_preserve_zero (fun a -> a /: pivot) row + + let swap_rows m j k = + List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m k else row) m + let normalize (m : t) : t Option.t = - let entries = m in let col_count = num_cols m in - let swap_rows (m : t) (r1_idx : int) (r2_idx : int) : t = - failwith "TODO" - (* - List.mapi (fun i row -> - if i = r1_idx then List.nth m r2_idx - else if i = r2_idx then List.nth m r1_idx - else row - ) entries*) - in - let rec sub_rows (minu : V.t) (subt : V.t) : (int * A.t) list = - failwith "TODO" - (* - match minu, subt with - | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( - match xidx - yidx with - | d when d = 0 && xv <> yv -> (xidx, xv -: yv)::(sub_rows xs ys) - | d when d < 0 -> (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) - | d when d > 0 -> (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) - | _ -> sub_rows xs ys ) (* remove row when is (0, 0) *) - | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) - | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) - | ([],[]) -> [] - *) - in - let div_row (row : V.t) (pivot : A.t) : V.t = - failwith "TODO" - (* - List.map (fun (idx, value) -> (idx, value /: pivot)) row - *) - in - let dec_mat_2D (m : t) : t = + + let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = m in - let rec find_pivot_in_col (m : t) (row_idx : int) (col_idx : int) : (int * A.t) Option.t = - failwith "TODO" - (* - match m with - | ((idx, value)::_)::xs -> if idx = col_idx then Some (row_idx, value) else find_pivot_in_col xs (row_idx + 1) col_idx - | ([])::xs -> find_pivot_in_col xs (row_idx + 1) col_idx - | [] -> None - *) - in - (* let rec find_pivot m col_idx row_idx = - if col_idx >= col_count then None else - match find_pivot_in_col m col_idx row_idx with - | Some (row_idx, value) -> Some (row_idx, value) - | None -> find_pivot m (col_idx + 1) row_idx - in *) + (* Function for finding a pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) + let rec find_pivot (m : t) (row_idx : int) (col_idx : int) : (int * int * A.t) Option.t = + if col_idx >= col_count then None else + let get_first_non_zero v = (* Returns (col_idx, value) of first non-zero row*) + let v' = V.to_sparse_list v in + match v' with + | [] -> None + | (idx, value)::_ -> Some (idx, value) + in + (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) + let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> + let row_first_non_zero = get_first_non_zero row in + match row_first_non_zero with + | None -> (cur_row, cur_col, cur_val) + | Some (col_idx, value) -> if col_idx < cur_col then (i, col_idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) + in + if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) + in let rec main_loop (m : t) (m' : t) (row_idx : int) (col_idx : int) : t = - failwith "TODO" - (* - if col_idx = (col_count - 1) (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) - then m + if col_idx = (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else - match find_pivot_in_col m' row_idx col_idx with - | None -> main_loop m m' row_idx (col_idx + 1) - | Some (piv_row_idx, piv_val) -> ( + match find_pivot m' row_idx col_idx with + | None -> m (* No pivot found means already normalized*) + | Some (piv_row_idx, piv_col_idx, piv_val) -> ( let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in let piv_row = (List.nth normalized_m row_idx) in let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in - let m' = dec_mat_2D m in - main_loop subtracted_m m' (row_idx + 1) (col_idx + 1) - ) - *) + let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in + main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in Some m' diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 9da0729cc5..0412c05356 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -19,7 +19,9 @@ sig val insert_val_at: int -> num -> t -> t val map_preserve_zero: (num -> num) -> t -> t + val map2_preserve_zero: (num -> num -> num) -> t -> t -> t + val apply_with_c: (num -> num -> num) -> num -> t -> t val apply_with_c_with: (num -> num -> num) -> num -> t -> unit From 40996b77fdc523a3a52055cf7690ec4ff18eb383 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 28 Nov 2024 16:50:14 +0100 Subject: [PATCH 053/240] Renamed sparseMatrix.ml to match module name --- .../sparseImplementation/{sparseMatrix.ml => listMatrix.ml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/cdomains/affineEquality/sparseImplementation/{sparseMatrix.ml => listMatrix.ml} (99%) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml similarity index 99% rename from src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml rename to src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index d961b2a59c..8756be9712 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -184,7 +184,7 @@ module ListMatrix: AbstractMatrix = failwith "deprecated" let normalize_with m = Timing.wrap "normalize_with" normalize_with m - + let normalize (m : t) : t Option.t = let entries = m in let col_count = num_cols m in From 702f258a9c3f3914a9751531ed0d574a7975dcc1 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 28 Nov 2024 16:56:34 +0100 Subject: [PATCH 054/240] builds now + reduce_col --- .../arrayImplementation/arrayVector.ml | 3 ++ .../sparseImplementation/sparseMatrix.ml | 44 ++++++------------- .../sparseImplementation/sparseVector.ml | 18 ++++++-- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 030d397398..05cbaec7d1 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -111,4 +111,7 @@ module ArrayVector: AbstractVector = let find_opt f v = failwith "TODO" + + let map_preserve_zero f v = failwith "TODO" + let map2_preserve_zero f v1 v2 = failwith "TODO" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml index 8756be9712..76b7868f5f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseMatrix.ml @@ -106,44 +106,28 @@ module ListMatrix: AbstractMatrix = failwith "deprecated" let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j - let reduce_col m j = + let reduce_col m j = if is_empty m then m else let rec find_pivot idx entries = (* Finds non-zero element in column j and returns pair of row idx and the pivot value *) match entries with | [] -> None - | row :: rest -> match (List.assoc_opt j row) with - | None -> find_pivot (idx - 1) rest - | Some value -> Some (idx, value) + | row :: rest -> let value = V.nth row j in + if value =: A.zero then find_pivot (idx - 1) rest else Some (idx, value) in - match (find_pivot (num_rows m - 1) (List.rev m.entries)) with + match (find_pivot (num_rows m - 1) (List.rev m)) with | None -> m (* column is already filled with zeroes *) | Some (row_idx, pivot) -> - let pivot_row = List.nth m.entries row_idx in - let entries' = - List.mapi(fun idx row -> - if idx = row_idx then - [] - else - match (List.assoc_opt j row) with (* Find column element in row and, if it exists, subtract row *) - | None -> row - | Some row_value -> (let s = row_value /: pivot in - let rec merge acc piv_row cur_row = - match piv_row, cur_row with - | [], [] -> acc - | [], (i, value) :: rest -> merge ((i, value) :: acc) piv_row rest - | (i, value) :: rest, [] -> let new_value = A.zero -: s *: value in merge ((i, new_value) :: acc) rest cur_row - | (i, piv_val) :: piv_rest, (j, cur_val) :: cur_rest -> - if i = j then - let new_value = cur_val -: s *: piv_val in merge ((i, new_value) :: acc) piv_rest cur_rest - else if i < j then - let new_value = A.zero -: s *: piv_val in merge ((i, new_value) :: acc) piv_rest cur_row - else - merge ((j, cur_val) :: acc) piv_row cur_rest - in List.rev @@ merge [] pivot_row row) - ) m.entries - in - {entries = entries'; column_count = m.column_count} + let pivot_row = List.nth m row_idx in + List.mapi (fun idx row -> + if idx = row_idx then + V.zero_vec (num_cols m) + else + let row_value = V.nth row j in + if row_value = A.zero then row + else (let s = row_value /: pivot in + V.map2_preserve_zero (fun x y -> x -: s *: y) row pivot_row) + ) m let del_col m j = if num_cols m = 1 then empty () diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 218fb36578..a346d0fc51 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -18,8 +18,6 @@ module SparseVector: AbstractVector = }[@@deriving eq, ord, hash] let tV e l = {entries=e; len=l} - let show v = - failwith "TODO" let keep_vals v n = let rec keep_vals_vec v n = @@ -91,8 +89,13 @@ module SparseVector: AbstractVector = ) [] (List.rev v.entries) in {entries = entries'; len = v.len + 1} - let map_preserve_zero f v = tV ((List.map f) v.entries) v.len + let map_preserve_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) + let entries' = List.filter_map ( + fun (idx, value) -> let new_val = f value in + if new_val = A.zero then None else Some (idx, new_val)) v.entries in + {entries = entries'; len = v.len} + (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) let map2_preserve_zero f v1 v2 = let rec map2_nonzero_aux v1 v2 = match v1, v2 with @@ -225,4 +228,13 @@ module SparseVector: AbstractVector = let find_opt f v = failwith "TODO: Do we need this?" + let show v = + let t = to_list v in + let rec list_str l = + match l with + | [] -> "]" + | x :: xs -> (A.to_string x) ^" "^(list_str xs) + in + "["^list_str t^"\n" + end \ No newline at end of file From bec7535afb3f47a6824e45675cb8543c5e0b8fc7 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 17:14:15 +0100 Subject: [PATCH 055/240] Moved swap, div, sub and normalize to new listMatrix.ml --- .../sparseImplementation/listMatrix.ml | 94 +++++++------------ 1 file changed, 36 insertions(+), 58 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 76b7868f5f..a4b66bf4b2 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -169,74 +169,52 @@ module ListMatrix: AbstractMatrix = let normalize_with m = Timing.wrap "normalize_with" normalize_with m + let sub_rows (minu : V.t) (subt : V.t) : V.t = + V.map2_preserve_zero (-:) minu subt + + let div_row (row : V.t) (pivot : A.t) : V.t = + V.map_preserve_zero (fun a -> a /: pivot) row + + let swap_rows m j k = + List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m k else row) m + let normalize (m : t) : t Option.t = - let entries = m in let col_count = num_cols m in - let swap_rows (m : t) (r1_idx : int) (r2_idx : int) : t = - failwith "TODO" - (* - List.mapi (fun i row -> - if i = r1_idx then List.nth m r2_idx - else if i = r2_idx then List.nth m r1_idx - else row - ) entries*) - in - let rec sub_rows (minu : V.t) (subt : V.t) : (int * A.t) list = - failwith "TODO" - (* - match minu, subt with - | ((xidx, xv)::xs, (yidx,yv)::ys) -> ( - match xidx - yidx with - | d when d = 0 && xv <> yv -> (xidx, xv -: yv)::(sub_rows xs ys) - | d when d < 0 -> (xidx, xv)::(sub_rows xs ((yidx, yv)::ys)) - | d when d > 0 -> (yidx, A.zero -: yv)::(sub_rows ((xidx, xv)::xs) ys) - | _ -> sub_rows xs ys ) (* remove row when is (0, 0) *) - | ([], (yidx, yv)::ys) -> (yidx, A.zero -: yv)::(sub_rows [] ys) - | ((xidx, xv)::xs, []) -> (xidx, xv)::(sub_rows xs []) - | ([],[]) -> [] - *) - in - let div_row (row : V.t) (pivot : A.t) : V.t = - failwith "TODO" - (* - List.map (fun (idx, value) -> (idx, value /: pivot)) row - *) - in - let dec_mat_2D (m : t) : t = + + let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = m in - let rec find_pivot_in_col (m : t) (row_idx : int) (col_idx : int) : (int * A.t) Option.t = - failwith "TODO" - (* - match m with - | ((idx, value)::_)::xs -> if idx = col_idx then Some (row_idx, value) else find_pivot_in_col xs (row_idx + 1) col_idx - | ([])::xs -> find_pivot_in_col xs (row_idx + 1) col_idx - | [] -> None - *) - in - (* let rec find_pivot m col_idx row_idx = - if col_idx >= col_count then None else - match find_pivot_in_col m col_idx row_idx with - | Some (row_idx, value) -> Some (row_idx, value) - | None -> find_pivot m (col_idx + 1) row_idx - in *) + (* Function for finding a pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) + let rec find_pivot (m : t) (row_idx : int) (col_idx : int) : (int * int * A.t) Option.t = + if col_idx >= col_count then None else + let get_first_non_zero v = (* Returns (col_idx, value) of first non-zero row*) + let v' = V.to_sparse_list v in + match v' with + | [] -> None + | (idx, value)::_ -> Some (idx, value) + in + (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) + let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> + let row_first_non_zero = get_first_non_zero row in + match row_first_non_zero with + | None -> (cur_row, cur_col, cur_val) + | Some (col_idx, value) -> if col_idx < cur_col then (i, col_idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) + in + if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) + in let rec main_loop (m : t) (m' : t) (row_idx : int) (col_idx : int) : t = - failwith "TODO" - (* - if col_idx = (col_count - 1) (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) - then m + if col_idx = (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else - match find_pivot_in_col m' row_idx col_idx with - | None -> main_loop m m' row_idx (col_idx + 1) - | Some (piv_row_idx, piv_val) -> ( + match find_pivot m' row_idx col_idx with + | None -> m (* No pivot found means already normalized*) + | Some (piv_row_idx, piv_col_idx, piv_val) -> ( let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in let piv_row = (List.nth normalized_m row_idx) in let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in - let m' = dec_mat_2D m in - main_loop subtracted_m m' (row_idx + 1) (col_idx + 1) - ) - *) + let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in + main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in Some m' From ad34bc7470a70b33e14b2bd6bf8f71a63294eae9 Mon Sep 17 00:00:00 2001 From: Havercake Date: Thu, 28 Nov 2024 17:19:51 +0100 Subject: [PATCH 056/240] Renamed tV according to best practices --- .../affineEquality/sparseImplementation/sparseVector.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a346d0fc51..f8b65afb9a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -17,7 +17,7 @@ module SparseVector: AbstractVector = len: int }[@@deriving eq, ord, hash] - let tV e l = {entries=e; len=l} + let to_vector e l = {entries=e; len=l} let keep_vals v n = let rec keep_vals_vec v n = @@ -117,7 +117,7 @@ module SparseVector: AbstractVector = res@(map2_nonzero_aux xtail ytail) in if v1.len <> v2.len then raise (Invalid_argument "Different lengths") else - tV (map2_nonzero_aux v1.entries v2.entries) v1.len + to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len let apply_with_c f m v = From bd81ac15d0726adc1207c0cc04121ff7ccf27568 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 18:00:42 +0100 Subject: [PATCH 057/240] Implement vector findi and minor bugfix in ListMatrix normalize --- .../affineEquality/sparseImplementation/listMatrix.ml | 2 +- .../affineEquality/sparseImplementation/sparseVector.ml | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index a4b66bf4b2..4fb1f80969 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -198,7 +198,7 @@ module ListMatrix: AbstractMatrix = let row_first_non_zero = get_first_non_zero row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) - | Some (col_idx, value) -> if col_idx < cur_col then (i, col_idx, value) else (cur_row, cur_col, cur_val) + | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) in if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index f8b65afb9a..1fefe8e545 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -151,7 +151,10 @@ module SparseVector: AbstractVector = failwith "deprecated" let findi f v = - failwith "TODO" + if f A.zero then + fst @@ List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) + else + fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) let map f v = failwith "TODO" From 06a32ea49ae2d8393f9846648ffd05f06e1be0d4 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 28 Nov 2024 18:26:52 +0100 Subject: [PATCH 058/240] vectorfuncs, foldleftpreservezero --- .../sparseImplementation/sparseVector.ml | 42 ++++++++++++------- src/cdomains/affineEquality/vector.ml | 8 +++- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 1fefe8e545..10dfdb90c6 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -117,8 +117,13 @@ module SparseVector: AbstractVector = res@(map2_nonzero_aux xtail ytail) in if v1.len <> v2.len then raise (Invalid_argument "Different lengths") else - to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len + to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len + let fold_left_preserve_zero f v = + failwith "TODO" + + let fold_left2_preserve_zero f v v' = + failwith "TODO" let apply_with_c f m v = failwith "TODO" @@ -143,10 +148,24 @@ module SparseVector: AbstractVector = let length v = v.len + + let of_list l = + let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l + in {entries = entries'; len = List.length l} + let to_list v = + let[@tail_mod_cons] rec extend_zero_aux i v' = + if i >= v.len then failwith "out of Bounds for to_list" else (*can probably be removed*) + match v' with + | (xi,xv)::xs -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero::(extend_zero_aux (i+1) v') + | [] -> [] + in + (extend_zero_aux 0 v.entries) + let map2 f v v' = - failwith "TODO" - + if v.len <> v'.len then failwith "Unequal vector length" else + of_list (List.map2 f (to_list v) (to_list v')) + let map2_with f v v' = failwith "deprecated" @@ -157,22 +176,14 @@ module SparseVector: AbstractVector = fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) let map f v = - failwith "TODO" + of_list (List.map f (to_list v)) let map_with f v = - failwith "TODO" + failwith "deprecated" let compare_length_with v n = Int.compare v.len n - let of_list l = - let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l - in {entries = entries'; len = List.length l} - - let to_list v = - let l = List.init v.len (fun _ -> A.zero) in - List.fold_left (fun acc (idx, value) -> (List.modify_at idx (fun _ -> value) acc)) l v.entries - let filteri f v = failwith "TODO" @@ -196,20 +207,19 @@ module SparseVector: AbstractVector = failwith "deprecated" let map2i f v v' = - failwith "TODO" + of_list (List.map2i f (to_list v) (to_list v')) let map2i_with f v v' = failwith "deprecated" let mapi f v = - failwith "TODO" + of_list (List.mapi f (to_list v)) let mapi_with f v = failwith "deprecated" let find2i f v v' = failwith "TODO" - let to_array v = let vec = Array.make v.len A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 9da0729cc5..96f89dcb18 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -19,7 +19,13 @@ sig val insert_val_at: int -> num -> t -> t val map_preserve_zero: (num -> num) -> t -> t - val map2_preserve_zero: (num -> num -> num) -> t -> t -> t + + val map2_preserve_zero: (num -> num -> num) -> t -> t -> t + + val fold_left_preserve_zero: ('acc -> num -> 'acc) -> t -> 'acc + + val fold_left2_preserve_zero: ('acc -> num -> num -> 'acc) -> t -> t -> 'acc + val apply_with_c: (num -> num -> num) -> num -> t -> t val apply_with_c_with: (num -> num -> num) -> num -> t -> unit From 05a3dc5dd1cc7c6aa79647f0d7b163590acd64a8 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 18:37:11 +0100 Subject: [PATCH 059/240] Add normalize check for invalid affeq matrix --- .../affineEquality/sparseImplementation/listMatrix.ml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 4fb1f80969..9b684406aa 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -178,6 +178,12 @@ module ListMatrix: AbstractMatrix = let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m k else row) m + let is_valid_affeq_matrix m = + let col_count = num_cols m in + List.exists (fun row -> (* Invalid if row is zero, but coefficient is not zero *) + V.fold_left_preserve_zero (fun found_non_zero (col_idx, value) -> if col_idx = col_count - 1 && (not found_non_zero) && (value <>: A.zero) then false else found_non_zero) false row + ) m + let normalize (m : t) : t Option.t = let col_count = num_cols m in @@ -204,7 +210,7 @@ module ListMatrix: AbstractMatrix = if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) in let rec main_loop (m : t) (m' : t) (row_idx : int) (col_idx : int) : t = - if col_idx = (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) + if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else match find_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized*) @@ -217,7 +223,7 @@ module ListMatrix: AbstractMatrix = main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in - Some m' + if is_valid_affeq_matrix m' then Some m' else None let rref_vec_helper m pivot_positions v = failwith "TODO" From 409c01d0f42b914cca3a5c39119eee9499a5f4b8 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 21:09:55 +0100 Subject: [PATCH 060/240] Vector function findi_val_opt --- .../arrayImplementation/arrayVector.ml | 16 +++++++++ .../sparseImplementation/sparseVector.ml | 33 ++++++++++++------- src/cdomains/affineEquality/vector.ml | 5 ++- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 05cbaec7d1..dcd442f498 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -114,4 +114,20 @@ module ArrayVector: AbstractVector = let map_preserve_zero f v = failwith "TODO" let map2_preserve_zero f v1 v2 = failwith "TODO" + + let fold_left_preserve_zero f v = + failwith "TODO" + + let fold_left2_preserve_zero f v v' = + failwith "TODO" + + let fold_left_preserve_zero f v = + failwith "TODO" + + let fold_left2_preserve_zero f v v' = + failwith "TODO" + + let findi_val_opt f v = + failwith "TODO" + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 10dfdb90c6..4f275f4514 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -117,7 +117,7 @@ module SparseVector: AbstractVector = res@(map2_nonzero_aux xtail ytail) in if v1.len <> v2.len then raise (Invalid_argument "Different lengths") else - to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len + to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len let fold_left_preserve_zero f v = failwith "TODO" @@ -148,24 +148,24 @@ module SparseVector: AbstractVector = let length v = v.len - + let of_list l = let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l in {entries = entries'; len = List.length l} let to_list v = let[@tail_mod_cons] rec extend_zero_aux i v' = - if i >= v.len then failwith "out of Bounds for to_list" else (*can probably be removed*) - match v' with - | (xi,xv)::xs -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero::(extend_zero_aux (i+1) v') - | [] -> [] - in - (extend_zero_aux 0 v.entries) - + if i >= v.len then failwith "out of Bounds for to_list" else (*can probably be removed*) + match v' with + | (xi,xv)::xs -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero::(extend_zero_aux (i+1) v') + | [] -> [] + in + (extend_zero_aux 0 v.entries) + let map2 f v v' = if v.len <> v'.len then failwith "Unequal vector length" else - of_list (List.map2 f (to_list v) (to_list v')) - + of_list (List.map2 f (to_list v) (to_list v')) + let map2_with f v v' = failwith "deprecated" @@ -175,6 +175,17 @@ module SparseVector: AbstractVector = else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) + let findi_val_opt f v = + if f A.zero then + ( + let i, (col_idx, value) = List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries in + if i < col_idx then (* In this case, Zero was the first element found because iteration index i is smaller than "found" value *) + Some (i, A.zero) + else Some (col_idx, value) + ) + else + Some (List.find (fun (idx, value) -> f value) v.entries) + let map f v = of_list (List.map f (to_list v)) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 96f89dcb18..a97289b768 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -21,7 +21,7 @@ sig val map_preserve_zero: (num -> num) -> t -> t val map2_preserve_zero: (num -> num -> num) -> t -> t -> t - + val fold_left_preserve_zero: ('acc -> num -> 'acc) -> t -> 'acc val fold_left2_preserve_zero: ('acc -> num -> num -> 'acc) -> t -> t -> 'acc @@ -44,6 +44,9 @@ sig val findi: (num -> bool) -> t -> int + (* Returns optional tuple of position and value which was found*) + val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t + val find_opt: (num -> bool) -> t -> num Option.t val map: (num -> num) -> t -> t From ad9f6180fe84e8c466dc74942ff4a1224738db52 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 21:11:15 +0100 Subject: [PATCH 061/240] Adapting normalize and reordering deprecated functions in ListMatrix.ml --- .../arrayImplementation/arrayMatrix.ml | 12 +- .../sparseImplementation/listMatrix.ml | 107 +++++++++--------- 2 files changed, 65 insertions(+), 54 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 9212cf501f..1f4722adff 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -321,8 +321,6 @@ module ArrayMatrix: AbstractMatrix = let find_opt f m = let f' x = f (V.of_array x) in Option.map V.of_array (Array.find_opt f' m) - let map2 f m v = - let f' x y = V.to_array @@ f (V.of_array x) y in Array.map2 f' m (V.to_array v) let map2_with f m v = if num_rows m = V.length v then @@ -332,6 +330,16 @@ module ArrayMatrix: AbstractMatrix = m.(i) <- V.to_array @@ f (V.of_array m.(i)) (V.nth v i) done + (* Deprecated + let map2 f m v = + let f' x y = V.to_array @@ f (V.of_array x) y in Array.map2 f' m (V.to_array v) + *) + + let map2 f m v = + let m' = copy m in + map2_with f m' v; + m' + let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v let map2i_with f m v = diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 9b684406aa..6b1c71d52c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -89,11 +89,6 @@ module ListMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - let set_col_with m new_col n = - failwith "deprecated" - - let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n - let set_col m new_col n = List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m @@ -102,10 +97,6 @@ module ListMatrix: AbstractMatrix = let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 - let reduce_col_with m j = - failwith "deprecated" - - let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = if is_empty m then m else @@ -150,11 +141,6 @@ module ListMatrix: AbstractMatrix = let remove_zero_rows m = List.filter (fun row -> not (V.is_zero_vec row)) m - let rref_with m = - failwith "deprecated" - - let rref_with m = Timing.wrap "rref_with" rref_with m - let init_with_vec v = [v] @@ -164,11 +150,6 @@ module ListMatrix: AbstractMatrix = let get_pivot_positions m = failwith "TODO" - let normalize_with m = - failwith "deprecated" - - let normalize_with m = Timing.wrap "normalize_with" normalize_with m - let sub_rows (minu : V.t) (subt : V.t) : V.t = V.map2_preserve_zero (-:) minu subt @@ -176,32 +157,28 @@ module ListMatrix: AbstractMatrix = V.map_preserve_zero (fun a -> a /: pivot) row let swap_rows m j k = - List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m k else row) m + List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m let is_valid_affeq_matrix m = + failwith "TODO" + (* let col_count = num_cols m in List.exists (fun row -> (* Invalid if row is zero, but coefficient is not zero *) - V.fold_left_preserve_zero (fun found_non_zero (col_idx, value) -> if col_idx = col_count - 1 && (not found_non_zero) && (value <>: A.zero) then false else found_non_zero) false row + V.fold_left_preserve_zero (fun found_non_zero (col_idx, value) -> if col_idx = col_count - 1 && (not found_non_zero) && (value <>: A.zero) then false else found_non_zero) false row ) m + *) - let normalize (m : t) : t Option.t = + let normalize m = let col_count = num_cols m in - let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = m in - (* Function for finding a pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) - let rec find_pivot (m : t) (row_idx : int) (col_idx : int) : (int * int * A.t) Option.t = + (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) + let find_first_pivot m row_idx col_idx = if col_idx >= col_count then None else - let get_first_non_zero v = (* Returns (col_idx, value) of first non-zero row*) - let v' = V.to_sparse_list v in - match v' with - | [] -> None - | (idx, value)::_ -> Some (idx, value) - in (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> - let row_first_non_zero = get_first_non_zero row in + let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) @@ -209,10 +186,10 @@ module ListMatrix: AbstractMatrix = in if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) in - let rec main_loop (m : t) (m' : t) (row_idx : int) (col_idx : int) : t = + let rec main_loop m m' row_idx col_idx = if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else - match find_pivot m' row_idx col_idx with + match find_first_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized*) | Some (piv_row_idx, piv_col_idx, piv_val) -> ( let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in @@ -225,16 +202,6 @@ module ListMatrix: AbstractMatrix = let m' = main_loop m m 0 0 in if is_valid_affeq_matrix m' then Some m' else None - let rref_vec_helper m pivot_positions v = - failwith "TODO" - - let rref_vec_with m v = - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) - (*m must be in rref form and contain the same num of cols as v*) - (*If m is empty then v is simply normalized and returned*) - failwith "deprecated" - - let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) @@ -243,13 +210,6 @@ module ListMatrix: AbstractMatrix = let rref_vec m v = normalize @@ append_matrices m (init_with_vec v) - let rref_matrix_with m1 m2 = - (*Similar to rref_vec_with but takes two matrices instead.*) - (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - failwith "deprecated" - - let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 - (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) (*TODO: OPTIMIZE!*) @@ -268,13 +228,56 @@ module ListMatrix: AbstractMatrix = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m + let rref_vec_helper m pivot_positions v = + failwith "TODO" + + + (* ------------------------- Deprecated ------------------------*) + + let rref_vec_with m v = + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*m must be in rref form and contain the same num of cols as v*) + (*If m is empty then v is simply normalized and returned*) + failwith "deprecated" + + let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v + let rref_with m = + failwith "deprecated" + + let reduce_col_with m j = + failwith "deprecated" + + let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j + + + let rref_with m = Timing.wrap "rref_with" rref_with m + + let normalize_with m = + failwith "deprecated" + + let normalize_with m = Timing.wrap "normalize_with" normalize_with m + + + let set_col_with m new_col n = + failwith "deprecated" + + let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n + let map2_with f m v = failwith "deprecated" let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v let map2i_with f m v = - failwith "Do not use!" + failwith "deprecated" let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v + + let rref_matrix_with m1 m2 = + (*Similar to rref_vec_with but takes two matrices instead.*) + (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) + failwith "deprecated" + + let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 + end \ No newline at end of file From 33b8723cb16e9ff1ac0aa304027acecd84237df1 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 28 Nov 2024 21:44:04 +0100 Subject: [PATCH 062/240] Implement Vector foldleft and apply_with_c --- .../arrayImplementation/arrayVector.ml | 10 ++-------- .../sparseImplementation/sparseVector.ml | 13 +++++++------ src/cdomains/affineEquality/vector.ml | 4 ++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index dcd442f498..9a0bc3b8a8 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -115,16 +115,10 @@ module ArrayVector: AbstractVector = let map_preserve_zero f v = failwith "TODO" let map2_preserve_zero f v1 v2 = failwith "TODO" - let fold_left_preserve_zero f v = + let fold_left_preserve_zero f acc v = failwith "TODO" - let fold_left2_preserve_zero f v v' = - failwith "TODO" - - let fold_left_preserve_zero f v = - failwith "TODO" - - let fold_left2_preserve_zero f v v' = + let fold_left2_preserve_zero f acc v v' = failwith "TODO" let findi_val_opt f v = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 4f275f4514..814121349c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -119,14 +119,15 @@ module SparseVector: AbstractVector = if v1.len <> v2.len then raise (Invalid_argument "Different lengths") else to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len - let fold_left_preserve_zero f v = - failwith "TODO" + let fold_left_preserve_zero f acc v = + List.fold_left (fun acc (_, value) -> f acc value) acc v.entries - let fold_left2_preserve_zero f v v' = - failwith "TODO" + let fold_left2_preserve_zero f acc v v' = + List.fold_left2 (fun acc (_, value) (_, value') -> f acc value value') acc v.entries v'.entries - let apply_with_c f m v = - failwith "TODO" + let apply_with_c f c v = + let entries' = List.map (fun (idx, value) -> (idx, f value c)) v.entries in + {entries = entries'; len = v.len} let apply_with_c_with f m v = failwith "deprecated" diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index a97289b768..3fe0fa69e4 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -22,9 +22,9 @@ sig val map2_preserve_zero: (num -> num -> num) -> t -> t -> t - val fold_left_preserve_zero: ('acc -> num -> 'acc) -> t -> 'acc + val fold_left_preserve_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc - val fold_left2_preserve_zero: ('acc -> num -> num -> 'acc) -> t -> t -> 'acc + val fold_left2_preserve_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc val apply_with_c: (num -> num -> num) -> num -> t -> t From 785f75d85b0d759f2d226a77a2479c481ef9257b Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 29 Nov 2024 18:16:42 +0100 Subject: [PATCH 063/240] add column and helper functions --- .../arrayImplementation/arrayVector.ml | 2 + .../sparseImplementation/listMatrix.ml | 41 +++++-------------- .../sparseImplementation/sparseVector.ml | 15 ++++++- src/cdomains/affineEquality/vector.ml | 2 + .../apron/affineEqualityDomain.apron.ml | 1 + src/goblint_lib.ml | 2 +- 6 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 9a0bc3b8a8..2fefdd0043 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -36,6 +36,8 @@ module ArrayVector: AbstractVector = let remove_at_indices v idx = failwith "TODO" + let insert_zero_at_indices v idx = failwith "TODO" + let set_nth_with v n new_val = if n >= Array.length v then failwith "n outside of Array range" else Array.set v n new_val diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6b1c71d52c..a888834a73 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -38,38 +38,17 @@ module ListMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m - let add_empty_columns m cols = failwith "TODO" - (*let colsL = List.sort (fun a b -> a-b) (Array.to_list cols) in - let emptyT = A.zero in - let rec list_of_all_before_index idx cols = - match cols with - | x::xs -> - if x < idx - then - let (h,t) = list_of_all_before_index idx xs in - (x::h, t) - else ([],x::xs) - | [] -> ([],[]) + let add_empty_columns m cols = + let cols = Array.to_list cols in + let sorted_cols = List.sort Stdlib.compare cols in + let rec count_sorted_occ acc cols last count = + match cols with + | [] -> acc + | (x :: xs) when x = last -> count_sorted_occ acc xs x (count + 1) + | (x :: xs) -> count_sorted_occ ((last, count) :: acc) xs x 1 in - (*This could easily be abstracted into the above functions, but its nice to have - it here for readability and debugging*) - let rec make_empty_entries_for_idxs idxs = - match idxs with - | x::xs -> (x, emptyT)::(make_empty_entries_for_idxs xs) - | [] -> [] - in - let rec add_column_element r cols = - match r with - | (idx, _)::xs -> - let (bef,aft) = list_of_all_before_index idx cols in - (make_empty_entries_for_idxs bef)@(add_column_element xs aft) - | [] -> [] - in - let rec add_empty_columns_on_list m cols = - match m with - | x::xs -> (add_column_element x cols)::(add_empty_columns_on_list xs cols) - | [] -> [] - in tM (add_empty_columns_on_list m.entries colsL) (m.column_count + Array.length cols)*) + let occ_cols = count_sorted_occ [] sorted_cols (-1) 0 in + List.map (fun row -> V.insert_zero_at_indices row occ_cols) m let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 814121349c..d01ca2704b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -62,12 +62,25 @@ module SparseVector: AbstractVector = match vec, idx with | [], [] -> [] | [], (y :: ys) -> failwith "remove at indices: no more columns to delete" - | ((col_idx, value) :: xs), [] -> (col_idx - deleted_count, value) :: remove_indices_helper xs idx deleted_count + | ((col_idx, value) :: xs), [] -> (col_idx - deleted_count, value) :: remove_indices_helper xs [] deleted_count | ((col_idx, value) :: xs), (y :: ys) when y = col_idx -> remove_indices_helper xs ys (deleted_count + 1) + | ((col_idx, value) :: xs), (y :: ys) when y < col_idx -> remove_indices_helper vec ys (deleted_count + 1) | ((col_idx, value) :: xs), (y :: ys) -> (col_idx - deleted_count, value) :: remove_indices_helper xs idx deleted_count in {entries = remove_indices_helper v.entries idx 0; len = v.len - List.length idx} + let insert_zero_at_indices v idx = + let rec add_indices_helper vec idx added_count = + match vec, idx with + | [], [] -> [] + | [], (y :: ys) -> [] (* inserting at the end only means changing the dimension *) + | ((col_idx, value) :: xs), [] -> (col_idx + added_count, value) :: add_indices_helper xs [] added_count + | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) + | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> (col_idx + added_count + count, value) :: add_indices_helper xs ys (added_count + count) + | ((col_idx, value) :: xs), ((i, count) :: ys) -> (col_idx + added_count, value) :: add_indices_helper xs idx added_count + in + {entries = add_indices_helper v.entries idx 0; len = v.len + List.length idx} + let set_nth v n num = if n >= v.len then failwith "Out of bounds" else diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 3fe0fa69e4..e4c9fa90b4 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -12,6 +12,8 @@ sig val remove_at_indices: t -> int list -> t + val insert_zero_at_indices: t -> (int * int) list -> t + val set_nth: t -> int -> num -> t val set_nth_with: t -> int -> num -> unit diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 617549db53..7700444018 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -19,6 +19,7 @@ open AbstractMatrix open Batteries module Array = Batteries.Array +module Mpqf = SharedFunctions.Mpqf module Mpqf = SharedFunctions.Mpqf module AffineEqualityMatrix (Vec: AbstractVector) (Mx: AbstractMatrix) = diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index a5fe9230fe..0bf0be6bfb 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -438,7 +438,7 @@ module AbstractMatrix = AbstractMatrix module ArrayVector = ArrayVector module ArrayMatrix = ArrayMatrix module SparseVector = SparseVector -module SparseMatrix = SparseMatrix +module ListMatrix = ListMatrix module RatOps = RatOps module ConvenienceOps = ConvenienceOps From fe9513ad042b257df6f53896b25d46ee6bfb9d5a Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 30 Nov 2024 14:13:41 +0100 Subject: [PATCH 064/240] Fix del_cols duplicate edge case chech before comparing length --- .../sparseImplementation/listMatrix.ml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index a888834a73..2486e792d6 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -69,7 +69,8 @@ module ListMatrix: AbstractMatrix = Timing.wrap "get_col" (get_col m) n let set_col m new_col n = - List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m + (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) + List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) m1 @ m2 @@ -105,17 +106,18 @@ module ListMatrix: AbstractMatrix = List.map (fun row -> V.remove_nth row j) m let del_cols m cols = - if (Array.length cols) = num_cols m then empty() + let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) + if (List.length cols) = num_cols m then empty() else - let cols = Array.to_list cols in - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification), maybe use List instead?*) List.map (fun row -> V.remove_at_indices row sorted_cols) m let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols let map2i f m v = let vector_length = V.length v in - List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row) m + (* List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row) m *) + List.map2i (fun index row value -> if index < vector_length then f index row value else row) m (V.to_list v) let remove_zero_rows m = List.filter (fun row -> not (V.is_zero_vec row)) m From 7a8fab9752fcb5d0bcf4f6f366e191a89a9c3e6a Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 30 Nov 2024 14:13:56 +0100 Subject: [PATCH 065/240] Fix set_nth in Vector --- .../sparseImplementation/sparseVector.ml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index d01ca2704b..0ef6015abc 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -84,11 +84,20 @@ module SparseVector: AbstractVector = let set_nth v n num = if n >= v.len then failwith "Out of bounds" else - let new_entries = List.map (fun (col_idx, value) -> - if col_idx = n then (col_idx, num) else (col_idx, value) - ) v.entries - in - {entries= new_entries; len=v.len} + let rev_entries', _ = List.fold_lefti (fun (acc, found) i (idx, value) -> + if found then ((idx, value) :: acc, true) + else + if i = v.len - 1 then + if idx = n then (if num <>: A.zero then (n, num) :: acc, true else acc, true) + else if idx > n then (if num <>: A.zero then (idx, value) :: (n, num) :: acc, true else (idx, value) :: acc, true) + else failwith "Out of bounds (Should not be reachable)" + else + if idx < n then ((idx, value) :: acc, false) + else if idx = n then (if num <>: A.zero then (n, num) :: acc , true else acc, true) + else (if num <>: A.zero then (idx, value) :: (n, num) :: acc, true else (idx, value) :: acc, true) + + ) ([], false) v.entries in + {entries = List.rev rev_entries'; len = v.len} let set_nth_with = failwith "deprecated" From 519ee02ef6ba1ecf72e851013d21a1030d8b5c1d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sun, 1 Dec 2024 17:32:48 +0100 Subject: [PATCH 066/240] Remove double Mpqf definition --- src/cdomains/apron/affineEqualityDomain.apron.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 7700444018..94d144c485 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -20,7 +20,7 @@ open Batteries module Array = Batteries.Array module Mpqf = SharedFunctions.Mpqf -module Mpqf = SharedFunctions.Mpqf + module AffineEqualityMatrix (Vec: AbstractVector) (Mx: AbstractMatrix) = struct From d3d998d49f2f0f1a49e7d09d66d892b31622e6ff Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 3 Dec 2024 14:09:09 +0100 Subject: [PATCH 067/240] Renamed SparseMatrix to ListMatrix in goblint_lib.ml --- src/goblint_lib.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index a5fe9230fe..0bf0be6bfb 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -438,7 +438,7 @@ module AbstractMatrix = AbstractMatrix module ArrayVector = ArrayVector module ArrayMatrix = ArrayMatrix module SparseVector = SparseVector -module SparseMatrix = SparseMatrix +module ListMatrix = ListMatrix module RatOps = RatOps module ConvenienceOps = ConvenienceOps From d68c719aa30aca0cd7bf7e75401e930485377c6a Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 3 Dec 2024 14:33:33 +0100 Subject: [PATCH 068/240] Implement is_covered_by structure, but helper function still missing --- .../arrayImplementation/arrayVector.ml | 3 +++ .../sparseImplementation/listMatrix.ml | 21 +++++++++++++++++-- .../sparseImplementation/sparseVector.ml | 5 +++++ src/cdomains/affineEquality/vector.ml | 2 ++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 2fefdd0043..24ad36323f 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -126,4 +126,7 @@ module ArrayVector: AbstractVector = let findi_val_opt f v = failwith "TODO" + let exists2 f v1 v1 = + failwith "TODO / deprecated" + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 2486e792d6..ae63a82931 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -129,7 +129,8 @@ module ListMatrix: AbstractMatrix = failwith "TODO" let get_pivot_positions m = - failwith "TODO" + List.mapi (fun i row -> V.findi (fun z -> z =: A.one) row) m + let sub_rows (minu : V.t) (subt : V.t) : V.t = V.map2_preserve_zero (-:) minu subt @@ -197,9 +198,25 @@ module ListMatrix: AbstractMatrix = let rref_matrix m1 m2 = normalize @@ append_matrices m1 m2 - let is_covered_by m1 m2 = + + let delete_row_with_pivots row pivots m = failwith "TODO" + let is_covered_by m1 m2 = + if num_rows m1 > num_rows m2 then false else + let pivots = get_pivot_positions m2 in (* TODO: Lazy? *) + try + let _ = List.map2i (fun i row1 row2 -> + if not @@ V.exists2 (<>:) row1 row2 + then V.zero_vec (V.length row1) else + let row1 = delete_row_with_pivots row1 pivots m2 in + if V.nth row1 (V.length row1 - 1) <>: A.zero + then raise Stdlib.Exit + else V.zero_vec (V.length row1) + ) m1 m2 in + true + with Stdlib.Exit -> false + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 0ef6015abc..d9d773939e 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -198,6 +198,7 @@ module SparseVector: AbstractVector = else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) + (* Returns optional of (index * value) where f evaluated to true *) let findi_val_opt f v = if f A.zero then ( @@ -233,6 +234,9 @@ module SparseVector: AbstractVector = | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs in (exists_aux c f v.entries) + let exists2 f v1 v2 = + failwith "TODO" + let rev v = let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - idx, value)) v.entries in {entries = entries'; len = v.len} @@ -254,6 +258,7 @@ module SparseVector: AbstractVector = let find2i f v v' = failwith "TODO" + let to_array v = let vec = Array.make v.len A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index e4c9fa90b4..623c338dcd 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -69,6 +69,8 @@ sig val exists: (num -> bool) -> t -> bool + val exists2: (num -> num -> bool) -> t -> t -> bool + val rev: t -> t val rev_with: t -> unit From 159d07ee7c7c1154cf1857525969db58d8c29285 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 3 Dec 2024 14:45:11 +0100 Subject: [PATCH 069/240] bugfix in insert_at and reduce_col_with_vec --- .../sparseImplementation/listMatrix.ml | 17 ++++++++++------- .../sparseImplementation/sparseVector.ml | 5 ++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index ae63a82931..96a1caf63f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -100,6 +100,16 @@ module ListMatrix: AbstractMatrix = V.map2_preserve_zero (fun x y -> x -: s *: y) row pivot_row) ) m + let reduce_col_with_vec m j v = + let pivot_element = V.nth v j in + if pivot_element = A.zero then m + else List.mapi (fun idx row -> + let row_value = V.nth row j in + if row_value = A.zero then row + else (let s = row_value /: pivot_element in + V.map2_preserve_zero (fun x y -> x -: s *: y) row v) + ) m + let del_col m j = if num_cols m = 1 then empty () else @@ -125,13 +135,9 @@ module ListMatrix: AbstractMatrix = let init_with_vec v = [v] - let reduce_col_with_vec m j v = - failwith "TODO" - let get_pivot_positions m = List.mapi (fun i row -> V.findi (fun z -> z =: A.one) row) m - let sub_rows (minu : V.t) (subt : V.t) : V.t = V.map2_preserve_zero (-:) minu subt @@ -226,9 +232,6 @@ module ListMatrix: AbstractMatrix = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m - let rref_vec_helper m pivot_positions v = - failwith "TODO" - (* ------------------------- Deprecated ------------------------*) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index d9d773939e..794ec54fe5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -106,10 +106,9 @@ module SparseVector: AbstractVector = if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) let entries' = List.fold_left (fun acc (idx, value) -> if idx < n then (idx, value) :: acc - else if idx = n then (n, new_val) :: (idx + 1, value) :: acc - else (idx + 1, value) :: acc + else (idx + 1, value) :: acc ) [] (List.rev v.entries) in - {entries = entries'; len = v.len + 1} + {entries = List.sort (fun (i, _) (j, _) -> Int.compare i j) entries'; len = v.len + 1} let map_preserve_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( From 1f85d28138d96e281277b84305586fac5e2d7f0a Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 3 Dec 2024 15:13:48 +0100 Subject: [PATCH 070/240] Implement more vector functions --- .../sparseImplementation/listMatrix.ml | 71 +++++++++---------- .../sparseImplementation/sparseVector.ml | 64 +++++++++-------- 2 files changed, 69 insertions(+), 66 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 96a1caf63f..023721a0ec 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -149,46 +149,45 @@ module ListMatrix: AbstractMatrix = let is_valid_affeq_matrix m = failwith "TODO" - (* + (* let col_count = num_cols m in List.exists (fun row -> (* Invalid if row is zero, but coefficient is not zero *) V.fold_left_preserve_zero (fun found_non_zero (col_idx, value) -> if col_idx = col_count - 1 && (not found_non_zero) && (value <>: A.zero) then false else found_non_zero) false row - ) m *) - - let normalize m = - let col_count = num_cols m in - let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = - m - in - (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) - let find_first_pivot m row_idx col_idx = - if col_idx >= col_count then None else - (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) - let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> - let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in - match row_first_non_zero with - | None -> (cur_row, cur_col, cur_val) - | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) - ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) - in - if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) - in - let rec main_loop m m' row_idx col_idx = - if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) - else - match find_first_pivot m' row_idx col_idx with - | None -> m (* No pivot found means already normalized*) - | Some (piv_row_idx, piv_col_idx, piv_val) -> ( - let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in - let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in - let piv_row = (List.nth normalized_m row_idx) in - let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in - let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in - main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) - in - let m' = main_loop m m 0 0 in - if is_valid_affeq_matrix m' then Some m' else None + + let normalize m = + let col_count = num_cols m in + let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = + m + in + (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) + let find_first_pivot m row_idx col_idx = + if col_idx >= col_count then None else + (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) + let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> + let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in + match row_first_non_zero with + | None -> (cur_row, cur_col, cur_val) + | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) + in + if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) + in + let rec main_loop m m' row_idx col_idx = + if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) + else + match find_first_pivot m' row_idx col_idx with + | None -> m (* No pivot found means already normalized*) + | Some (piv_row_idx, piv_col_idx, piv_val) -> ( + let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in + let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in + let piv_row = (List.nth normalized_m row_idx) in + let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in + let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in + main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) + in + let m' = main_loop m m 0 0 in + if is_valid_affeq_matrix m' then Some m' else None (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 794ec54fe5..6c1e7cab1d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -4,6 +4,7 @@ open ConvenienceOps open BatList open BatArray + module List = BatList module Array = BatArray @@ -99,9 +100,6 @@ module SparseVector: AbstractVector = ) ([], false) v.entries in {entries = List.rev rev_entries'; len = v.len} - let set_nth_with = - failwith "deprecated" - let insert_val_at n new_val v = if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) let entries' = List.fold_left (fun acc (idx, value) -> @@ -150,9 +148,6 @@ module SparseVector: AbstractVector = let entries' = List.map (fun (idx, value) -> (idx, f value c)) v.entries in {entries = entries'; len = v.len} - let apply_with_c_with f m v = - failwith "deprecated" - let zero_vec n = {entries = []; len = n} @@ -188,8 +183,6 @@ module SparseVector: AbstractVector = if v.len <> v'.len then failwith "Unequal vector length" else of_list (List.map2 f (to_list v) (to_list v')) - let map2_with f v v' = - failwith "deprecated" let findi f v = if f A.zero then @@ -212,14 +205,11 @@ module SparseVector: AbstractVector = let map f v = of_list (List.map f (to_list v)) - let map_with f v = - failwith "deprecated" - let compare_length_with v n = Int.compare v.len n - let filteri f v = - failwith "TODO" + let filteri f v = (* TODO: optimize! *) + of_list (List.filteri f (to_list v)) let append v v' = let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in @@ -233,29 +223,20 @@ module SparseVector: AbstractVector = | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs in (exists_aux c f v.entries) - let exists2 f v1 v2 = - failwith "TODO" + let exists2 f v1 v2 = (* TODO: optimize! *) + List.exists2 f (to_list v1) (to_list v2) let rev v = let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - idx, value)) v.entries in {entries = entries'; len = v.len} - let rev_with v = - failwith "deprecated" - - let map2i f v v' = + let map2i f v v' = (* TODO: optimize! *) of_list (List.map2i f (to_list v) (to_list v')) - let map2i_with f v v' = - failwith "deprecated" - - let mapi f v = + let mapi f v = (* TODO: optimize! *) of_list (List.mapi f (to_list v)) - let mapi_with f v = - failwith "deprecated" - - let find2i f v v' = + let find2i f v v' = (* TODO: optimize! *) failwith "TODO" let to_array v = @@ -276,8 +257,8 @@ module SparseVector: AbstractVector = let to_sparse_list v = v.entries - let find_opt f v = - failwith "TODO: Do we need this?" + let find_opt f v = (* TODO: Do we need this? And optimize!!!*) + List.find_opt f (to_list v) let show v = let t = to_list v in @@ -288,4 +269,27 @@ module SparseVector: AbstractVector = in "["^list_str t^"\n" - end \ No newline at end of file + (* ------------------- Deprecated ------------------- *) + let mapi_with f v = + failwith "deprecated" + + let map2i_with f v v' = + failwith "deprecated" + + + let rev_with v = + failwith "deprecated" + + let map_with f v = + failwith "deprecated" + + + let map2_with f v v' = + failwith "deprecated" + + let apply_with_c_with f m v = + failwith "deprecated" + + let set_nth_with = + failwith "deprecated" + end From 793df4a2468a7c2bd79ee9d1a62c611c11365f2d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 3 Dec 2024 15:14:20 +0100 Subject: [PATCH 071/240] Formatting --- .../sparseImplementation/listMatrix.ml | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 023721a0ec..f6b71ee1ad 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -154,40 +154,40 @@ module ListMatrix: AbstractMatrix = List.exists (fun row -> (* Invalid if row is zero, but coefficient is not zero *) V.fold_left_preserve_zero (fun found_non_zero (col_idx, value) -> if col_idx = col_count - 1 && (not found_non_zero) && (value <>: A.zero) then false else found_non_zero) false row *) - - let normalize m = - let col_count = num_cols m in - let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = - m - in - (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) - let find_first_pivot m row_idx col_idx = - if col_idx >= col_count then None else - (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) - let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> - let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in - match row_first_non_zero with - | None -> (cur_row, cur_col, cur_val) - | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) - ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) - in - if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) - in - let rec main_loop m m' row_idx col_idx = - if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) - else - match find_first_pivot m' row_idx col_idx with - | None -> m (* No pivot found means already normalized*) - | Some (piv_row_idx, piv_col_idx, piv_val) -> ( - let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in - let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in - let piv_row = (List.nth normalized_m row_idx) in - let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in - let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in - main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) - in - let m' = main_loop m m 0 0 in - if is_valid_affeq_matrix m' then Some m' else None + + let normalize m = + let col_count = num_cols m in + let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = + m + in + (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) + let find_first_pivot m row_idx col_idx = + if col_idx >= col_count then None else + (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) + let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> + let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in + match row_first_non_zero with + | None -> (cur_row, cur_col, cur_val) + | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) + in + if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) + in + let rec main_loop m m' row_idx col_idx = + if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) + else + match find_first_pivot m' row_idx col_idx with + | None -> m (* No pivot found means already normalized*) + | Some (piv_row_idx, piv_col_idx, piv_val) -> ( + let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in + let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in + let piv_row = (List.nth normalized_m row_idx) in + let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in + let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in + main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) + in + let m' = main_loop m m 0 0 in + if is_valid_affeq_matrix m' then Some m' else None (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) From 6021c422fae29b8dbf2319e98fc9c1efa4cdd800 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 3 Dec 2024 18:51:30 +0100 Subject: [PATCH 072/240] Implement is_covered_by --- .../sparseImplementation/listMatrix.ml | 43 +++++++++++++------ .../sparseImplementation/sparseVector.ml | 2 +- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index f6b71ee1ad..d1627ac564 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -207,20 +207,39 @@ module ListMatrix: AbstractMatrix = let delete_row_with_pivots row pivots m = failwith "TODO" + (* Assumes that the first row of the matrix is already the pivot row fitting to the vector. *) + let rec is_linearly_independent_rref v m = + match m with + | [] -> not @@ V.is_zero_vec v + | x::xs -> + let pivot_opt = V.findi_val_opt ((<>:) A.zero) v in + match pivot_opt with + | None -> true (* When we found no pivot, the vector is already A.zero. *) + | Some (pivot_id, pivot) -> + let new_v = V.map2_preserve_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in + is_linearly_independent_rref new_v xs + let is_covered_by m1 m2 = if num_rows m1 > num_rows m2 then false else - let pivots = get_pivot_positions m2 in (* TODO: Lazy? *) - try - let _ = List.map2i (fun i row1 row2 -> - if not @@ V.exists2 (<>:) row1 row2 - then V.zero_vec (V.length row1) else - let row1 = delete_row_with_pivots row1 pivots m2 in - if V.nth row1 (V.length row1 - 1) <>: A.zero - then raise Stdlib.Exit - else V.zero_vec (V.length row1) - ) m1 m2 in - true - with Stdlib.Exit -> false + let rec is_covered_by_helper m1 m2 = + match m1 with + | [] -> true + | v1::vs1 -> + let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in + match first_non_zero with + | None -> true (* vs1 must also be zero-vectors because of rref *) + | Some (idx, _) -> + let m' = List.drop_while (fun v2 -> + match V.findi_val_opt ((<>:) A.zero) v2 with + | None -> true (* In this case, m2 only has zero rows after that *) + | Some (idx', _) -> idx' < idx + ) m2 in (* Only consider the part of m2 where the pivot is at a position useful for deleting first_non_zero of v1*) + let linearly_indep = is_linearly_independent_rref v1 m' in + if linearly_indep then false else is_covered_by_helper vs1 m' + in is_covered_by_helper m1 m2 + + + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6c1e7cab1d..78a94fd886 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -214,7 +214,7 @@ module SparseVector: AbstractVector = let append v v' = let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in {entries = entries'; len = v.len + v'.len} - + let exists f v = let c = v.len in let rec exists_aux at f v = From 97a735bb0e79f93233260c5ee6b3378d6dbda516 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Wed, 4 Dec 2024 17:22:03 +0100 Subject: [PATCH 073/240] small bugfixes --- .../sparseImplementation/listMatrix.ml | 4 +-- .../sparseImplementation/sparseVector.ml | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index d1627ac564..6cb170034e 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -19,7 +19,7 @@ module ListMatrix: AbstractMatrix = [@@deriving eq, ord, hash] let show x = - List.fold_left (^) "" (List.map (fun x -> (V.show x) ^ "\n") x) + List.fold_left (^) "" (List.map (fun x -> (V.show x)) x) let empty () = [] @@ -204,7 +204,7 @@ module ListMatrix: AbstractMatrix = normalize @@ append_matrices m1 m2 - let delete_row_with_pivots row pivots m = + let delete_row_with_pivots row pivots m2 = failwith "TODO" (* Assumes that the first row of the matrix is already the pivot row fitting to the vector. *) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 78a94fd886..2c44f7c9fe 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -172,10 +172,11 @@ module SparseVector: AbstractVector = let to_list v = let[@tail_mod_cons] rec extend_zero_aux i v' = - if i >= v.len then failwith "out of Bounds for to_list" else (*can probably be removed*) - match v' with - | (xi,xv)::xs -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero::(extend_zero_aux (i+1) v') - | [] -> [] + if i >= v.len then [] else (*can probably be removed*) + match v', i with + | (xi,xv)::xs, _ -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero ::(extend_zero_aux (i+1) v') + | [], j when i < v.len -> A.zero :: (extend_zero_aux (i+1) v') + | [], _ -> [] in (extend_zero_aux 0 v.entries) @@ -265,31 +266,31 @@ module SparseVector: AbstractVector = let rec list_str l = match l with | [] -> "]" - | x :: xs -> (A.to_string x) ^" "^(list_str xs) + | x :: xs -> " " ^ (A.to_string x) ^ (list_str xs) in "["^list_str t^"\n" (* ------------------- Deprecated ------------------- *) let mapi_with f v = - failwith "deprecated" + failwith "mapi_with deprecated" let map2i_with f v v' = - failwith "deprecated" + failwith "map2i_with deprecated" let rev_with v = - failwith "deprecated" + failwith "rev_with deprecated" let map_with f v = - failwith "deprecated" + failwith "map_with deprecated" let map2_with f v v' = - failwith "deprecated" + failwith "map2_with deprecated" let apply_with_c_with f m v = - failwith "deprecated" + failwith "apply_with_c_with deprecated" - let set_nth_with = - failwith "deprecated" + let set_nth_with f n num = ( + failwith "set_nth_with deprecated") end From b17f33eed7a7fd54750d119bc897e7387bfa2ed9 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Wed, 4 Dec 2024 18:40:54 +0100 Subject: [PATCH 074/240] Finish normalize first version with dec2D --- .../arrayImplementation/arrayVector.ml | 3 +++ .../sparseImplementation/listMatrix.ml | 15 ++++++++------- .../sparseImplementation/sparseVector.ml | 7 ++++++- src/cdomains/affineEquality/vector.ml | 3 +++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 24ad36323f..937c4ee36f 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -129,4 +129,7 @@ module ArrayVector: AbstractVector = let exists2 f v1 v1 = failwith "TODO / deprecated" + let starting_from_nth n v = + failwith "TODO / deprecated" + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6cb170034e..e04fe6a174 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -148,17 +148,18 @@ module ListMatrix: AbstractMatrix = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m let is_valid_affeq_matrix m = - failwith "TODO" - (* let col_count = num_cols m in - List.exists (fun row -> (* Invalid if row is zero, but coefficient is not zero *) - V.fold_left_preserve_zero (fun found_non_zero (col_idx, value) -> if col_idx = col_count - 1 && (not found_non_zero) && (value <>: A.zero) then false else found_non_zero) false row - *) + let row_is_invalid row = (* TODO: Vector findi_opt *) + match V.findi_val_opt ((<>:) A.zero) row with + | Some (idx, _) -> if idx = col_count - 1 then true else false (* If all cofactors of the affeq are zero, but the constant is non-zero, the row is invalid *) + | None -> false (* Full zero row is not invalid *) + in + List.exists row_is_invalid m let normalize m = let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = - m + List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) let find_first_pivot m row_idx col_idx = @@ -187,7 +188,7 @@ module ListMatrix: AbstractMatrix = main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in - if is_valid_affeq_matrix m' then Some m' else None + if is_valid_affeq_matrix m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 2c44f7c9fe..cad838a474 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -215,7 +215,7 @@ module SparseVector: AbstractVector = let append v v' = let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in {entries = entries'; len = v.len + v'.len} - + let exists f v = let c = v.len in let rec exists_aux at f v = @@ -261,6 +261,10 @@ module SparseVector: AbstractVector = let find_opt f v = (* TODO: Do we need this? And optimize!!!*) List.find_opt f (to_list v) + let starting_from_nth n v = + let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in + {entries = entries'; len = v.len - n} + let show v = let t = to_list v in let rec list_str l = @@ -293,4 +297,5 @@ module SparseVector: AbstractVector = let set_nth_with f n num = ( failwith "set_nth_with deprecated") + end diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 623c338dcd..7b067018e4 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -99,4 +99,7 @@ sig val to_sparse_list: t -> (int * num) list + (* Returns the part of the vector starting from index n*) + val starting_from_nth : int -> t -> t + end \ No newline at end of file From 80672a1f42f1f2b78b351aea9c245d78fbe6d680 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 5 Dec 2024 09:52:52 +0100 Subject: [PATCH 075/240] bugfix in find_val_opt and lin_independent --- .../sparseImplementation/listMatrix.ml | 7 ++----- .../sparseImplementation/sparseVector.ml | 17 ++++++++--------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index e04fe6a174..f1183dcd95 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -215,7 +215,7 @@ module ListMatrix: AbstractMatrix = | x::xs -> let pivot_opt = V.findi_val_opt ((<>:) A.zero) v in match pivot_opt with - | None -> true (* When we found no pivot, the vector is already A.zero. *) + | None -> false (* When we found no pivot, the vector is already A.zero. *) | Some (pivot_id, pivot) -> let new_v = V.map2_preserve_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in is_linearly_independent_rref new_v xs @@ -238,10 +238,7 @@ module ListMatrix: AbstractMatrix = let linearly_indep = is_linearly_independent_rref v1 m' in if linearly_indep then false else is_covered_by_helper vs1 m' in is_covered_by_helper m1 m2 - - - - + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index cad838a474..7ac1d4c434 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -193,15 +193,14 @@ module SparseVector: AbstractVector = (* Returns optional of (index * value) where f evaluated to true *) let findi_val_opt f v = - if f A.zero then - ( - let i, (col_idx, value) = List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries in - if i < col_idx then (* In this case, Zero was the first element found because iteration index i is smaller than "found" value *) - Some (i, A.zero) - else Some (col_idx, value) - ) - else - Some (List.find (fun (idx, value) -> f value) v.entries) + let rec find_zero_or_val vec last_col_idx = + match vec, last_col_idx with + | [], _ -> if v.len <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) else None + | (idx, value) :: xs, i -> + if idx <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) + else if f value then Some (idx, value) + else find_zero_or_val xs idx + in find_zero_or_val v.entries (-1) let map f v = of_list (List.map f (to_list v)) From 418de56be635e161de3d0d826f47d927f1876a53 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 5 Dec 2024 15:37:17 +0100 Subject: [PATCH 076/240] Fixed affeq_rows_are_valid helper for normalize --- .../sparseImplementation/listMatrix.ml | 21 +++++++++---------- .../sparseImplementation/sparseVector.ml | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index f1183dcd95..2e0eda574f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -147,15 +147,6 @@ module ListMatrix: AbstractMatrix = let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m - let is_valid_affeq_matrix m = - let col_count = num_cols m in - let row_is_invalid row = (* TODO: Vector findi_opt *) - match V.findi_val_opt ((<>:) A.zero) row with - | Some (idx, _) -> if idx = col_count - 1 then true else false (* If all cofactors of the affeq are zero, but the constant is non-zero, the row is invalid *) - | None -> false (* Full zero row is not invalid *) - in - List.exists row_is_invalid m - let normalize m = let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = @@ -174,6 +165,14 @@ module ListMatrix: AbstractMatrix = in if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) in + let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) + let col_count = num_cols m in + let row_is_valid row = (* TODO: Vector findi_opt *) + match V.findi_val_opt ((<>:) A.zero) row with + | Some (idx, _) -> if idx < col_count - 1 then true else false (* If all cofactors of the affeq are zero, but the constant is non-zero, the row is invalid *) + | None -> true (* Full zero row is valid *) + in + List.for_all row_is_valid m in let rec main_loop m m' row_idx col_idx = if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else @@ -188,7 +187,7 @@ module ListMatrix: AbstractMatrix = main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in - if is_valid_affeq_matrix m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) + if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) @@ -238,7 +237,7 @@ module ListMatrix: AbstractMatrix = let linearly_indep = is_linearly_independent_rref v1 m' in if linearly_indep then false else is_covered_by_helper vs1 m' in is_covered_by_helper m1 m2 - + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 7ac1d4c434..3f80cc7d46 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -191,7 +191,7 @@ module SparseVector: AbstractVector = else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) - (* Returns optional of (index * value) where f evaluated to true *) + (* Returns optional of (index * value) where f value evaluated to true *) let findi_val_opt f v = let rec find_zero_or_val vec last_col_idx = match vec, last_col_idx with From e10493adaf387d28378dd4a1a8fee64e44d92ec5 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 5 Dec 2024 16:27:43 +0100 Subject: [PATCH 077/240] better map2pz,better naming --- .../sparseImplementation/sparseVector.ml | 45 +++++++++---------- src/cdomains/affineEquality/vector.ml | 8 ++-- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 3f80cc7d46..47d63ca87d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -108,40 +108,37 @@ module SparseVector: AbstractVector = ) [] (List.rev v.entries) in {entries = List.sort (fun (i, _) (j, _) -> Int.compare i j) entries'; len = v.len + 1} - let map_preserve_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) + let map_f_preserve_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( fun (idx, value) -> let new_val = f value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) - let map2_preserve_zero f v1 v2 = - let rec map2_nonzero_aux v1 v2 = + let map2_f_preserve_zero f v1 v2 = + let f_rem_zero acc idx e1 e2 = + let r = f e1 e2 in + if r =: A.zero then acc else (idx, r)::acc + in + let rec aux acc v1 v2 = match v1, v2 with - | [], [] -> [] - | x , y -> - let cons, xtail, ytail = - match x, y with - | (xidx, xv)::xs, (yidx,yv)::ys -> ( - match xidx - yidx with - | d when d < 0 -> (xidx, f xv A.zero), xs, v2 - | d when d > 0 -> (yidx, f A.zero yv), v1, ys - | _ -> (xidx, f xv yv) , xs, ys - ) - | (xidx, xv)::xs, [] -> (xidx, f xv A.zero), xs, [] - | [], (yidx, yv)::ys -> (yidx, f A.zero yv), [], ys - | [],[] -> raise (Failure "Should never be reached") - in - let res = if snd cons = A.zero then [] else [cons] in - res@(map2_nonzero_aux xtail ytail) - in - if v1.len <> v2.len then raise (Invalid_argument "Different lengths") else - to_vector (map2_nonzero_aux v1.entries v2.entries) v1.len + | [], [] -> acc + | [], (yidx, yval)::ys -> aux (f_rem_zero acc yidx A.zero yval) [] ys + | (xidx, xval)::xs, [] -> aux (f_rem_zero acc xidx xval A.zero) xs [] + | (xidx, xval)::xs, (yidx, yval)::ys -> + match xidx - yidx with + | d when d < 0 -> aux (f_rem_zero acc xidx xval A.zero) xs v2 + | d when d > 0 -> aux (f_rem_zero acc yidx A.zero yval) v1 ys + | _ -> aux (f_rem_zero acc xidx xval yval) xs ys + in + if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else + to_vector (List.rev (aux [] v1.entries v2.entries)) v1.len + - let fold_left_preserve_zero f acc v = + let fold_left_f_preserve_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries - let fold_left2_preserve_zero f acc v v' = + let fold_left2_f_preserve_zero f acc v v' = List.fold_left2 (fun acc (_, value) (_, value') -> f acc value value') acc v.entries v'.entries let apply_with_c f c v = diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 7b067018e4..d9c2d7d299 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -20,13 +20,13 @@ sig val insert_val_at: int -> num -> t -> t - val map_preserve_zero: (num -> num) -> t -> t + val map_f_preserve_zero: (num -> num) -> t -> t - val map2_preserve_zero: (num -> num -> num) -> t -> t -> t + val map2_f_preserve_zero: (num -> num -> num) -> t -> t -> t - val fold_left_preserve_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc + val fold_left_f_preserve_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc - val fold_left2_preserve_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc + val fold_left2_f_preserve_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc val apply_with_c: (num -> num -> num) -> num -> t -> t From d2b0be74812ae47b908a988f6b3b6d99c2c53580 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 5 Dec 2024 16:37:03 +0100 Subject: [PATCH 078/240] small hickup --- .../affineEquality/sparseImplementation/listMatrix.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 2e0eda574f..b580aad2af 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -97,7 +97,7 @@ module ListMatrix: AbstractMatrix = let row_value = V.nth row j in if row_value = A.zero then row else (let s = row_value /: pivot in - V.map2_preserve_zero (fun x y -> x -: s *: y) row pivot_row) + V.map2_f_preserve_zero (fun x y -> x -: s *: y) row pivot_row) ) m let reduce_col_with_vec m j v = @@ -107,7 +107,7 @@ module ListMatrix: AbstractMatrix = let row_value = V.nth row j in if row_value = A.zero then row else (let s = row_value /: pivot_element in - V.map2_preserve_zero (fun x y -> x -: s *: y) row v) + V.map2_f_preserve_zero (fun x y -> x -: s *: y) row v) ) m let del_col m j = @@ -139,10 +139,10 @@ module ListMatrix: AbstractMatrix = List.mapi (fun i row -> V.findi (fun z -> z =: A.one) row) m let sub_rows (minu : V.t) (subt : V.t) : V.t = - V.map2_preserve_zero (-:) minu subt + V.map2_f_preserve_zero (-:) minu subt let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_preserve_zero (fun a -> a /: pivot) row + V.map_f_preserve_zero (fun a -> a /: pivot) row let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m @@ -216,7 +216,7 @@ module ListMatrix: AbstractMatrix = match pivot_opt with | None -> false (* When we found no pivot, the vector is already A.zero. *) | Some (pivot_id, pivot) -> - let new_v = V.map2_preserve_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in + let new_v = V.map2_f_preserve_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in is_linearly_independent_rref new_v xs let is_covered_by m1 m2 = From 859ec26b7fbc661e0586ea96205e467abd02f852 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 5 Dec 2024 16:50:53 +0100 Subject: [PATCH 079/240] normalize bug fix --- .../sparseImplementation/listMatrix.ml | 28 +++++++++++++++---- .../sparseImplementation/sparseVector.ml | 14 +++++----- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index b580aad2af..6fabd9295d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -77,6 +77,18 @@ module ListMatrix: AbstractMatrix = let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 + let sub_rows (minu : V.t) (subt : V.t) : V.t = + V.map2_f_preserve_zero (-:) minu subt + + let div_row (row : V.t) (pivot : A.t) : V.t = + V.map_f_preserve_zero (fun a -> a /: pivot) row + + let swap_rows m j k = + List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m + + let sub_scaled_row row1 row2 s = + V.map2_f_preserve_zero (fun x y -> x -: s *: y) row1 row2 + let reduce_col m j = if is_empty m then m else @@ -97,7 +109,7 @@ module ListMatrix: AbstractMatrix = let row_value = V.nth row j in if row_value = A.zero then row else (let s = row_value /: pivot in - V.map2_f_preserve_zero (fun x y -> x -: s *: y) row pivot_row) + sub_scaled_row row pivot_row s) ) m let reduce_col_with_vec m j v = @@ -153,17 +165,18 @@ module ListMatrix: AbstractMatrix = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) - let find_first_pivot m row_idx col_idx = + let find_first_pivot m' row_idx col_idx = if col_idx >= col_count then None else (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) - | Some (col_idx, value) -> if col_idx < cur_col then (row_idx + i, col_idx, value) else (cur_row, cur_col, cur_val) - ) (num_rows m, num_cols m, A.zero) m (* Initializing with max, so num_cols m indicates that pivot is not found *) + | Some (idx, value) -> let () = Printf.printf "We found first non-zero at index %i in row %i\n" idx i in + if idx < cur_col then (row_idx + i, idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m', num_cols m', A.zero) m' (* Initializing with max, so num_cols m indicates that pivot is not found *) in - if piv_col = (num_cols m) then None else Some (piv_row, piv_col, piv_val) + if piv_col = (num_cols m') then None else Some (piv_row, piv_col + col_idx, piv_val) in let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) let col_count = num_cols m in @@ -179,10 +192,13 @@ module ListMatrix: AbstractMatrix = match find_first_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized*) | Some (piv_row_idx, piv_col_idx, piv_val) -> ( + let () = Printf.printf "The current matrix is: \n%s and the pivot is (%i, %i, %s)\n" (show m) piv_row_idx piv_col_idx (A.to_string piv_val) in let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in let piv_row = (List.nth normalized_m row_idx) in - let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then sub_rows row piv_row else row) normalized_m in + let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then + let scale = V.nth row piv_col_idx in + sub_scaled_row row piv_row scale else row) normalized_m in let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 47d63ca87d..6f51f01d3c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -132,7 +132,7 @@ module SparseVector: AbstractVector = | _ -> aux (f_rem_zero acc xidx xval yval) xs ys in if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else - to_vector (List.rev (aux [] v1.entries v2.entries)) v1.len + to_vector (List.rev (aux [] v1.entries v2.entries)) v1.len let fold_left_f_preserve_zero f acc v = @@ -191,12 +191,12 @@ module SparseVector: AbstractVector = (* Returns optional of (index * value) where f value evaluated to true *) let findi_val_opt f v = let rec find_zero_or_val vec last_col_idx = - match vec, last_col_idx with - | [], _ -> if v.len <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) else None - | (idx, value) :: xs, i -> - if idx <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) - else if f value then Some (idx, value) - else find_zero_or_val xs idx + match vec, last_col_idx with + | [], _ -> if v.len <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) else None + | (idx, value) :: xs, i -> + if idx <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) + else if f value then Some (idx, value) + else find_zero_or_val xs idx in find_zero_or_val v.entries (-1) let map f v = From 67c1d5c48477dfbc9cf8635682b4c42d2bedf00f Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 5 Dec 2024 16:56:34 +0100 Subject: [PATCH 080/240] small naming --- .../arrayImplementation/arrayVector.ml | 8 ++++---- .../sparseImplementation/listMatrix.ml | 14 +++++++------- .../sparseImplementation/sparseVector.ml | 8 ++++---- src/cdomains/affineEquality/vector.ml | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 937c4ee36f..3bf873df78 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -114,13 +114,13 @@ module ArrayVector: AbstractVector = let find_opt f v = failwith "TODO" - let map_preserve_zero f v = failwith "TODO" - let map2_preserve_zero f v1 v2 = failwith "TODO" + let map_f_preserves_zero f v = failwith "TODO" + let map2_f_preserves_zero f v1 v2 = failwith "TODO" - let fold_left_preserve_zero f acc v = + let fold_left_f_preserves_zero f acc v = failwith "TODO" - let fold_left2_preserve_zero f acc v v' = + let fold_left2_f_preserves_zero f acc v v' = failwith "TODO" let findi_val_opt f v = diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6fabd9295d..3d00d37fbf 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -78,16 +78,16 @@ module ListMatrix: AbstractMatrix = let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 let sub_rows (minu : V.t) (subt : V.t) : V.t = - V.map2_f_preserve_zero (-:) minu subt + V.map2_f_preserves_zero (-:) minu subt let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_f_preserve_zero (fun a -> a /: pivot) row + V.map_f_preserves_zero (fun a -> a /: pivot) row let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m let sub_scaled_row row1 row2 s = - V.map2_f_preserve_zero (fun x y -> x -: s *: y) row1 row2 + V.map2_f_preserves_zero (fun x y -> x -: s *: y) row1 row2 let reduce_col m j = if is_empty m then m @@ -119,7 +119,7 @@ module ListMatrix: AbstractMatrix = let row_value = V.nth row j in if row_value = A.zero then row else (let s = row_value /: pivot_element in - V.map2_f_preserve_zero (fun x y -> x -: s *: y) row v) + V.map2_f_preserves_zero (fun x y -> x -: s *: y) row v) ) m let del_col m j = @@ -151,10 +151,10 @@ module ListMatrix: AbstractMatrix = List.mapi (fun i row -> V.findi (fun z -> z =: A.one) row) m let sub_rows (minu : V.t) (subt : V.t) : V.t = - V.map2_f_preserve_zero (-:) minu subt + V.map2_f_preserves_zero (-:) minu subt let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_f_preserve_zero (fun a -> a /: pivot) row + V.map_f_preserves_zero (fun a -> a /: pivot) row let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m @@ -232,7 +232,7 @@ module ListMatrix: AbstractMatrix = match pivot_opt with | None -> false (* When we found no pivot, the vector is already A.zero. *) | Some (pivot_id, pivot) -> - let new_v = V.map2_f_preserve_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in + let new_v = V.map2_f_preserves_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in is_linearly_independent_rref new_v xs let is_covered_by m1 m2 = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6f51f01d3c..3591782507 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -108,14 +108,14 @@ module SparseVector: AbstractVector = ) [] (List.rev v.entries) in {entries = List.sort (fun (i, _) (j, _) -> Int.compare i j) entries'; len = v.len + 1} - let map_f_preserve_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) + let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( fun (idx, value) -> let new_val = f value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) - let map2_f_preserve_zero f v1 v2 = + let map2_f_preserves_zero f v1 v2 = let f_rem_zero acc idx e1 e2 = let r = f e1 e2 in if r =: A.zero then acc else (idx, r)::acc @@ -135,10 +135,10 @@ module SparseVector: AbstractVector = to_vector (List.rev (aux [] v1.entries v2.entries)) v1.len - let fold_left_f_preserve_zero f acc v = + let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries - let fold_left2_f_preserve_zero f acc v v' = + let fold_left2_f_preserves_zero f acc v v' = List.fold_left2 (fun acc (_, value) (_, value') -> f acc value value') acc v.entries v'.entries let apply_with_c f c v = diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index d9c2d7d299..15215b5512 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -20,13 +20,13 @@ sig val insert_val_at: int -> num -> t -> t - val map_f_preserve_zero: (num -> num) -> t -> t + val map_f_preserves_zero: (num -> num) -> t -> t - val map2_f_preserve_zero: (num -> num -> num) -> t -> t -> t + val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t - val fold_left_f_preserve_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc + val fold_left_f_preserves_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc - val fold_left2_f_preserve_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc + val fold_left2_f_preserves_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc val apply_with_c: (num -> num -> num) -> num -> t -> t From 71768bee4808fe569a2f8a99d254f2521f52132f Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 5 Dec 2024 17:04:18 +0100 Subject: [PATCH 081/240] fold_left2_f_preserves_zero --- .../sparseImplementation/sparseVector.ml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 3591782507..262dfb8c32 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -138,8 +138,20 @@ module SparseVector: AbstractVector = let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries - let fold_left2_f_preserves_zero f acc v v' = - List.fold_left2 (fun acc (_, value) (_, value') -> f acc value value') acc v.entries v'.entries + let fold_left2_f_preserves_zero f acc v v' = + let rec aux acc v1 v2 = + match v1, v2 with + | [], [] -> acc + | [], (yidx, yval)::ys -> aux (f acc A.zero yval) [] ys + | (xidx, xval)::xs, [] -> aux (f acc xval A.zero) xs [] + | (xidx, xval)::xs, (yidx, yval)::ys -> + match xidx - yidx with + | d when d < 0 -> aux (f acc xval A.zero) xs v2 + | d when d > 0 -> aux (f acc A.zero yval) v1 ys + | _ -> aux (f acc xval yval) xs ys + in + if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else + (aux acc v.entries v'.entries) let apply_with_c f c v = let entries' = List.map (fun (idx, value) -> (idx, f value c)) v.entries in From 0207a737cda601d2fb05207c8c0ced200e57fae8 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 5 Dec 2024 17:39:57 +0100 Subject: [PATCH 082/240] print for debugging --- regtest.sh | 2 +- src/analyses/apron/affineEqualityAnalysis.apron.ml | 5 ++++- .../affineEquality/arrayImplementation/arrayMatrix.ml | 5 +++++ .../affineEquality/arrayImplementation/arrayVector.ml | 8 ++++---- .../affineEquality/sparseImplementation/listMatrix.ml | 3 +++ src/cdomains/apron/affineEqualityDomain.apron.ml | 2 +- 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/regtest.sh b/regtest.sh index 488dd0bab4..f263b2b968 100755 --- a/regtest.sh +++ b/regtest.sh @@ -14,7 +14,7 @@ if [[ $OSTYPE == 'darwin'* ]]; then grep="ggrep" fi params="`$grep -oP "PARAM: \K.*" $file`" -cmd="./goblint --enable warn.debug --enable dbg.regression --html $params ${@:3} $file" # -v +cmd="./goblint --enable warn.debug --enable dbg.regression $params ${@:3} $file -v" # -v --html echo "$cmd" eval $cmd echo "See result/index.xml" diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index 73ad59162f..80d3b32874 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -7,11 +7,14 @@ open Analyses open ArrayVector open ArrayMatrix +open SparseVector +open ListMatrix + include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in + let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 1f4722adff..0981c17626 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -288,7 +288,9 @@ module ArrayMatrix: AbstractMatrix = let normalize m = let copy = copy m in + let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in if normalize_with copy then + let () = Printf.printf "After normalizing we have m:\n%s" (show copy) in Some copy else None @@ -297,6 +299,8 @@ module ArrayMatrix: AbstractMatrix = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) (*Both input matrices must be in rref form!*) if num_rows m1 > num_rows m2 then false else + let m1' = copy m1 in + let m2' = copy m2 in let p2 = lazy (get_pivot_positions m2) in try ( for i = 0 to num_rows m1 - 1 do @@ -312,6 +316,7 @@ module ArrayMatrix: AbstractMatrix = if m1_i. (num_cols m1 - 1) <>: A.zero then raise Stdlib.Exit done; + (*let () = Printf.printf "m1: %sand m2: %s return true in is_covered_by.\n" (show m1') (show m2') in*) true ) with Stdlib.Exit -> false;; diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 937c4ee36f..b469245c27 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -114,13 +114,13 @@ module ArrayVector: AbstractVector = let find_opt f v = failwith "TODO" - let map_preserve_zero f v = failwith "TODO" - let map2_preserve_zero f v1 v2 = failwith "TODO" + let map_f_preserve_zero f v = failwith "TODO" + let map2_f_preserve_zero f v1 v2 = failwith "TODO" - let fold_left_preserve_zero f acc v = + let fold_left_f_preserve_zero f acc v = failwith "TODO" - let fold_left2_preserve_zero f acc v v' = + let fold_left2_f_preserve_zero f acc v v' = failwith "TODO" let findi_val_opt f v = diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6fabd9295d..0276662cc6 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -90,6 +90,7 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserve_zero (fun x y -> x -: s *: y) row1 row2 let reduce_col m j = + let () = Printf.printf "We are reducing matrix m:\n%s with %i\n" (show m) j in if is_empty m then m else let rec find_pivot idx entries = (* Finds non-zero element in column j and returns pair of row idx and the pivot value *) @@ -160,6 +161,7 @@ module ListMatrix: AbstractMatrix = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m let normalize m = + let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m @@ -203,6 +205,7 @@ module ListMatrix: AbstractMatrix = main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in + let () = Printf.printf "After normalizing we have m:\n%s" (show m') in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 2897559c43..000363286a 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -451,7 +451,7 @@ struct let t_primed = add_vars t primed_vars in let multi_t = List.fold_left2 (fun t' v_prime (_,v') -> assign_var t' v_prime v') t_primed primed_vars vv's in match multi_t.d with - | Some m when not @@ is_top_env multi_t -> + | Some m when not @@ is_top_env multi_t -> let () = Printf.printf "Matrix in Domain m:\n%s" (Matrix.show m) in let replace_col m x y = let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in let col_x = Matrix.get_col m dim_x in From ef0cc364fcfe82073b468099ba37b414c5c539cd Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 5 Dec 2024 22:59:32 +0100 Subject: [PATCH 083/240] Bugfixes in Vector and more Debug prints --- .../arrayImplementation/arrayMatrix.ml | 11 ++++- .../sparseImplementation/listMatrix.ml | 8 ++++ .../sparseImplementation/sparseVector.ml | 45 ++++++++++--------- .../apron/affineEqualityDomain.apron.ml | 12 ++++- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 0981c17626..1103f8c0a7 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -39,6 +39,7 @@ module ArrayMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m let add_empty_columns m cols = + let () = Printf.printf "Before add_empty_columns m:\n%s\n" (show m) in let nnc = Array.length cols in if is_empty m || nnc = 0 then m else let nr, nc = num_rows m, num_cols m in @@ -50,17 +51,20 @@ module ArrayMatrix: AbstractMatrix = m'.(i).(j + !offset) <- m.(i).(j); done done; + let () = Printf.printf "After add_empty_columns m:\n%s\n" (show m') in m' let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = + let () = Printf.printf "Before append_row m:\n%s\n" (show m) in let size = num_rows m in let new_matrix = Array.make_matrix (size + 1) (num_cols m) A.zero in for i = 0 to size - 1 do new_matrix.(i) <- m.(i) done; new_matrix.(size) <- V.to_array row; + let () = Printf.printf "After append_row m:\n%s\n" (show new_matrix) in new_matrix let get_row m n = @@ -84,11 +88,14 @@ module ArrayMatrix: AbstractMatrix = let set_col_with m new_col n = for i = 0 to num_rows m - 1 do m.(i).(n) <- V.nth new_col i - done; m + done; + let () = Printf.printf "After set_col m:\n%s\n" (show m) in + m let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n let set_col m new_col n = + let () = Printf.printf "Before set_col m:\n%s\n" (show m) in let copy = copy m in set_col_with copy new_col n @@ -341,8 +348,10 @@ module ArrayMatrix: AbstractMatrix = *) let map2 f m v = + let () = Printf.printf "Before map2 m:\n%s\n" (show m) in let m' = copy m in map2_with f m' v; + let () = Printf.printf "After map2 m:\n%s\n" (show m') in m' let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 1269396e66..081bcf206f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -39,6 +39,7 @@ module ListMatrix: AbstractMatrix = Timing.wrap "copy" (copy) m let add_empty_columns m cols = + let () = Printf.printf "Before add_empty_columns m:\n%s\n" (show m) in let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in let rec count_sorted_occ acc cols last count = @@ -48,12 +49,15 @@ module ListMatrix: AbstractMatrix = | (x :: xs) -> count_sorted_occ ((last, count) :: acc) xs x 1 in let occ_cols = count_sorted_occ [] sorted_cols (-1) 0 in + let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols) m)) in List.map (fun row -> V.insert_zero_at_indices row occ_cols) m let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = + let () = Printf.printf "Before append_row m:\n%s\n" (show m) in + let () = Printf.printf "After append_row m:\n%s\n" (show ( m @ [row])) in m @ [row] let get_row m n = @@ -69,7 +73,9 @@ module ListMatrix: AbstractMatrix = Timing.wrap "get_col" (get_col m) n let set_col m new_col n = + let () = Printf.printf "Before set_col m:\n%s\n" (show m) in (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) + let () = Printf.printf "After set_col m:\n%s\n" (show (List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col))) in List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) @@ -263,7 +269,9 @@ module ListMatrix: AbstractMatrix = List.find_opt f m let map2 f m v = + let () = Printf.printf "Before map2 we have m:\n%s\n" (show m) in let vector_length = V.length v in + let () = Printf.printf "After map2 we have m:\n%s\n" (show (List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m)) in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 262dfb8c32..aa9b7394d7 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -4,6 +4,7 @@ open ConvenienceOps open BatList open BatArray +open Batteries module List = BatList module Array = BatArray @@ -20,6 +21,20 @@ module SparseVector: AbstractVector = let to_vector e l = {entries=e; len=l} + let to_list v = + let[@tail_mod_cons] rec extend_zero_aux i v' = + if i >= v.len then [] else (*can probably be removed*) + match v', i with + | (xi,xv)::xs, _ -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero ::(extend_zero_aux (i+1) v') + | [], j when i < v.len -> A.zero :: (extend_zero_aux (i+1) v') + | [], _ -> [] + in + (extend_zero_aux 0 v.entries) + + let of_list l = + let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l + in {entries = entries'; len = List.length l} + let keep_vals v n = let rec keep_vals_vec v n = match v with @@ -82,7 +97,8 @@ module SparseVector: AbstractVector = in {entries = add_indices_helper v.entries idx 0; len = v.len + List.length idx} - let set_nth v n num = + let set_nth v n num = (* TODO: Optimize! *) + (* if n >= v.len then failwith "Out of bounds" else let rev_entries', _ = List.fold_lefti (fun (acc, found) i (idx, value) -> @@ -99,6 +115,8 @@ module SparseVector: AbstractVector = ) ([], false) v.entries in {entries = List.rev rev_entries'; len = v.len} + *) + of_list @@ List.mapi (fun i x -> if i = n then num else x) (to_list v) let insert_val_at n new_val v = if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) @@ -153,17 +171,14 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else (aux acc v.entries v'.entries) - let apply_with_c f c v = - let entries' = List.map (fun (idx, value) -> (idx, f value c)) v.entries in - {entries = entries'; len = v.len} let zero_vec n = {entries = []; len = n} let is_zero_vec v = (v.entries = []) - let nth v n = - if n >= v.len then failwith "V.nth out of bounds" + let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) + if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") else let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) | [] -> A.zero @@ -175,24 +190,12 @@ module SparseVector: AbstractVector = let length v = v.len - let of_list l = - let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l - in {entries = entries'; len = List.length l} - - let to_list v = - let[@tail_mod_cons] rec extend_zero_aux i v' = - if i >= v.len then [] else (*can probably be removed*) - match v', i with - | (xi,xv)::xs, _ -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero ::(extend_zero_aux (i+1) v') - | [], j when i < v.len -> A.zero :: (extend_zero_aux (i+1) v') - | [], _ -> [] - in - (extend_zero_aux 0 v.entries) - let map2 f v v' = if v.len <> v'.len then failwith "Unequal vector length" else of_list (List.map2 f (to_list v) (to_list v')) + let apply_with_c f c v = (* TODO: optimize! *) + of_list @@ List.map (fun value -> f value c) (to_list v) let findi f v = if f A.zero then @@ -246,7 +249,7 @@ module SparseVector: AbstractVector = of_list (List.mapi f (to_list v)) let find2i f v v' = (* TODO: optimize! *) - failwith "TODO" + fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) let to_array v = let vec = Array.make v.len A.zero in diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 000363286a..f8e632ee6b 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -33,11 +33,13 @@ struct let dim_remove (ch: Apron.Dim.change) m ~del = + let () = Printf.printf "Before dim_remove m:\n%s" (show m) in if Array.length ch.dim = 0 || is_empty m then m else ( Array.modifyi (+) ch.dim; let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in + let () = Printf.printf "After dim_remove m':\n%s" (show (remove_zero_rows @@ del_cols m' ch.dim)) in remove_zero_rows @@ del_cols m' ch.dim) let dim_remove ch m ~del = Timing.wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del @@ -348,6 +350,7 @@ struct let join a b = let res = join a b in + let () = Printf.printf "join a: %s b: %s -> %s \n" (show a) (show b) (show res) in if M.tracing then M.tracel "join" "join a: %s b: %s -> %s " (show a) (show b) (show res) ; res @@ -368,6 +371,7 @@ struct let remove_rels_with_var x var env = Timing.wrap "remove_rels_with_var" remove_rels_with_var x var env let forget_vars t vars = + let () = Printf.printf "forget_vars m:\n%s" (show t) in if is_bot t || is_top_env t || vars = [] then t else @@ -409,7 +413,8 @@ struct in (* let assign_uninvertible_rel x var b env = Timing.wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) let is_invertible v = Vector.nth v @@ Environment.dim_of_var t.env var <>: Mpqf.zero - in let affineEq_vec = get_coeff_vec t texp + in let affineEq_vec = get_coeff_vec t texp in + let () = Printf.printf "After affineEq_vec m:\n%s\n" (Vector.show (Option.get affineEq_vec)) in if is_bot t then t else let m = Option.get t.d in match affineEq_vec with | Some v when is_top_env t -> if is_invertible v then t else assign_uninvertible_rel m var v t.env @@ -445,13 +450,15 @@ struct res let assign_var_parallel t vv's = + let () = Printf.printf "Before assign_var_parallel m:\n%s\n" (show t) in let assigned_vars = List.map fst vv's in let t = add_vars t assigned_vars in let primed_vars = List.init (List.length assigned_vars) (fun i -> Var.of_string (Int.to_string i ^"'")) in (* TODO: we use primed vars in analysis, conflict? *) let t_primed = add_vars t primed_vars in let multi_t = List.fold_left2 (fun t' v_prime (_,v') -> assign_var t' v_prime v') t_primed primed_vars vv's in + let () = Printf.printf "After assign_var_parallel multi_t:\n%s\n" (show multi_t) in match multi_t.d with - | Some m when not @@ is_top_env multi_t -> let () = Printf.printf "Matrix in Domain m:\n%s" (Matrix.show m) in + | Some m when not @@ is_top_env multi_t -> let () = Printf.printf "Matrix in Domain m:\n%s\n" (Matrix.show m) in let replace_col m x y = let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in let col_x = Matrix.get_col m dim_x in @@ -459,6 +466,7 @@ struct in let m_cp = Matrix.copy m in let switched_m = List.fold_left2 replace_col m_cp primed_vars assigned_vars in + let () = Printf.printf "Switched Matrix in Domain switched_m:\n%s\n" (Matrix.show switched_m) in let res = drop_vars {d = Some switched_m; env = multi_t.env} primed_vars ~del:true in let x = Option.get res.d in (match Matrix.normalize x with From c038dc76417f271e821bd2a2b648bbf046ffa450 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 6 Dec 2024 08:32:17 +0100 Subject: [PATCH 084/240] Bugfix in Vector keep_vals and to_list; Implement set_nth in Vector" --- .../sparseImplementation/listMatrix.ml | 5 +- .../sparseImplementation/sparseVector.ml | 46 +++++++------------ .../apron/affineEqualityDomain.apron.ml | 3 ++ 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 081bcf206f..fdc78a8a8a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -56,8 +56,8 @@ module ListMatrix: AbstractMatrix = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - let () = Printf.printf "Before append_row m:\n%s\n" (show m) in - let () = Printf.printf "After append_row m:\n%s\n" (show ( m @ [row])) in + let () = Printf.printf "Before append_row m:\n%s\n" (show m) in + let () = Printf.printf "After append_row m:\n%s\n" (show ( m @ [row])) in m @ [row] let get_row m n = @@ -67,6 +67,7 @@ module ListMatrix: AbstractMatrix = List.remove_at n m let get_col m n = + let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_list @@ List.map (fun row -> V.nth row n) m)) in V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) let get_col m n = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index aa9b7394d7..46cd68b990 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -23,11 +23,10 @@ module SparseVector: AbstractVector = let to_list v = let[@tail_mod_cons] rec extend_zero_aux i v' = - if i >= v.len then [] else (*can probably be removed*) - match v', i with - | (xi,xv)::xs, _ -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero ::(extend_zero_aux (i+1) v') - | [], j when i < v.len -> A.zero :: (extend_zero_aux (i+1) v') - | [], _ -> [] + match v', i with + | (xi,xv)::xs, _ -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero ::(extend_zero_aux (i+1) v') + | [], j when i < v.len -> A.zero :: (extend_zero_aux (i+1) v') + | [], _ -> [] in (extend_zero_aux 0 v.entries) @@ -36,13 +35,8 @@ module SparseVector: AbstractVector = in {entries = entries'; len = List.length l} let keep_vals v n = - let rec keep_vals_vec v n = - match v with - | x::xs -> if fst x > n then [] else x::(keep_vals_vec xs n) - | [] -> [] - in - if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = keep_vals_vec v.entries n; len=n} + if n >= v.len then v else + {entries = take_while (fun (idx, _) -> idx < n) v.entries; len=n} let remove_nth v n = @@ -98,25 +92,17 @@ module SparseVector: AbstractVector = {entries = add_indices_helper v.entries idx 0; len = v.len + List.length idx} let set_nth v n num = (* TODO: Optimize! *) - (* if n >= v.len then failwith "Out of bounds" else - let rev_entries', _ = List.fold_lefti (fun (acc, found) i (idx, value) -> - if found then ((idx, value) :: acc, true) - else - if i = v.len - 1 then - if idx = n then (if num <>: A.zero then (n, num) :: acc, true else acc, true) - else if idx > n then (if num <>: A.zero then (idx, value) :: (n, num) :: acc, true else (idx, value) :: acc, true) - else failwith "Out of bounds (Should not be reachable)" - else - if idx < n then ((idx, value) :: acc, false) - else if idx = n then (if num <>: A.zero then (n, num) :: acc , true else acc, true) - else (if num <>: A.zero then (idx, value) :: (n, num) :: acc, true else (idx, value) :: acc, true) - - ) ([], false) v.entries in - {entries = List.rev rev_entries'; len = v.len} - *) - of_list @@ List.mapi (fun i x -> if i = n then num else x) (to_list v) + (* of_list @@ List.mapi (fun i x -> if i = n then num else x) (to_list v) *) + let rec set_nth_helper vec acc = + match vec with + | [] -> if num <>: A.zero then List.rev ((n, num) :: acc) else List.rev acc + | (idx, value) :: xs when n = idx -> if num <>: A.zero then List.rev_append ((idx, num) :: acc) xs else List.rev_append acc xs + | (idx, value) :: xs when n < idx -> if num <>: A.zero then List.rev_append ((n, num) :: acc) vec else List.rev_append acc ((idx, value) :: xs) + | x :: xs -> set_nth_helper xs (x :: acc) + in + {entries = set_nth_helper v.entries []; len = v.len} let insert_val_at n new_val v = if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) @@ -190,7 +176,7 @@ module SparseVector: AbstractVector = let length v = v.len - let map2 f v v' = + let map2 f v v' = (* TODO: Optimize! *) if v.len <> v'.len then failwith "Unequal vector length" else of_list (List.map2 f (to_list v) (to_list v')) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index f8e632ee6b..9823227b03 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -257,6 +257,7 @@ struct let meet t1 t2 = let res = meet t1 t2 in + let () = Printf.printf "meet a: %s b: %s -> %s \n" (show t1) (show t2) (show res) in if M.tracing then M.tracel "meet" "meet a: %s b: %s -> %s " (show t1) (show t2) (show res) ; res @@ -283,6 +284,7 @@ struct let leq t1 t2 = let res = leq t1 t2 in + let () = Printf.printf "leq a: %s b: %s -> %b \n" (show t1) (show t2) res in if M.tracing then M.tracel "leq" "leq a: %s b: %s -> %b " (show t1) (show t2) res ; res @@ -355,6 +357,7 @@ struct res let widen a b = + let () = Printf.printf "Widen a: %s b: %s\n" (show a) (show b) in if Environment.equal a.env b.env then join a b else From 92b784a805db6341378e97be12c399f8f8a12fa1 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 6 Dec 2024 10:51:34 +0100 Subject: [PATCH 085/240] Bugfix insert_val_at --- .../affineEquality/sparseImplementation/sparseVector.ml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 46cd68b990..ea306745ad 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -59,8 +59,7 @@ module SparseVector: AbstractVector = if n >= v.len then failwith "Out of bounds" else let new_entries = List.filter_map (fun (col_idx, value) -> - if col_idx = n - then None + if col_idx = n then None else if col_idx > n then Some (col_idx - 1, value) else Some (col_idx, value) @@ -108,7 +107,7 @@ module SparseVector: AbstractVector = if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) let entries' = List.fold_left (fun acc (idx, value) -> if idx < n then (idx, value) :: acc - else (idx + 1, value) :: acc + else (idx + 1, value) :: (idx, new_val):: acc ) [] (List.rev v.entries) in {entries = List.sort (fun (i, _) (j, _) -> Int.compare i j) entries'; len = v.len + 1} From 8ba57776013acdf49ef27e330c2fbcb8c18017b4 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 6 Dec 2024 12:32:21 +0100 Subject: [PATCH 086/240] Bugfix Matrix map2i and Vector insert_val_at again --- .../sparseImplementation/listMatrix.ml | 12 ++++++++---- .../sparseImplementation/sparseVector.ml | 8 ++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index fdc78a8a8a..236da00c64 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -144,10 +144,14 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols - let map2i f m v = - let vector_length = V.length v in - (* List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row) m *) - List.map2i (fun index row value -> if index < vector_length then f index row value else row) m (V.to_list v) + let map2i f m v= + let rec map2i_min i acc m v = + match m, v with + | [], _ | _, [] -> List.rev acc + | row :: rs, value :: vs -> + map2i_min (i + 1) (f i row value :: acc) rs vs + in + map2i_min 0 [] m (V.to_list v) let remove_zero_rows m = List.filter (fun row -> not (V.is_zero_vec row)) m diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index ea306745ad..338d8f396c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -105,11 +105,11 @@ module SparseVector: AbstractVector = let insert_val_at n new_val v = if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) - let entries' = List.fold_left (fun acc (idx, value) -> + let entries' = List.rev @@ List.fold_left (fun acc (idx, value) -> if idx < n then (idx, value) :: acc - else (idx + 1, value) :: (idx, new_val):: acc - ) [] (List.rev v.entries) in - {entries = List.sort (fun (i, _) (j, _) -> Int.compare i j) entries'; len = v.len + 1} + else (if new_val <>: A.zero then (idx + 1, value) :: (n, new_val) :: acc else (idx + 1, value) :: acc) + ) [] v.entries in + {entries = entries'; len = v.len + 1} let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( From f6a415ee35b8c7a1a0679831d7446434e32a9e89 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 6 Dec 2024 13:53:42 +0100 Subject: [PATCH 087/240] Add more debug-prints --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 2 +- .../affineEquality/arrayImplementation/arrayMatrix.ml | 5 +++++ .../affineEquality/sparseImplementation/listMatrix.ml | 9 ++++++--- .../affineEquality/sparseImplementation/sparseVector.ml | 4 ++-- src/cdomains/apron/affineEqualityDomain.apron.ml | 3 +++ 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index 80d3b32874..e262b2653b 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -14,7 +14,7 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in + let module AD = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 1103f8c0a7..2248b1f414 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -81,6 +81,7 @@ module ArrayMatrix: AbstractMatrix = Array.blit m (n + 1) new_matrix n (num_rows new_matrix - n)); new_matrix let get_col m n = + let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)))) in V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)) let get_col m n = Timing.wrap "get_col" (get_col m) n @@ -206,12 +207,14 @@ module ArrayMatrix: AbstractMatrix = let reduce_col_with_vec m j v = + let () = Printf.printf "Matrix: Before reduce_col_with_vec %i with vec %s of m:\n%s\n" j (V.show (V.of_array v)) (show m) in for i = 0 to num_rows m - 1 do if m.(i).(j) <>: A.zero then let beta = m.(i).(j) /: v.(j) in Array.iteri (fun j' x -> m.(i).(j') <- x -: beta *: v.(j')) m.(i) done + let get_pivot_positions m = let pivot_elements = Array.make (num_rows m) 0 in Array.iteri (fun i x -> pivot_elements.(i) <- Array.findi (fun z -> z =: A.one) x) m; pivot_elements @@ -373,8 +376,10 @@ module ArrayMatrix: AbstractMatrix = Array.map2 f' m (Array.combine range_array (V.to_array v)) *) let map2i f m v = + let () = Printf.printf "Before map2i m:\n%sv:%s\n" (show m) (V.show v) in let m' = copy m in map2i_with f m' v; + let () = Printf.printf "After map2i m:\n%s\n" (show m') in m' let swap_rows m j k = diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 236da00c64..87bf5702da 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -97,7 +97,7 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: s *: y) row1 row2 let reduce_col m j = - let () = Printf.printf "We are reducing matrix m:\n%s with %i\n" (show m) j in + let () = Printf.printf "Matrix: reduce_col %i of m:\n%s\n" j (show m) in if is_empty m then m else let rec find_pivot idx entries = (* Finds non-zero element in column j and returns pair of row idx and the pivot value *) @@ -121,6 +121,7 @@ module ListMatrix: AbstractMatrix = ) m let reduce_col_with_vec m j v = + let () = Printf.printf "Before reduce_col_with_vec %i with vec %s of m:\n%s\n" j (V.show v) (show m) in let pivot_element = V.nth v j in if pivot_element = A.zero then m else List.mapi (fun idx row -> @@ -144,13 +145,15 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols - let map2i f m v= + let map2i f m v = + let () = Printf.printf "Before map2i m:\n%sv:%s\n" (show m) (V.show v) in let rec map2i_min i acc m v = match m, v with | [], _ | _, [] -> List.rev acc | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs - in + in + let () = Printf.printf "After map2i m:\n%s\n" (show (map2i_min 0 [] m (V.to_list v))) in map2i_min 0 [] m (V.to_list v) let remove_zero_rows m = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 338d8f396c..1dd59d1454 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -192,9 +192,9 @@ module SparseVector: AbstractVector = let findi_val_opt f v = let rec find_zero_or_val vec last_col_idx = match vec, last_col_idx with - | [], _ -> if v.len <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) else None + | [], _ -> if f A.zero && v.len <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else None | (idx, value) :: xs, i -> - if idx <> last_col_idx + 1 && f A.zero then Some (last_col_idx + 1, A.zero) + if f A.zero && idx <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else if f value then Some (idx, value) else find_zero_or_val xs idx in find_zero_or_val v.entries (-1) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 9823227b03..a08c44b661 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -298,7 +298,9 @@ struct in let case_three a b col_a col_b max = let col_a, col_b = Vector.copy col_a, Vector.copy col_b in + let () = Printf.printf "Before keep_vals: \ncol_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in let col_a, col_b = Vector.keep_vals col_a max, Vector.keep_vals col_b max in + let () = Printf.printf "After keep_vals: \ncol_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in if Vector.equal col_a col_b then (a, b, max) else @@ -312,6 +314,7 @@ struct let col_a = Vector.map2 (-:) col_a col_b in let col_a = Vector.rev col_a in let multiply_by_t m t = + let () = Printf.printf "Before multiply_by_t col_a: %s" (Vector.show col_a) in Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2 (fun u j -> u -: (beta *: j)) x t) else x) m col_a; in From 3e7d3d6ae503011ec665bc49d6dfd06d0e266b5f Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 6 Dec 2024 18:42:36 +0100 Subject: [PATCH 088/240] Bugfix in Vector rev and Matrix map2i again --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 2 +- .../affineEquality/arrayImplementation/arrayMatrix.ml | 1 + .../affineEquality/sparseImplementation/listMatrix.ml | 7 ++++--- .../affineEquality/sparseImplementation/sparseVector.ml | 2 +- src/cdomains/apron/affineEqualityDomain.apron.ml | 2 ++ 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index e262b2653b..80d3b32874 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -14,7 +14,7 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in + let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 2248b1f414..5e8407d621 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -71,6 +71,7 @@ module ArrayMatrix: AbstractMatrix = V.of_array m.(n) let remove_row m n = + let () = Printf.printf "Before remove_row %i of m:\n%s\n" n (show m) in let new_matrix = Array.make_matrix (num_rows m - 1) (num_cols m) A.zero in if not @@ is_empty new_matrix then if n = 0 then diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 87bf5702da..5440c55244 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -64,6 +64,7 @@ module ListMatrix: AbstractMatrix = List.nth m n let remove_row m n = + let () = Printf.printf "Before remove_row %i of m:\n%s\n" n (show m) in List.remove_at n m let get_col m n = @@ -149,9 +150,9 @@ module ListMatrix: AbstractMatrix = let () = Printf.printf "Before map2i m:\n%sv:%s\n" (show m) (V.show v) in let rec map2i_min i acc m v = match m, v with - | [], _ | _, [] -> List.rev acc - | row :: rs, value :: vs -> - map2i_min (i + 1) (f i row value :: acc) rs vs + | [], _ -> List.rev acc + | row :: rs, [] -> List.rev_append (row :: acc) rs + | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs in let () = Printf.printf "After map2i m:\n%s\n" (show (map2i_min 0 [] m (V.to_list v))) in map2i_min 0 [] m (V.to_list v) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 1dd59d1454..a9e5af6fd0 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -224,7 +224,7 @@ module SparseVector: AbstractVector = List.exists2 f (to_list v1) (to_list v2) let rev v = - let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - idx, value)) v.entries in + let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in {entries = entries'; len = v.len} let map2i f v v' = (* TODO: optimize! *) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index a08c44b661..7df3ac7edc 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -305,8 +305,10 @@ struct (a, b, max) else ( + let () = Printf.printf "Before rev col_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in let col_a = Vector.rev col_a in let col_b = Vector.rev col_b in + let () = Printf.printf "After rev col_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in let i = Vector.find2i (<>:) col_a col_b in let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in From 0c95dc73572d2e5de8b62fb407bde54098725c78 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 6 Dec 2024 20:12:37 +0100 Subject: [PATCH 089/240] Bugfix in Matrix del_cols and Vector remove_at_indices --- .../arrayImplementation/arrayMatrix.ml | 4 +++- .../sparseImplementation/listMatrix.ml | 23 +++++++++++++++---- .../sparseImplementation/sparseVector.ml | 4 +++- .../apron/affineEqualityDomain.apron.ml | 1 + 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 5e8407d621..14963944e2 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -124,8 +124,10 @@ module ArrayMatrix: AbstractMatrix = let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = + let () = Printf.printf "Before reduce_col %i of m:\n%s\n" j (show m) in let copy = copy m in reduce_col_with copy j; + let () = Printf.printf "After reduce_col %i of m:\n%s\n" j (show copy) in copy let del_col m j = @@ -208,7 +210,6 @@ module ArrayMatrix: AbstractMatrix = let reduce_col_with_vec m j v = - let () = Printf.printf "Matrix: Before reduce_col_with_vec %i with vec %s of m:\n%s\n" j (V.show (V.of_array v)) (show m) in for i = 0 to num_rows m - 1 do if m.(i).(j) <>: A.zero then let beta = m.(i).(j) /: v.(j) in @@ -288,6 +289,7 @@ module ArrayMatrix: AbstractMatrix = let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 let rref_matrix m1 m2 = + let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in let m1' = copy m1 in let m2' = copy m2 in rref_matrix_with m1' m2' diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 5440c55244..a4690a55e4 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -98,7 +98,7 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: s *: y) row1 row2 let reduce_col m j = - let () = Printf.printf "Matrix: reduce_col %i of m:\n%s\n" j (show m) in + let () = Printf.printf "Before reduce_col %i of m:\n%s\n" j (show m) in if is_empty m then m else let rec find_pivot idx entries = (* Finds non-zero element in column j and returns pair of row idx and the pivot value *) @@ -108,8 +108,18 @@ module ListMatrix: AbstractMatrix = if value =: A.zero then find_pivot (idx - 1) rest else Some (idx, value) in match (find_pivot (num_rows m - 1) (List.rev m)) with - | None -> m (* column is already filled with zeroes *) + | None -> let () = Printf.printf "After reduce_col %i of m:\n%s\n" j (show m) in m (* column is already filled with zeroes *) | Some (row_idx, pivot) -> + let () = Printf.printf "After reduce_col %i of m:\n%s\n" j (show (let pivot_row = List.nth m row_idx in + List.mapi (fun idx row -> + if idx = row_idx then + V.zero_vec (num_cols m) + else + let row_value = V.nth row j in + if row_value = A.zero then row + else (let s = row_value /: pivot in + sub_scaled_row row pivot_row s) + ) m)) in let pivot_row = List.nth m row_idx in List.mapi (fun idx row -> if idx = row_idx then @@ -140,7 +150,8 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) - if (List.length cols) = num_cols m then empty() + let () = Printf.printf "Before del_cols cols_length=%i sorted_length=%i \nm:\n%s\n" (List.length cols) (List.length sorted_cols) (show m) in + if (List.length sorted_cols) = num_cols m then empty() else List.map (fun row -> V.remove_at_indices row sorted_cols) m @@ -189,7 +200,7 @@ module ListMatrix: AbstractMatrix = let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) - | Some (idx, value) -> let () = Printf.printf "We found first non-zero at index %i in row %i\n" idx i in + | Some (idx, value) -> (* let () = Printf.printf "We found first non-zero at index %i in row %i\n" idx i in *) if idx < cur_col then (row_idx + i, idx, value) else (cur_row, cur_col, cur_val) ) (num_rows m', num_cols m', A.zero) m' (* Initializing with max, so num_cols m indicates that pivot is not found *) in @@ -209,7 +220,7 @@ module ListMatrix: AbstractMatrix = match find_first_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized*) | Some (piv_row_idx, piv_col_idx, piv_val) -> ( - let () = Printf.printf "The current matrix is: \n%s and the pivot is (%i, %i, %s)\n" (show m) piv_row_idx piv_col_idx (A.to_string piv_val) in + (* let () = Printf.printf "The current matrix is: \n%s and the pivot is (%i, %i, %s)\n" (show m) piv_row_idx piv_col_idx (A.to_string piv_val) in *) let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in let piv_row = (List.nth normalized_m row_idx) in @@ -229,12 +240,14 @@ module ListMatrix: AbstractMatrix = (*If m is empty then v is simply normalized and returned*) (* TODO: OPTIMIZE! *) let rref_vec m v = + let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in normalize @@ append_matrices m (init_with_vec v) (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) (*TODO: OPTIMIZE!*) let rref_matrix m1 m2 = + let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in normalize @@ append_matrices m1 m2 diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a9e5af6fd0..10a841beee 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -66,11 +66,13 @@ module SparseVector: AbstractVector = ) v.entries in {entries = new_entries; len = v.len - 1} + (* Note: It is assumed and necessary here that idx is sorted!!! *) let remove_at_indices v idx = let rec remove_indices_helper vec idx deleted_count = match vec, idx with | [], [] -> [] - | [], (y :: ys) -> failwith "remove at indices: no more columns to delete" + | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> failwith "remove at indices: no more columns to delete" + | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) (* Removing zero (also in next iteration, else failwith ) *) | ((col_idx, value) :: xs), [] -> (col_idx - deleted_count, value) :: remove_indices_helper xs [] deleted_count | ((col_idx, value) :: xs), (y :: ys) when y = col_idx -> remove_indices_helper xs ys (deleted_count + 1) | ((col_idx, value) :: xs), (y :: ys) when y < col_idx -> remove_indices_helper vec ys (deleted_count + 1) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 7df3ac7edc..3c00ebf263 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -415,6 +415,7 @@ struct let b_length = Vector.length b in let b = Vector.mapi (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b in let b = Vector.set_nth b (Environment.dim_of_var env var) Mpqf.one in + let () = Printf.printf "Before Matrix.rref_vec x:\n%s b:\n%s\n" (Matrix.show x) (Vector.show b) in match Matrix.rref_vec x b with | None -> bot () | some_matrix -> {d = some_matrix; env = env} From c72c77d0203df105e4ad7e846fc7908d9da2b9d7 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 6 Dec 2024 22:10:43 +0100 Subject: [PATCH 090/240] arraymatrix passes tests again --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 2 +- src/cdomains/apron/affineEqualityDomain.apron.ml | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index 80d3b32874..e262b2653b 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -14,7 +14,7 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in + let module AD = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 3c00ebf263..5a666f728b 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -423,11 +423,12 @@ struct (* let assign_uninvertible_rel x var b env = Timing.wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) let is_invertible v = Vector.nth v @@ Environment.dim_of_var t.env var <>: Mpqf.zero in let affineEq_vec = get_coeff_vec t texp in - let () = Printf.printf "After affineEq_vec m:\n%s\n" (Vector.show (Option.get affineEq_vec)) - in if is_bot t then t else let m = Option.get t.d in + if is_bot t then t else let m = Option.get t.d in match affineEq_vec with - | Some v when is_top_env t -> if is_invertible v then t else assign_uninvertible_rel m var v t.env - | Some v -> if is_invertible v then let t' = assign_invertible_rels (Matrix.copy m) var v t.env in {d = t'.d; env = t'.env} + | Some v when is_top_env t -> let () = Printf.printf "After affineEq_vec m:\n%s\n" (Vector.show v) in + if is_invertible v then t else assign_uninvertible_rel m var v t.env + | Some v -> let () = Printf.printf "After affineEq_vec m:\n%s\n" (Vector.show v) in + if is_invertible v then let t' = assign_invertible_rels (Matrix.copy m) var v t.env in {d = t'.d; env = t'.env} else let new_m = Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env in assign_uninvertible_rel new_m var v t.env | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env); env = t.env} From 09054a1eec8e898ee0e2cd8a02104f08ad44e3a8 Mon Sep 17 00:00:00 2001 From: Havercake Date: Fri, 6 Dec 2024 23:12:25 +0100 Subject: [PATCH 091/240] Reduced test suite; Simple normalized test with mxn-Matrix with m!=n; --- .../sparseMatrixImplementationTest.ml | 47 +++++++++++++++++++ tests/unit/mainTest.ml | 5 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml new file mode 100644 index 0000000000..5632dc4e4a --- /dev/null +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -0,0 +1,47 @@ +(* + To run this, type `dune runtest tests/unit/`. +*) + +open Goblint_lib +open OUnit2 +open SparseVector +open ListMatrix +module D = SharedFunctions.Mpqf +module Vector = SparseVector (D) +module Matrix = ListMatrix (D) (SparseVector) + +let normalize _ = + let width = 4 in + let int x = D.of_int x in + let any_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 2); (2, int 4); (3, int (-1)) ]) + ) + (Vector.of_sparse_list width [ (0, int 2); (1, int 3); (2, int 4) ]) + ) + (Vector.of_sparse_list width [ (0, int 1); (1, int 1); (2, int 2); (3, int 4) ] + ) + in + let normalized_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_sparse_list width [ (0,int 1); (2,int 2) ]) + ) + (Vector.of_sparse_list width [ (1,int 1) ]) + ) + (Vector.of_sparse_list width [ (3,int 1) ] + ) + in + match Matrix.normalize any_matrix with + | None -> assert_failure "The matrix is normalizable but was not normalized!" + | Some reduced_matrix -> assert_equal reduced_matrix normalized_matrix + +let tests = "SparseMatrixImplementationTest" >::: [ "normalize" >:: normalize ] + +let () = + run_test_tt_main tests diff --git a/tests/unit/mainTest.ml b/tests/unit/mainTest.ml index 4f071ea25c..4fd65f6736 100644 --- a/tests/unit/mainTest.ml +++ b/tests/unit/mainTest.ml @@ -7,6 +7,7 @@ let all_tests = MapDomainTest.test (); SolverTest.test (); LvalTest.test (); + SparseMatrixImplementationTest.tests ; CompilationDatabaseTest.tests; LibraryDslTest.tests; CilfacadeTest.tests; @@ -15,6 +16,8 @@ let all_tests = IntOpsTest.tests; ] +let subset_tests = "" >::: [SparseMatrixImplementationTest.tests] + let () = print_string "\027[0;1munit: \027[0;0;00m"; - run_test_tt_main all_tests + run_test_tt_main subset_tests From 29689633ea5c4514ff4498e8b17c2b332888d409 Mon Sep 17 00:00:00 2001 From: Havercake Date: Fri, 6 Dec 2024 23:20:40 +0100 Subject: [PATCH 092/240] Added example source --- .../sparseImplementation/sparseMatrixImplementationTest.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 5632dc4e4a..cce52c6a7d 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -11,6 +11,7 @@ module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) let normalize _ = + (* Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ)*) let width = 4 in let int x = D.of_int x in let any_matrix = From 4ef3acc661bba131402cb7cc8f7f24955d2b06c8 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Sat, 7 Dec 2024 11:58:34 +0100 Subject: [PATCH 093/240] more debugging prints and added remove_zero_rows to rref_vec --- .../arrayImplementation/arrayMatrix.ml | 44 +++++++++++-------- .../sparseImplementation/listMatrix.ml | 7 ++- .../sparseImplementation/sparseVector.ml | 2 +- .../sparseMatrixImplementationTest.ml | 2 + 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 14963944e2..b9bd503ddc 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -139,6 +139,7 @@ module ArrayMatrix: AbstractMatrix = let del_cols m cols = let n_c = Array.length cols in + let () = Printf.printf "Before del_cols cols_length=%i \nm:\n%s\n" n_c (show m) in if n_c = 0 || is_empty m then m else let m_r, m_c = num_rows m, num_cols m in @@ -210,6 +211,7 @@ module ArrayMatrix: AbstractMatrix = let reduce_col_with_vec m j v = + let () = Printf.printf "Before reduce_col_with_vec %i with vec %s of m:\n%s\n" j (V.show (V.of_array v)) (show m) in for i = 0 to num_rows m - 1 do if m.(i).(j) <>: A.zero then let beta = m.(i).(j) /: v.(j) in @@ -245,12 +247,25 @@ module ArrayMatrix: AbstractMatrix = else (Array.blit m 0 new_m 0 i; new_m.(i) <- v; Array.blit m i new_m (i + 1) (Array.length m - j)); Some new_m + let normalize_with m = + rref_with m + + let normalize_with m = Timing.wrap "normalize_with" normalize_with m + let normalize m = + let copy = copy m in + let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in + if normalize_with copy then + let () = Printf.printf "After normalizing we have m:\n%s" (show copy) in + Some copy + else + let () = Printf.printf "No normalization" in + None let rref_vec_with m v = (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) - let v = V.to_array v in + (*let v = V.to_array v in if is_empty m then match Array.findi (fun x -> x <>: A.zero) v with | exception Not_found -> None @@ -259,14 +274,19 @@ module ArrayMatrix: AbstractMatrix = Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) else let pivot_elements = get_pivot_positions m in - rref_vec_helper m pivot_elements v + rref_vec_helper m pivot_elements v*) + normalize @@ append_row m v let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v let rref_vec m v = (* !! There was another rref_vec function that has been renamed to rref_vec_helper !!*) + let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in let m' = copy m in let v' = V.copy v in - rref_vec_with m' v' + match rref_vec_with m' v' with + | Some res -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in + Some (remove_zero_rows res) + | None -> None let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) @@ -294,20 +314,6 @@ module ArrayMatrix: AbstractMatrix = let m2' = copy m2 in rref_matrix_with m1' m2' - let normalize_with m = - rref_with m - - let normalize_with m = Timing.wrap "normalize_with" normalize_with m - - let normalize m = - let copy = copy m in - let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in - if normalize_with copy then - let () = Printf.printf "After normalizing we have m:\n%s" (show copy) in - Some copy - else - None - let is_covered_by m1 m2 = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) (*Both input matrices must be in rref form!*) @@ -354,10 +360,10 @@ module ArrayMatrix: AbstractMatrix = *) let map2 f m v = - let () = Printf.printf "Before map2 m:\n%s\n" (show m) in + let () = Printf.printf "Before map2 we have m:\n%s\n" (show m) in let m' = copy m in map2_with f m' v; - let () = Printf.printf "After map2 m:\n%s\n" (show m') in + let () = Printf.printf "After map2 we have m:\n%s\n" (show m') in m' let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index a4690a55e4..8aa2955427 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -150,7 +150,7 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) - let () = Printf.printf "Before del_cols cols_length=%i sorted_length=%i \nm:\n%s\n" (List.length cols) (List.length sorted_cols) (show m) in + let () = Printf.printf "Before del_cols cols_length=%i \nm:\n%s\n" (List.length cols) (show m) in if (List.length sorted_cols) = num_cols m then empty() else List.map (fun row -> V.remove_at_indices row sorted_cols) m @@ -241,7 +241,10 @@ module ListMatrix: AbstractMatrix = (* TODO: OPTIMIZE! *) let rref_vec m v = let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in - normalize @@ append_matrices m (init_with_vec v) + match normalize @@ append_matrices m (init_with_vec v) with + | Some res -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in + Some (remove_zero_rows res) + | None -> None (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 10a841beee..76646527ed 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -268,7 +268,7 @@ module SparseVector: AbstractVector = let rec list_str l = match l with | [] -> "]" - | x :: xs -> " " ^ (A.to_string x) ^ (list_str xs) + | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) in "["^list_str t^"\n" diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index cce52c6a7d..9e9633317d 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -6,6 +6,8 @@ open Goblint_lib open OUnit2 open SparseVector open ListMatrix +open ArrayVector +open ArrayMatrix module D = SharedFunctions.Mpqf module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) From 968c533d673d5b55a066102b29c882324c3d431b Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 7 Dec 2024 12:21:34 +0100 Subject: [PATCH 094/240] Bugfixes in ListMatrix normalize --- .../affineEquality/sparseImplementation/listMatrix.ml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 8aa2955427..3c67dfec02 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -193,18 +193,20 @@ module ListMatrix: AbstractMatrix = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) + (* The last column represents the constant in the affeq *) let find_first_pivot m' row_idx col_idx = if col_idx >= col_count then None else + let max_piv_col_idx = num_cols m' - 2 in (* col at num_cols - 1 is the constant of the affeq *) (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) | Some (idx, value) -> (* let () = Printf.printf "We found first non-zero at index %i in row %i\n" idx i in *) - if idx < cur_col then (row_idx + i, idx, value) else (cur_row, cur_col, cur_val) - ) (num_rows m', num_cols m', A.zero) m' (* Initializing with max, so num_cols m indicates that pivot is not found *) + if idx < cur_col then (i, idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m', max_piv_col_idx + 1, A.zero) m' (* Initializing with max, so num_cols m indicates that pivot is not found *) in - if piv_col = (num_cols m') then None else Some (piv_row, piv_col + col_idx, piv_val) + if piv_col = (max_piv_col_idx + 1) then None else Some (row_idx + piv_row, col_idx + piv_col, piv_val) in let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) let col_count = num_cols m in @@ -227,7 +229,7 @@ module ListMatrix: AbstractMatrix = let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then let scale = V.nth row piv_col_idx in sub_scaled_row row piv_row scale else row) normalized_m in - let m' = dec_mat_2D m (row_idx + 1) (piv_col_idx + 1) in + let m' = dec_mat_2D subtracted_m (row_idx + 1) (piv_col_idx + 1) in main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in From fe6b2a6eeb1b415dcfcfd92047333ddd11135cda Mon Sep 17 00:00:00 2001 From: Havercake Date: Mon, 9 Dec 2024 11:39:39 +0100 Subject: [PATCH 095/240] Added a solution vector to the normalize unit test --- .../sparseMatrixImplementationTest.ml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 9e9633317d..17250cd074 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -13,8 +13,12 @@ module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) let normalize _ = - (* Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ)*) - let width = 4 in + (* + Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) + but extended by a solution vector b = [0;0;25]^T. + *) + + let width = 5 in let int x = D.of_int x in let any_matrix = Matrix.append_row @@ -25,7 +29,7 @@ let normalize _ = ) (Vector.of_sparse_list width [ (0, int 2); (1, int 3); (2, int 4) ]) ) - (Vector.of_sparse_list width [ (0, int 1); (1, int 1); (2, int 2); (3, int 4) ] + (Vector.of_sparse_list width [ (0, int 1); (1, int 1); (2, int 2); (3, int 4); (4, int 25)] ) in let normalized_matrix = @@ -33,11 +37,11 @@ let normalize _ = (Matrix.append_row (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0,int 1); (2,int 2) ]) + (Vector.of_sparse_list width [ (0,int 1); (2,int 2); (4, int 3)]) ) - (Vector.of_sparse_list width [ (1,int 1) ]) + (Vector.of_sparse_list width [ (1,int 1); (4, int (-2)) ]) ) - (Vector.of_sparse_list width [ (3,int 1) ] + (Vector.of_sparse_list width [ (3,int 1); (4, int 6)] ) in match Matrix.normalize any_matrix with From 18acca5cbeba2bf5d2920fde1bf8c848a8190c32 Mon Sep 17 00:00:00 2001 From: Havercake Date: Mon, 9 Dec 2024 16:36:16 +0100 Subject: [PATCH 096/240] Normalize test for a shuffeled matrix --- .../sparseMatrixImplementationTest.ml | 92 +++++++++++++------ 1 file changed, 65 insertions(+), 27 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 17250cd074..313f4d5231 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -12,43 +12,81 @@ module D = SharedFunctions.Mpqf module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) -let normalize _ = - (* - Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) - but extended by a solution vector b = [0;0;25]^T. - *) +(** This function runs the equality assertion with the solution after normalizing the matrix. *) +let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = + let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in + let do_dimensions_match dim1 dim2 = + match (dim1, dim2) with (r1, c1), (r2, c2) -> r1 == r2 && c1 == c2 + in + let matrix_dim = get_dimensions matrix in + let solution_dim = get_dimensions solution in + if not (do_dimensions_match solution_dim matrix_dim) then + failwith + "The matrix to normalize and the solution have different dimensions!" + else + match Matrix.normalize matrix with + | None -> + assert_failure "The matrix is normalizable but was not normalized!" + | Some reduced_matrix -> assert_equal reduced_matrix solution +(** + Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) + but extended by a solution vector b = [0;0;25]^T. +*) +let standard_normalize _ = let width = 5 in let int x = D.of_int x in let any_matrix = Matrix.append_row (Matrix.append_row - (Matrix.append_row - (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 2); (2, int 4); (3, int (-1)) ]) - ) - (Vector.of_sparse_list width [ (0, int 2); (1, int 3); (2, int 4) ]) - ) - (Vector.of_sparse_list width [ (0, int 1); (1, int 1); (2, int 2); (3, int 4); (4, int 25)] - ) + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width + [ (0, int 2); (2, int 4); (3, int (-1)) ])) + (Vector.of_sparse_list width [ (0, int 2); (1, int 3); (2, int 4) ])) + (Vector.of_sparse_list width + [ (0, int 1); (1, int 1); (2, int 2); (3, int 4); (4, int 25) ]) in let normalized_matrix = Matrix.append_row (Matrix.append_row - (Matrix.append_row - (Matrix.empty ()) - (Vector.of_sparse_list width [ (0,int 1); (2,int 2); (4, int 3)]) - ) - (Vector.of_sparse_list width [ (1,int 1); (4, int (-2)) ]) - ) - (Vector.of_sparse_list width [ (3,int 1); (4, int 6)] - ) + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (2, int 2); (4, int 3) ])) + (Vector.of_sparse_list width [ (1, int 1); (4, int (-2)) ])) + (Vector.of_sparse_list width [ (3, int 1); (4, int 6) ]) + in + normalize_and_assert any_matrix normalized_matrix + +let should_just_sort_normalize _ = + let width = 10 in + let int x = D.of_int x in + let chaotic_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (2, int 1) ])) + (Vector.of_sparse_list width [ (5, int 1) ])) + (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) + (Vector.of_sparse_list width [ (1, int 1); (4, int (-3)) ]) + in + + let sorted_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) + (Vector.of_sparse_list width [ (1, int 1); (4, int (-3)) ])) + (Vector.of_sparse_list width [ (2, int 1) ])) + (Vector.of_sparse_list width [ (5, int 1) ]) in - match Matrix.normalize any_matrix with - | None -> assert_failure "The matrix is normalizable but was not normalized!" - | Some reduced_matrix -> assert_equal reduced_matrix normalized_matrix + normalize_and_assert chaotic_matrix sorted_matrix -let tests = "SparseMatrixImplementationTest" >::: [ "normalize" >:: normalize ] +let tests = + "SparseMatrixImplementationTest" + >::: [ + "standard" >:: standard_normalize; + "should_sort" >:: should_just_sort_normalize; + ] -let () = - run_test_tt_main tests +let () = run_test_tt_main tests From 43e042f9c932d8ac10fa1b13bedc01ee10738c20 Mon Sep 17 00:00:00 2001 From: Havercake Date: Mon, 9 Dec 2024 16:48:57 +0100 Subject: [PATCH 097/240] Normalize test for row elimination --- .../sparseMatrixImplementationTest.ml | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 313f4d5231..85e813efa6 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -12,6 +12,8 @@ module D = SharedFunctions.Mpqf module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) +let int x = D.of_int x + (** This function runs the equality assertion with the solution after normalizing the matrix. *) let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in @@ -26,16 +28,15 @@ let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = else match Matrix.normalize matrix with | None -> - assert_failure "The matrix is normalizable but was not normalized!" + assert_failure "The matrix is normalizable but was not normalized!" | Some reduced_matrix -> assert_equal reduced_matrix solution (** - Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) - but extended by a solution vector b = [0;0;25]^T. + Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) + but extended by a solution vector b = [0;0;25]^T. *) let standard_normalize _ = let width = 5 in - let int x = D.of_int x in let any_matrix = Matrix.append_row (Matrix.append_row @@ -57,8 +58,7 @@ let standard_normalize _ = normalize_and_assert any_matrix normalized_matrix let should_just_sort_normalize _ = - let width = 10 in - let int x = D.of_int x in + let width = 7 in let chaotic_matrix = Matrix.append_row (Matrix.append_row @@ -82,11 +82,33 @@ let should_just_sort_normalize _ = in normalize_and_assert chaotic_matrix sorted_matrix +let should_eliminate_rows _ = + let width = 3 in + let linearly_dependent_rows = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (2, int 4) ])) + (Vector.of_sparse_list width [ (0, int 2); (2, int 8) ])) + (Vector.of_sparse_list width [ (0, int 3); (2, int 12) ]) + in + + let minimized_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (2, int 4) ])) + (Vector.zero_vec width)) + (Vector.zero_vec width) + in + normalize_and_assert linearly_dependent_rows minimized_matrix + let tests = "SparseMatrixImplementationTest" >::: [ - "standard" >:: standard_normalize; - "should_sort" >:: should_just_sort_normalize; - ] + "standard" >:: standard_normalize; + "should_sort" >:: should_just_sort_normalize; + "should_eliminate" >:: should_eliminate_rows; + ] let () = run_test_tt_main tests From ef07123f1137e41a30385f7c0ac447f9f036b317 Mon Sep 17 00:00:00 2001 From: Havercake Date: Mon, 9 Dec 2024 17:20:32 +0100 Subject: [PATCH 098/240] Normalize tests with different domains --- .../sparseMatrixImplementationTest.ml | 61 +++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 85e813efa6..14ccdf8c04 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -12,8 +12,14 @@ module D = SharedFunctions.Mpqf module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) +(** Shorthands for common functions. *) let int x = D.of_int x +let frac numerator denominator = D.of_frac numerator denominator + +(** Shorthands for common functions. *) +let float x = D.of_float x + (** This function runs the equality assertion with the solution after normalizing the matrix. *) let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in @@ -57,7 +63,10 @@ let standard_normalize _ = in normalize_and_assert any_matrix normalized_matrix -let should_just_sort_normalize _ = +(** + Normalization just sorts the matrix, as the rows are already reduced. +*) +let does_just_sort _ = let width = 7 in let chaotic_matrix = Matrix.append_row @@ -82,7 +91,10 @@ let should_just_sort_normalize _ = in normalize_and_assert chaotic_matrix sorted_matrix -let should_eliminate_rows _ = +(** + Normalization should eliminate both linearly dependent rows. +*) +let does_eliminate_dependent_rows _ = let width = 3 in let linearly_dependent_rows = Matrix.append_row @@ -103,12 +115,51 @@ let should_eliminate_rows _ = in normalize_and_assert linearly_dependent_rows minimized_matrix +let does_handle_floats _ = + let width = 3 in + let any_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, float 5.); (2, float (1. /. 2.)) ])) + (Vector.of_sparse_list width + [ (0, float (1. /. 4.)); (2, float 23.); (2, float 2.) ]) + in + + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, float 1.); (2, float (1. /. 10.)) ])) + (Vector.of_sparse_list width [ (2, float 1.); (2, float (79. /. 920.)) ]) + in + normalize_and_assert any_matrix normalized_matrix + +let does_handle_fractions _ = + let width = 3 in + let any_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, frac 5 1); (2, frac 1 2) ])) + (Vector.of_sparse_list width + [ (0, frac 1 4); (2, frac 23 1); (2, frac 2 1) ]) + in + + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, frac 1 1); (2, frac 1 10) ])) + (Vector.of_sparse_list width [ (2, frac 1 1); (2, frac 79 920) ]) + in + normalize_and_assert any_matrix normalized_matrix + let tests = "SparseMatrixImplementationTest" >::: [ - "standard" >:: standard_normalize; - "should_sort" >:: should_just_sort_normalize; - "should_eliminate" >:: should_eliminate_rows; + "can solve a standard normalization" >:: standard_normalize; + "does sort already reduzed" >:: does_just_sort; + "does eliminate dependent rows" >:: does_eliminate_dependent_rows; + (* Looks like deadlocking or inifinite execution when the bottom tests are activated. *) + (*"can handle float domain" >:: does_handle_floats;*) + (*"can handle fraction domain" >:: does_handle_fractions;*) ] let () = run_test_tt_main tests From 8d1c5485abe208ce80af1bb98fd196ed495a5277 Mon Sep 17 00:00:00 2001 From: Havercake Date: Mon, 9 Dec 2024 17:33:53 +0100 Subject: [PATCH 099/240] Normalize tests for idempotency and negation --- .../sparseMatrixImplementationTest.ml | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 14ccdf8c04..9f8a63b83c 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -151,15 +151,49 @@ let does_handle_fractions _ = in normalize_and_assert any_matrix normalized_matrix +let does_negate_negative _ = + let width = 5 in + let negative_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int (-1)); (3, int (-3)) ])) + (Vector.of_sparse_list width [ (2, int (-1)); (4, int (-5)) ]) + in + + let negated_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (3, int 3) ])) + (Vector.of_sparse_list width [ (2, int 1); (4, int 5) ]) + in + normalize_and_assert negative_matrix negated_matrix + +(** + Normalization is idempotent. +*) +let does_not_change_normalized_matrix _ = + let width = 5 in + let already_normalized = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) + (Vector.of_sparse_list width [ (1, int 1); (3, int 3) ])) + (Vector.of_sparse_list width [ (2, int 1); (3, int 1) ]) + in + normalize_and_assert already_normalized already_normalized + let tests = "SparseMatrixImplementationTest" >::: [ "can solve a standard normalization" >:: standard_normalize; "does sort already reduzed" >:: does_just_sort; "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - (* Looks like deadlocking or inifinite execution when the bottom tests are activated. *) + (* Looks like the tests are deadlock or inifinite execution when those are activated. *) (*"can handle float domain" >:: does_handle_floats;*) (*"can handle fraction domain" >:: does_handle_fractions;*) + "does negate negative matrix" >:: does_negate_negative; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; ] let () = run_test_tt_main tests From d71d7bde130bff32b930e5407504f5be27817b1b Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 10 Dec 2024 10:05:05 +0100 Subject: [PATCH 100/240] bugfix in add_empty_columns, behavious still differs from arraymatrix --- .../arrayImplementation/arrayMatrix.ml | 6 ++--- .../arrayImplementation/arrayVector.ml | 2 +- .../sparseImplementation/listMatrix.ml | 23 +++++++++++-------- .../sparseImplementation/sparseVector.ml | 4 ++-- src/cdomains/affineEquality/vector.ml | 2 +- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index b9bd503ddc..eec27c0c48 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -39,7 +39,7 @@ module ArrayMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m let add_empty_columns m cols = - let () = Printf.printf "Before add_empty_columns m:\n%s\n" (show m) in + let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> s ^ (Int.to_string x) ^ ",") cols "") in let nnc = Array.length cols in if is_empty m || nnc = 0 then m else let nr, nc = num_rows m, num_cols m in @@ -82,7 +82,7 @@ module ArrayMatrix: AbstractMatrix = Array.blit m (n + 1) new_matrix n (num_rows new_matrix - n)); new_matrix let get_col m n = - let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)))) in + (*let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)))) in*) V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)) let get_col m n = Timing.wrap "get_col" (get_col m) n @@ -286,7 +286,7 @@ module ArrayMatrix: AbstractMatrix = match rref_vec_with m' v' with | Some res -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in Some (remove_zero_rows res) - | None -> None + | None -> let () = Printf.printf "After rref_vec there is no normalization\n" in None let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 3bf873df78..622a12e328 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -36,7 +36,7 @@ module ArrayVector: AbstractVector = let remove_at_indices v idx = failwith "TODO" - let insert_zero_at_indices v idx = failwith "TODO" + let insert_zero_at_indices v idx count = failwith "TODO" let set_nth_with v n new_val = if n >= Array.length v then failwith "n outside of Array range" else diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 3c67dfec02..ee200f1923 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -39,18 +39,21 @@ module ListMatrix: AbstractMatrix = Timing.wrap "copy" (copy) m let add_empty_columns m cols = - let () = Printf.printf "Before add_empty_columns m:\n%s\n" (show m) in + let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> s ^ (Int.to_string x) ^ ",") cols "") in let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in - let rec count_sorted_occ acc cols last count = + let rec count_sorted_occ acc cols last count = match cols with - | [] -> acc - | (x :: xs) when x = last -> count_sorted_occ acc xs x (count + 1) - | (x :: xs) -> count_sorted_occ ((last, count) :: acc) xs x 1 + | [] -> if count > 0 then (last, count) :: acc else acc + | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) + | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in + count_sorted_occ acc xs x 1 in - let occ_cols = count_sorted_occ [] sorted_cols (-1) 0 in - let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols) m)) in - List.map (fun row -> V.insert_zero_at_indices row occ_cols) m + let occ_cols = List.rev @@ count_sorted_occ [] sorted_cols 0 0 in + (*let () = Printf.printf "sorted cols is: %s\n" (List.fold_right (fun x s -> (Int.to_string x) ^ s) sorted_cols "") in + let () = Printf.printf "sorted_occ is: %s\n" (List.fold_right (fun (i, count) s -> "(" ^ (Int.to_string i) ^ "," ^ (Int.to_string count) ^ ")" ^ s) occ_cols "") in*) + let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m)) in + List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols @@ -68,7 +71,7 @@ module ListMatrix: AbstractMatrix = List.remove_at n m let get_col m n = - let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_list @@ List.map (fun row -> V.nth row n) m)) in + (*let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_list @@ List.map (fun row -> V.nth row n) m)) in*) V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) let get_col m n = @@ -246,7 +249,7 @@ module ListMatrix: AbstractMatrix = match normalize @@ append_matrices m (init_with_vec v) with | Some res -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in Some (remove_zero_rows res) - | None -> None + | None -> let () = Printf.printf "After rref_vec there is no normalization\n " in None (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 76646527ed..51753475e6 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -80,7 +80,7 @@ module SparseVector: AbstractVector = in {entries = remove_indices_helper v.entries idx 0; len = v.len - List.length idx} - let insert_zero_at_indices v idx = + let insert_zero_at_indices v idx count = let rec add_indices_helper vec idx added_count = match vec, idx with | [], [] -> [] @@ -90,7 +90,7 @@ module SparseVector: AbstractVector = | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> (col_idx + added_count + count, value) :: add_indices_helper xs ys (added_count + count) | ((col_idx, value) :: xs), ((i, count) :: ys) -> (col_idx + added_count, value) :: add_indices_helper xs idx added_count in - {entries = add_indices_helper v.entries idx 0; len = v.len + List.length idx} + {entries = add_indices_helper v.entries idx 0; len = v.len + count} let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 15215b5512..f52f6eadbb 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -12,7 +12,7 @@ sig val remove_at_indices: t -> int list -> t - val insert_zero_at_indices: t -> (int * int) list -> t + val insert_zero_at_indices: t -> (int * int) list -> int -> t val set_nth: t -> int -> num -> t From db97f30245e47d06096e2d3d2156cfeca08f4dda Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 10 Dec 2024 12:51:48 +0100 Subject: [PATCH 101/240] add_emtpy_cols uses arraymatrix logic here + bugfix in normalize - one test still missing --- .../apron/affineEqualityAnalysis.apron.ml | 2 +- .../arrayImplementation/arrayMatrix.ml | 8 +-- .../sparseImplementation/listMatrix.ml | 54 ++++++++++++++----- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index e262b2653b..80d3b32874 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -14,7 +14,7 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in + let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index eec27c0c48..7d640a7bdc 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -39,7 +39,7 @@ module ArrayMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m let add_empty_columns m cols = - let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> s ^ (Int.to_string x) ^ ",") cols "") in + let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in let nnc = Array.length cols in if is_empty m || nnc = 0 then m else let nr, nc = num_rows m, num_cols m in @@ -284,7 +284,7 @@ module ArrayMatrix: AbstractMatrix = let m' = copy m in let v' = V.copy v in match rref_vec_with m' v' with - | Some res -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in + | Some res -> let () = Printf.printf "After rref_vec, before removing zero rows, we have m:\n%s\n" (show res) in Some (remove_zero_rows res) | None -> let () = Printf.printf "After rref_vec there is no normalization\n" in None @@ -312,7 +312,9 @@ module ArrayMatrix: AbstractMatrix = let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in let m1' = copy m1 in let m2' = copy m2 in - rref_matrix_with m1' m2' + match rref_matrix_with m1' m2' with + | Some m -> let () = Printf.printf "After rref_matrix m:\n %s\n" (show m) in Some m + | None -> let () = Printf.printf "No normalization for rref_matrix found" in None let is_covered_by m1 m2 = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index ee200f1923..6264dce9d6 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -38,22 +38,50 @@ module ListMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m - let add_empty_columns m cols = - let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> s ^ (Int.to_string x) ^ ",") cols "") in + (* This uses the logic from ArrayMatrix to add empty_columns*) + let add_empty_columns (m : t) (cols : int array) : t = + let nr = num_rows m in + let nc = if nr = 0 then 0 else num_cols m in + let nnc = Array.length cols in + + (* If no rows or no new columns, just return m as is *) + if nr = 0 || nnc = 0 then m + else + (* Create a new list of rows with additional columns. *) + let new_rows = + List.map (fun row -> + let old_row_arr = V.to_array row in + let new_row_arr = Array.make (nc + nnc) A.zero in + + let offset = ref 0 in + for j = 0 to nc - 1 do + (* Check if we need to insert zero columns before placing old_row_arr.(j) *) + while !offset < nnc && !offset + j = cols.(!offset) do + incr offset + done; + new_row_arr.(j + !offset) <- old_row_arr.(j); + done; + + V.of_array new_row_arr + ) m + in + + new_rows + (*let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in let rec count_sorted_occ acc cols last count = - match cols with - | [] -> if count > 0 then (last, count) :: acc else acc - | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) - | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in - count_sorted_occ acc xs x 1 + match cols with + | [] -> if count > 0 then (last, count) :: acc else acc + | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) + | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in + count_sorted_occ acc xs x 1 in let occ_cols = List.rev @@ count_sorted_occ [] sorted_cols 0 0 in (*let () = Printf.printf "sorted cols is: %s\n" (List.fold_right (fun x s -> (Int.to_string x) ^ s) sorted_cols "") in - let () = Printf.printf "sorted_occ is: %s\n" (List.fold_right (fun (i, count) s -> "(" ^ (Int.to_string i) ^ "," ^ (Int.to_string count) ^ ")" ^ s) occ_cols "") in*) + let () = Printf.printf "sorted_occ is: %s\n" (List.fold_right (fun (i, count) s -> "(" ^ (Int.to_string i) ^ "," ^ (Int.to_string count) ^ ")" ^ s) occ_cols "") in*) let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m)) in - List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m + List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m*) let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols @@ -220,7 +248,7 @@ module ListMatrix: AbstractMatrix = in List.for_all row_is_valid m in let rec main_loop m m' row_idx col_idx = - if col_idx = (col_count - 2) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) + if col_idx >= (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else match find_first_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized*) @@ -247,7 +275,7 @@ module ListMatrix: AbstractMatrix = let rref_vec m v = let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in match normalize @@ append_matrices m (init_with_vec v) with - | Some res -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in + | Some res -> let () = Printf.printf "After rref_vec, before removing zero rows, we have m:\n%s\n" (show res) in Some (remove_zero_rows res) | None -> let () = Printf.printf "After rref_vec there is no normalization\n " in None @@ -256,7 +284,9 @@ module ListMatrix: AbstractMatrix = (*TODO: OPTIMIZE!*) let rref_matrix m1 m2 = let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in - normalize @@ append_matrices m1 m2 + match normalize @@ append_matrices m1 m2 with + | Some m -> let () = Printf.printf "After rref_matrix m, before removing zero rows:\n %s\n" (show m) in Some (remove_zero_rows m) + | None -> let () = Printf.printf "No normalization for rref_matrix found" in None let delete_row_with_pivots row pivots m2 = From 315dac61fa1e11bb934194d74698849f44b9a834 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 10 Dec 2024 13:54:07 +0100 Subject: [PATCH 102/240] appending and normalizing in is_covered_by - all tests pass --- .../arrayImplementation/arrayMatrix.ml | 6 +-- .../sparseImplementation/listMatrix.ml | 39 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 7d640a7bdc..4e2d0f6e5e 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -57,14 +57,12 @@ module ArrayMatrix: AbstractMatrix = let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - let () = Printf.printf "Before append_row m:\n%s\n" (show m) in let size = num_rows m in let new_matrix = Array.make_matrix (size + 1) (num_cols m) A.zero in for i = 0 to size - 1 do new_matrix.(i) <- m.(i) done; new_matrix.(size) <- V.to_array row; - let () = Printf.printf "After append_row m:\n%s\n" (show new_matrix) in new_matrix let get_row m n = @@ -319,12 +317,12 @@ module ArrayMatrix: AbstractMatrix = let is_covered_by m1 m2 = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) (*Both input matrices must be in rref form!*) + let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in if num_rows m1 > num_rows m2 then false else - let m1' = copy m1 in - let m2' = copy m2 in let p2 = lazy (get_pivot_positions m2) in try ( for i = 0 to num_rows m1 - 1 do + (* check if there are rows in m1 and m2 that aren't equal *) if Array.exists2 (<>:) m1.(i) m2.(i) then let m1_i = Array.copy m1.(i) in for j = 0 to Array.length m1_i - 2 do diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6264dce9d6..5b12192a4c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -87,8 +87,6 @@ module ListMatrix: AbstractMatrix = Timing.wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = - let () = Printf.printf "Before append_row m:\n%s\n" (show m) in - let () = Printf.printf "After append_row m:\n%s\n" (show ( m @ [row])) in m @ [row] let get_row m n = @@ -305,23 +303,28 @@ module ListMatrix: AbstractMatrix = is_linearly_independent_rref new_v xs let is_covered_by m1 m2 = + Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2); + match normalize @@ append_matrices m2 m1 with + | None -> false + | Some m -> let m2' = remove_zero_rows m in List.for_all2 (fun x y -> V.equal x y) m2 m2' + (*let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in if num_rows m1 > num_rows m2 then false else - let rec is_covered_by_helper m1 m2 = - match m1 with - | [] -> true - | v1::vs1 -> - let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in - match first_non_zero with - | None -> true (* vs1 must also be zero-vectors because of rref *) - | Some (idx, _) -> - let m' = List.drop_while (fun v2 -> - match V.findi_val_opt ((<>:) A.zero) v2 with - | None -> true (* In this case, m2 only has zero rows after that *) - | Some (idx', _) -> idx' < idx - ) m2 in (* Only consider the part of m2 where the pivot is at a position useful for deleting first_non_zero of v1*) - let linearly_indep = is_linearly_independent_rref v1 m' in - if linearly_indep then false else is_covered_by_helper vs1 m' - in is_covered_by_helper m1 m2 + let rec is_covered_by_helper m1 m2 = + match m1 with + | [] -> true + | v1::vs1 -> + let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in + match first_non_zero with + | None -> true (* vs1 must also be zero-vectors because of rref *) + | Some (idx, _) -> + let m' = List.drop_while (fun v2 -> + match V.findi_val_opt ((<>:) A.zero) v2 with + | None -> true (* In this case, m2 only has zero rows after that *) + | Some (idx', _) -> idx' < idx + ) m2 in (* Only consider the part of m2 where the pivot is at a position useful for deleting first_non_zero of v1*) + let linearly_indep = is_linearly_independent_rref v1 m' in + if linearly_indep then false else is_covered_by_helper vs1 m' + in is_covered_by_helper m1 m2*) let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 From 58e34c0128d4bb08e2306ab1952c6caa0f46bb21 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 10 Dec 2024 15:45:56 +0100 Subject: [PATCH 103/240] Normalize tests for empty matrix, two column matrix and a normalized matrix with rationals --- .../sparseMatrixImplementationTest.ml | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 9f8a63b83c..edd4d51261 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -183,6 +183,54 @@ let does_not_change_normalized_matrix _ = in normalize_and_assert already_normalized already_normalized +(** + Normalization works on an empty matrix. +*) +let normalize_empty _ = + let width = 3 in + let empty_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) (Vector.zero_vec width)) + (Vector.zero_vec width)) + (Vector.zero_vec width) + in + normalize_and_assert empty_matrix empty_matrix + +let normalize_two_columns _ = + let width = 2 in + let two_col_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 3); (1, int 2) ])) + (Vector.of_sparse_list width [ (0, int 9); (1, int 6) ]) + in + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width + [ (0, int 1); (1, D.div (int 2) (int 3)) ])) + (Vector.of_sparse_list width []) + in + normalize_and_assert two_col_matrix normalized_matrix + +let int_domain_to_rational _ = + let width = 3 in + let int_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 3); (2, int 1) ])) + (Vector.of_sparse_list width [ (0, int 2); (1, int 1); (2, int 1) ]) + in + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width + [ (0, int 1); (2, D.div (int 1) (int 3)) ])) + (Vector.of_sparse_list width [ (1, int 1); (2, D.div (int 1) (int 3)) ]) + in + normalize_and_assert int_matrix normalized_matrix + let tests = "SparseMatrixImplementationTest" >::: [ @@ -193,7 +241,11 @@ let tests = (*"can handle float domain" >:: does_handle_floats;*) (*"can handle fraction domain" >:: does_handle_fractions;*) "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" >:: does_not_change_normalized_matrix; + "does not change already normalized matrix" + >:: does_not_change_normalized_matrix; + "does not change an empty matrix" >:: normalize_empty; + "can correctly normalize a two column matrix" >:: normalize_two_columns; + "can handle a rational solution" >:: int_domain_to_rational; ] let () = run_test_tt_main tests From 9f7cec947dee59627c44b1ed1dc5d2658f9f66a6 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 10 Dec 2024 15:48:07 +0100 Subject: [PATCH 104/240] Added a newline --- .../sparseImplementation/sparseMatrixImplementationTest.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index edd4d51261..7d3ffb48d8 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -241,8 +241,7 @@ let tests = (*"can handle float domain" >:: does_handle_floats;*) (*"can handle fraction domain" >:: does_handle_fractions;*) "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" - >:: does_not_change_normalized_matrix; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; "does not change an empty matrix" >:: normalize_empty; "can correctly normalize a two column matrix" >:: normalize_two_columns; "can handle a rational solution" >:: int_domain_to_rational; From 6673aae4635b3e63765b6a9eabfc5161c174075f Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 10 Dec 2024 15:50:23 +0100 Subject: [PATCH 105/240] Changed the assert failure text for when the normalization fails --- .../sparseImplementation/sparseMatrixImplementationTest.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 7d3ffb48d8..08318ec9bc 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -33,8 +33,7 @@ let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = "The matrix to normalize and the solution have different dimensions!" else match Matrix.normalize matrix with - | None -> - assert_failure "The matrix is normalizable but was not normalized!" + | None -> assert_failure "The normalization returned None." | Some reduced_matrix -> assert_equal reduced_matrix solution (** From fe984fb0b857253342a8564cd4dae0cc1588950c Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 10 Dec 2024 15:53:12 +0100 Subject: [PATCH 106/240] Add some is_covered_by tests --- .../sparseMatrixImplementationTest.ml | 90 ++++++++++++++++--- 1 file changed, 78 insertions(+), 12 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 9f8a63b83c..ef4cbf1236 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -20,6 +20,12 @@ let frac numerator denominator = D.of_frac numerator denominator (** Shorthands for common functions. *) let float x = D.of_float x +let make_matrix_of_2d_list l = + List.fold_left + (fun acc row -> Matrix.append_row acc (Vector.of_list row)) + (Matrix.empty ()) + l + (** This function runs the equality assertion with the solution after normalizing the matrix. *) let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in @@ -183,17 +189,77 @@ let does_not_change_normalized_matrix _ = in normalize_and_assert already_normalized already_normalized -let tests = - "SparseMatrixImplementationTest" - >::: [ - "can solve a standard normalization" >:: standard_normalize; - "does sort already reduzed" >:: does_just_sort; - "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - (* Looks like the tests are deadlock or inifinite execution when those are activated. *) - (*"can handle float domain" >:: does_handle_floats;*) - (*"can handle fraction domain" >:: does_handle_fractions;*) - "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" >:: does_not_change_normalized_matrix; - ] +let is_covered_by_simple _ = + let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 1; int 2; int 10]) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 1; int 0; int 6])) + (Vector.of_list [int 0; int 0; int 1; int 2]) in + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" result + +let is_covered_by_vector_first_row _ = + let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 2; int 0; int 7]) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 2; int 0; int 7])) + (Vector.of_list [int 0; int 0; int 1; int 2]) in + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" result + +let is_zero_vec_covered _ = + let m1 = Matrix.init_with_vec (Vector.zero_vec 4) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 2; int 0; int 7])) + (Vector.of_list [int 0; int 0; int 1; int 2]) in + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" result + +let is_not_covered _ = + let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 1; int 2; int 10]) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 1; int 0; int 6])) + (Vector.of_list [int 0; int 0; int 1; int 3]) in + let result = Matrix.is_covered_by m2 m1 in + assert_bool "Matrix m1 is not covered by m2, but was true" (not result) + +let is_covered_big _ = + let m1 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int (-1); int 0]; + [int 0; int 1; int 0; int 0; int 0; int (-2); int 0]; + [int 0; int 0; int 1; (frac (-1) 3); frac 1 3; int 0; frac 1 3]] in + + let m2 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 0; int 1; frac (-1) 3; frac 1 3; int 0; frac 1 3]; + [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in + + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" (result) + + let tests = + "SparseMatrixImplementationTest" + >::: [ + "can solve a standard normalization" >:: standard_normalize; + "does sort already reduzed" >:: does_just_sort; + "does eliminate dependent rows" >:: does_eliminate_dependent_rows; + (* Looks like the tests are deadlock or inifinite execution when those are activated. *) + (*"can handle float domain" >:: does_handle_floats;*) + (*"can handle fraction domain" >:: does_handle_fractions;*) + "does negate negative matrix" >:: does_negate_negative; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; + "m1 is covered by m2" >:: is_covered_by_simple; + "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; + "zero vector is covered by m2" >:: is_zero_vec_covered; + "m1 is not covered by m2" >:: is_not_covered; + "m1 is covered by m2 with big matrix" >:: is_covered_big; + ] let () = run_test_tt_main tests From f44f2eb861fbebab81862b300d3f60165b68dade Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 10 Dec 2024 15:53:36 +0100 Subject: [PATCH 107/240] Formatting --- .../sparseMatrixImplementationTest.ml | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index ef4cbf1236..c3c94c8d08 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -241,25 +241,25 @@ let is_covered_big _ = [int 0; int 0; int 1; frac (-1) 3; frac 1 3; int 0; frac 1 3]; [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in - let result = Matrix.is_covered_by m1 m2 in - assert_bool "Matrix m1 is covered by m2, but was false" (result) + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" (result) - let tests = - "SparseMatrixImplementationTest" - >::: [ - "can solve a standard normalization" >:: standard_normalize; - "does sort already reduzed" >:: does_just_sort; - "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - (* Looks like the tests are deadlock or inifinite execution when those are activated. *) - (*"can handle float domain" >:: does_handle_floats;*) - (*"can handle fraction domain" >:: does_handle_fractions;*) - "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" >:: does_not_change_normalized_matrix; - "m1 is covered by m2" >:: is_covered_by_simple; - "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; - "zero vector is covered by m2" >:: is_zero_vec_covered; - "m1 is not covered by m2" >:: is_not_covered; - "m1 is covered by m2 with big matrix" >:: is_covered_big; - ] +let tests = + "SparseMatrixImplementationTest" + >::: [ + "can solve a standard normalization" >:: standard_normalize; + "does sort already reduzed" >:: does_just_sort; + "does eliminate dependent rows" >:: does_eliminate_dependent_rows; + (* Looks like the tests are deadlock or inifinite execution when those are activated. *) + (*"can handle float domain" >:: does_handle_floats;*) + (*"can handle fraction domain" >:: does_handle_fractions;*) + "does negate negative matrix" >:: does_negate_negative; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; + "m1 is covered by m2" >:: is_covered_by_simple; + "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; + "zero vector is covered by m2" >:: is_zero_vec_covered; + "m1 is not covered by m2" >:: is_not_covered; + "m1 is covered by m2 with big matrix" >:: is_covered_big; + ] let () = run_test_tt_main tests From 79f890a9ac0488921c69dbe4eb35af2433bfa59d Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 10 Dec 2024 15:53:51 +0100 Subject: [PATCH 108/240] Added some comments on the test setup --- tests/unit/mainTest.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit/mainTest.ml b/tests/unit/mainTest.ml index 4fd65f6736..b8be9ef8f0 100644 --- a/tests/unit/mainTest.ml +++ b/tests/unit/mainTest.ml @@ -14,10 +14,12 @@ let all_tests = (* etc *) "domaintest" >::: QCheck_ounit.to_ounit2_test_list Maindomaintest.all_testsuite; IntOpsTest.tests; + (* SparseMatrixImplementationTest.tests; *) (* Uncomment this to add the sparse matrix tests to all tests *) ] let subset_tests = "" >::: [SparseMatrixImplementationTest.tests] let () = print_string "\027[0;1munit: \027[0;0;00m"; - run_test_tt_main subset_tests + run_test_tt_main subset_tests (* Remove this and uncomment the line below to run all tests.*) + (* run_test_tt_main all_tests *) From 4b34fda53588d5bb64ee8e5dbaf5b3782bb915e1 Mon Sep 17 00:00:00 2001 From: Havercake Date: Tue, 10 Dec 2024 15:54:03 +0100 Subject: [PATCH 109/240] Added some comments on the test setup --- tests/unit/mainTest.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/mainTest.ml b/tests/unit/mainTest.ml index b8be9ef8f0..9527679fe7 100644 --- a/tests/unit/mainTest.ml +++ b/tests/unit/mainTest.ml @@ -22,4 +22,4 @@ let subset_tests = "" >::: [SparseMatrixImplementationTest.tests] let () = print_string "\027[0;1munit: \027[0;0;00m"; run_test_tt_main subset_tests (* Remove this and uncomment the line below to run all tests.*) - (* run_test_tt_main all_tests *) +(* run_test_tt_main all_tests *) From 1241795438b11c651fda57a42a22d134ab3673a7 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 10 Dec 2024 17:31:21 +0100 Subject: [PATCH 110/240] bugfix in insert_zeros and use list funtionality again, uses apron standard for dim_add array now --- .../arrayImplementation/arrayMatrix.ml | 1 + .../sparseImplementation/listMatrix.ml | 37 ++----------------- .../sparseImplementation/sparseVector.ml | 2 +- .../apron/affineEqualityDomain.apron.ml | 3 +- 4 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 4e2d0f6e5e..a3d1199be9 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -40,6 +40,7 @@ module ArrayMatrix: AbstractMatrix = let add_empty_columns m cols = let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in + Array.modifyi (+) cols; let nnc = Array.length cols in if is_empty m || nnc = 0 then m else let nr, nc = num_rows m, num_cols m in diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 5b12192a4c..9a0aef5f5e 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -38,36 +38,9 @@ module ListMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m - (* This uses the logic from ArrayMatrix to add empty_columns*) - let add_empty_columns (m : t) (cols : int array) : t = - let nr = num_rows m in - let nc = if nr = 0 then 0 else num_cols m in - let nnc = Array.length cols in - - (* If no rows or no new columns, just return m as is *) - if nr = 0 || nnc = 0 then m - else - (* Create a new list of rows with additional columns. *) - let new_rows = - List.map (fun row -> - let old_row_arr = V.to_array row in - let new_row_arr = Array.make (nc + nnc) A.zero in - - let offset = ref 0 in - for j = 0 to nc - 1 do - (* Check if we need to insert zero columns before placing old_row_arr.(j) *) - while !offset < nnc && !offset + j = cols.(!offset) do - incr offset - done; - new_row_arr.(j + !offset) <- old_row_arr.(j); - done; - - V.of_array new_row_arr - ) m - in - - new_rows - (*let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in + (* This only works if Array.modifyi has been removed from dim_add *) + let add_empty_columns (m : t) (cols : int array) : t = + let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in let rec count_sorted_occ acc cols last count = @@ -78,10 +51,8 @@ module ListMatrix: AbstractMatrix = count_sorted_occ acc xs x 1 in let occ_cols = List.rev @@ count_sorted_occ [] sorted_cols 0 0 in - (*let () = Printf.printf "sorted cols is: %s\n" (List.fold_right (fun x s -> (Int.to_string x) ^ s) sorted_cols "") in - let () = Printf.printf "sorted_occ is: %s\n" (List.fold_right (fun (i, count) s -> "(" ^ (Int.to_string i) ^ "," ^ (Int.to_string count) ^ ")" ^ s) occ_cols "") in*) let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m)) in - List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m*) + List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 51753475e6..9459db70a0 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -87,7 +87,7 @@ module SparseVector: AbstractVector = | [], (y :: ys) -> [] (* inserting at the end only means changing the dimension *) | ((col_idx, value) :: xs), [] -> (col_idx + added_count, value) :: add_indices_helper xs [] added_count | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) - | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> (col_idx + added_count + count, value) :: add_indices_helper xs ys (added_count + count) + | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> add_indices_helper vec ys (added_count + count) | ((col_idx, value) :: xs), ((i, count) :: ys) -> (col_idx + added_count, value) :: add_indices_helper xs idx added_count in {entries = add_indices_helper v.entries idx 0; len = v.len + count} diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 5a666f728b..8df5994c9c 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -26,8 +26,7 @@ module AffineEqualityMatrix (Vec: AbstractVector) (Mx: AbstractMatrix) = struct include Mx(Mpqf) (Vec) let dim_add (ch: Apron.Dim.change) m = - Array.modifyi (+) ch.dim; - add_empty_columns m ch.dim + add_empty_columns m ch.dim let dim_add ch m = Timing.wrap "dim add" (dim_add ch) m From 091b9fa10c6e7a53f66941c9b0569a620cf66fe3 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 10 Dec 2024 17:47:45 +0100 Subject: [PATCH 111/240] coveredddd --- .../sparseImplementation/listMatrix.ml | 42 ++++++++----------- .../sparseImplementation/sparseVector.ml | 1 + .../sparseMatrixImplementationTest.ml | 14 +++++++ 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 9a0aef5f5e..7b26b6ac00 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -257,28 +257,27 @@ module ListMatrix: AbstractMatrix = | Some m -> let () = Printf.printf "After rref_matrix m, before removing zero rows:\n %s\n" (show m) in Some (remove_zero_rows m) | None -> let () = Printf.printf "No normalization for rref_matrix found" in None - let delete_row_with_pivots row pivots m2 = failwith "TODO" - (* Assumes that the first row of the matrix is already the pivot row fitting to the vector. *) - let rec is_linearly_independent_rref v m = - match m with - | [] -> not @@ V.is_zero_vec v - | x::xs -> + let is_covered_by m1 m2 = + let rec is_linearly_independent_rref v m = let pivot_opt = V.findi_val_opt ((<>:) A.zero) v in match pivot_opt with | None -> false (* When we found no pivot, the vector is already A.zero. *) | Some (pivot_id, pivot) -> - let new_v = V.map2_f_preserves_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in - is_linearly_independent_rref new_v xs - - let is_covered_by m1 m2 = - Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2); - match normalize @@ append_matrices m2 m1 with - | None -> false - | Some m -> let m2' = remove_zero_rows m in List.for_all2 (fun x y -> V.equal x y) m2 m2' - (*let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in + let m' = List.drop_while (fun v2 -> + match V.findi_val_opt ((<>:) A.zero) v2 with + | None -> true (* In this case, m2 only has zero rows after that *) + | Some (idx', _) -> idx' < pivot_id + ) m in + match m' with + | [] -> not @@ V.is_zero_vec v + | x::xs -> + let new_v = V.map2_f_preserves_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in + is_linearly_independent_rref new_v m' + in + let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in if num_rows m1 > num_rows m2 then false else let rec is_covered_by_helper m1 m2 = match m1 with @@ -288,15 +287,10 @@ module ListMatrix: AbstractMatrix = match first_non_zero with | None -> true (* vs1 must also be zero-vectors because of rref *) | Some (idx, _) -> - let m' = List.drop_while (fun v2 -> - match V.findi_val_opt ((<>:) A.zero) v2 with - | None -> true (* In this case, m2 only has zero rows after that *) - | Some (idx', _) -> idx' < idx - ) m2 in (* Only consider the part of m2 where the pivot is at a position useful for deleting first_non_zero of v1*) - let linearly_indep = is_linearly_independent_rref v1 m' in - if linearly_indep then false else is_covered_by_helper vs1 m' - in is_covered_by_helper m1 m2*) - + let linearly_indep = is_linearly_independent_rref v1 m2 in + if linearly_indep then false else is_covered_by_helper vs1 m2 + in is_covered_by_helper m1 m2 + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 9459db70a0..2fc3e16e5f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -191,6 +191,7 @@ module SparseVector: AbstractVector = fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) (* Returns optional of (index * value) where f value evaluated to true *) + (*Can be optimized, dont check every zero cell*) let findi_val_opt f v = let rec find_zero_or_val vec last_col_idx = match vec, last_col_idx with diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 22bcae134e..69eae4211b 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -243,6 +243,18 @@ let is_covered_big _ = let result = Matrix.is_covered_by m1 m2 in assert_bool "Matrix m1 is covered by m2, but was false" (result) +let is_covered_big2 _ = + let m1 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 1; int 0] + ] in + + let m2 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in + + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" (result) (** Normalization works on an empty matrix. *) @@ -310,6 +322,8 @@ let tests = "does not change an empty matrix" >:: normalize_empty; "can correctly normalize a two column matrix" >:: normalize_two_columns; "can handle a rational solution" >:: int_domain_to_rational; + "m1 is covered by m2 with big matrix2" >:: is_covered_big2; + ] let () = run_test_tt_main tests From a7a4e1444efffb4d707b345403e91c205255785d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 12 Dec 2024 15:07:19 +0100 Subject: [PATCH 112/240] Fix normalize tests for floating point and fraction --- .../sparseImplementation/listMatrix.ml | 1 + .../sparseMatrixImplementationTest.ml | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 7b26b6ac00..d7a280fa8f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -142,6 +142,7 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: s *: y) row v) ) m + let del_col m j = if num_cols m = 1 then empty () else diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 69eae4211b..0fe269d15e 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -127,14 +127,14 @@ let does_handle_floats _ = (Matrix.append_row (Matrix.empty ()) (Vector.of_sparse_list width [ (0, float 5.); (2, float (1. /. 2.)) ])) (Vector.of_sparse_list width - [ (0, float (1. /. 4.)); (2, float 23.); (2, float 2.) ]) + [ (0, float (1. /. 4.)); (1, float 23.); (2, float 2.) ]) in let normalized_matrix = Matrix.append_row (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, float 1.); (2, float (1. /. 10.)) ])) - (Vector.of_sparse_list width [ (2, float 1.); (2, float (79. /. 920.)) ]) + (Vector.of_sparse_list width [ (0, float 1.); (2, frac 1 10) ])) + (Vector.of_sparse_list width [ (1, float 1.); (2, frac 79 920) ]) in normalize_and_assert any_matrix normalized_matrix @@ -145,14 +145,14 @@ let does_handle_fractions _ = (Matrix.append_row (Matrix.empty ()) (Vector.of_sparse_list width [ (0, frac 5 1); (2, frac 1 2) ])) (Vector.of_sparse_list width - [ (0, frac 1 4); (2, frac 23 1); (2, frac 2 1) ]) + [ (0, frac 1 4); (1, frac 23 1); (2, frac 2 1) ]) in let normalized_matrix = Matrix.append_row (Matrix.append_row (Matrix.empty ()) (Vector.of_sparse_list width [ (0, frac 1 1); (2, frac 1 10) ])) - (Vector.of_sparse_list width [ (2, frac 1 1); (2, frac 79 920) ]) + (Vector.of_sparse_list width [ (1, frac 1 1); (2, frac 79 920) ]) in normalize_and_assert any_matrix normalized_matrix @@ -246,7 +246,7 @@ let is_covered_big _ = let is_covered_big2 _ = let m1 = make_matrix_of_2d_list @@ [[int 1; int 0; int 0; int 0; int 0; int 1; int 0] - ] in + ] in let m2 = make_matrix_of_2d_list @@ [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; @@ -309,9 +309,8 @@ let tests = "can solve a standard normalization" >:: standard_normalize; "does sort already reduzed" >:: does_just_sort; "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - (* Looks like the tests are deadlock or inifinite execution when those are activated. *) - (*"can handle float domain" >:: does_handle_floats;*) - (*"can handle fraction domain" >:: does_handle_fractions;*) + "can handle float domain" >:: does_handle_floats; + "can handle fraction domain" >:: does_handle_fractions; "does negate negative matrix" >:: does_negate_negative; "does not change already normalized matrix" >:: does_not_change_normalized_matrix; "m1 is covered by m2" >:: is_covered_by_simple; @@ -323,7 +322,6 @@ let tests = "can correctly normalize a two column matrix" >:: normalize_two_columns; "can handle a rational solution" >:: int_domain_to_rational; "m1 is covered by m2 with big matrix2" >:: is_covered_big2; - ] let () = run_test_tt_main tests From b15b9d2dfec55c8ce7df595ce6c55468ab4a2c99 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 12 Dec 2024 15:15:51 +0100 Subject: [PATCH 113/240] small tweak in findi_val_opt, could be even a tini tiny bit faster but not much --- .../affineEquality/sparseImplementation/sparseVector.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 2fc3e16e5f..1b31bfe2c7 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -194,10 +194,11 @@ module SparseVector: AbstractVector = (*Can be optimized, dont check every zero cell*) let findi_val_opt f v = let rec find_zero_or_val vec last_col_idx = - match vec, last_col_idx with - | [], _ -> if f A.zero && v.len <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else None - | (idx, value) :: xs, i -> - if f A.zero && idx <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) + let f0 = f A.zero in + match vec with + | [] -> if f0 && v.len <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else None + | (idx, value) :: xs -> + if f0 && idx <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else if f value then Some (idx, value) else find_zero_or_val xs idx in find_zero_or_val v.entries (-1) From 0f6509b0fac50563d8629f2c6a8dcd824711df99 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 12 Dec 2024 15:42:54 +0100 Subject: [PATCH 114/240] removed prints for benchmarking --- .../sparseImplementation/listMatrix.ml | 48 ++++--------------- .../apron/affineEqualityDomain.apron.ml | 22 ++------- 2 files changed, 13 insertions(+), 57 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 7b26b6ac00..d43e858138 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -40,18 +40,16 @@ module ListMatrix: AbstractMatrix = (* This only works if Array.modifyi has been removed from dim_add *) let add_empty_columns (m : t) (cols : int array) : t = - let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in let rec count_sorted_occ acc cols last count = - match cols with - | [] -> if count > 0 then (last, count) :: acc else acc - | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) - | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in - count_sorted_occ acc xs x 1 + match cols with + | [] -> if count > 0 then (last, count) :: acc else acc + | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) + | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in + count_sorted_occ acc xs x 1 in let occ_cols = List.rev @@ count_sorted_occ [] sorted_cols 0 0 in - let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m)) in List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m let add_empty_columns m cols = @@ -64,7 +62,6 @@ module ListMatrix: AbstractMatrix = List.nth m n let remove_row m n = - let () = Printf.printf "Before remove_row %i of m:\n%s\n" n (show m) in List.remove_at n m let get_col m n = @@ -75,9 +72,7 @@ module ListMatrix: AbstractMatrix = Timing.wrap "get_col" (get_col m) n let set_col m new_col n = - let () = Printf.printf "Before set_col m:\n%s\n" (show m) in (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) - let () = Printf.printf "After set_col m:\n%s\n" (show (List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col))) in List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) @@ -98,7 +93,6 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: s *: y) row1 row2 let reduce_col m j = - let () = Printf.printf "Before reduce_col %i of m:\n%s\n" j (show m) in if is_empty m then m else let rec find_pivot idx entries = (* Finds non-zero element in column j and returns pair of row idx and the pivot value *) @@ -108,18 +102,8 @@ module ListMatrix: AbstractMatrix = if value =: A.zero then find_pivot (idx - 1) rest else Some (idx, value) in match (find_pivot (num_rows m - 1) (List.rev m)) with - | None -> let () = Printf.printf "After reduce_col %i of m:\n%s\n" j (show m) in m (* column is already filled with zeroes *) + | None -> m (* column is already filled with zeroes *) | Some (row_idx, pivot) -> - let () = Printf.printf "After reduce_col %i of m:\n%s\n" j (show (let pivot_row = List.nth m row_idx in - List.mapi (fun idx row -> - if idx = row_idx then - V.zero_vec (num_cols m) - else - let row_value = V.nth row j in - if row_value = A.zero then row - else (let s = row_value /: pivot in - sub_scaled_row row pivot_row s) - ) m)) in let pivot_row = List.nth m row_idx in List.mapi (fun idx row -> if idx = row_idx then @@ -132,7 +116,6 @@ module ListMatrix: AbstractMatrix = ) m let reduce_col_with_vec m j v = - let () = Printf.printf "Before reduce_col_with_vec %i with vec %s of m:\n%s\n" j (V.show v) (show m) in let pivot_element = V.nth v j in if pivot_element = A.zero then m else List.mapi (fun idx row -> @@ -150,7 +133,6 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) - let () = Printf.printf "Before del_cols cols_length=%i \nm:\n%s\n" (List.length cols) (show m) in if (List.length sorted_cols) = num_cols m then empty() else List.map (fun row -> V.remove_at_indices row sorted_cols) m @@ -158,14 +140,12 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols let map2i f m v = - let () = Printf.printf "Before map2i m:\n%sv:%s\n" (show m) (V.show v) in let rec map2i_min i acc m v = match m, v with | [], _ -> List.rev acc | row :: rs, [] -> List.rev_append (row :: acc) rs | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs in - let () = Printf.printf "After map2i m:\n%s\n" (show (map2i_min 0 [] m (V.to_list v))) in map2i_min 0 [] m (V.to_list v) let remove_zero_rows m = @@ -187,7 +167,6 @@ module ListMatrix: AbstractMatrix = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m let normalize m = - let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m @@ -233,7 +212,6 @@ module ListMatrix: AbstractMatrix = main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = main_loop m m 0 0 in - let () = Printf.printf "After normalizing we have m:\n%s" (show m') in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) @@ -242,20 +220,17 @@ module ListMatrix: AbstractMatrix = (*If m is empty then v is simply normalized and returned*) (* TODO: OPTIMIZE! *) let rref_vec m v = - let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in match normalize @@ append_matrices m (init_with_vec v) with - | Some res -> let () = Printf.printf "After rref_vec, before removing zero rows, we have m:\n%s\n" (show res) in - Some (remove_zero_rows res) - | None -> let () = Printf.printf "After rref_vec there is no normalization\n " in None + | Some res -> Some (remove_zero_rows res) + | None -> None (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) (*TODO: OPTIMIZE!*) let rref_matrix m1 m2 = - let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in match normalize @@ append_matrices m1 m2 with - | Some m -> let () = Printf.printf "After rref_matrix m, before removing zero rows:\n %s\n" (show m) in Some (remove_zero_rows m) - | None -> let () = Printf.printf "No normalization for rref_matrix found" in None + | Some m -> Some (remove_zero_rows m) + | None -> None let delete_row_with_pivots row pivots m2 = failwith "TODO" @@ -277,7 +252,6 @@ module ListMatrix: AbstractMatrix = let new_v = V.map2_f_preserves_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in is_linearly_independent_rref new_v m' in - let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in if num_rows m1 > num_rows m2 then false else let rec is_covered_by_helper m1 m2 = match m1 with @@ -297,9 +271,7 @@ module ListMatrix: AbstractMatrix = List.find_opt f m let map2 f m v = - let () = Printf.printf "Before map2 we have m:\n%s\n" (show m) in let vector_length = V.length v in - let () = Printf.printf "After map2 we have m:\n%s\n" (show (List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m)) in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 8df5994c9c..bdc715127d 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -32,13 +32,11 @@ struct let dim_remove (ch: Apron.Dim.change) m ~del = - let () = Printf.printf "Before dim_remove m:\n%s" (show m) in if Array.length ch.dim = 0 || is_empty m then m else ( Array.modifyi (+) ch.dim; let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in - let () = Printf.printf "After dim_remove m':\n%s" (show (remove_zero_rows @@ del_cols m' ch.dim)) in remove_zero_rows @@ del_cols m' ch.dim) let dim_remove ch m ~del = Timing.wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del @@ -256,7 +254,6 @@ struct let meet t1 t2 = let res = meet t1 t2 in - let () = Printf.printf "meet a: %s b: %s -> %s \n" (show t1) (show t2) (show res) in if M.tracing then M.tracel "meet" "meet a: %s b: %s -> %s " (show t1) (show t2) (show res) ; res @@ -283,7 +280,6 @@ struct let leq t1 t2 = let res = leq t1 t2 in - let () = Printf.printf "leq a: %s b: %s -> %b \n" (show t1) (show t2) res in if M.tracing then M.tracel "leq" "leq a: %s b: %s -> %b " (show t1) (show t2) res ; res @@ -297,17 +293,13 @@ struct in let case_three a b col_a col_b max = let col_a, col_b = Vector.copy col_a, Vector.copy col_b in - let () = Printf.printf "Before keep_vals: \ncol_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in let col_a, col_b = Vector.keep_vals col_a max, Vector.keep_vals col_b max in - let () = Printf.printf "After keep_vals: \ncol_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in if Vector.equal col_a col_b then (a, b, max) else ( - let () = Printf.printf "Before rev col_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in let col_a = Vector.rev col_a in let col_b = Vector.rev col_b in - let () = Printf.printf "After rev col_a: %s col_b: %s\n" (Vector.show col_a) (Vector.show col_b) in let i = Vector.find2i (<>:) col_a col_b in let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in @@ -315,7 +307,6 @@ struct let col_a = Vector.map2 (-:) col_a col_b in let col_a = Vector.rev col_a in let multiply_by_t m t = - let () = Printf.printf "Before multiply_by_t col_a: %s" (Vector.show col_a) in Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2 (fun u j -> u -: (beta *: j)) x t) else x) m col_a; in @@ -356,12 +347,10 @@ struct let join a b = let res = join a b in - let () = Printf.printf "join a: %s b: %s -> %s \n" (show a) (show b) (show res) in if M.tracing then M.tracel "join" "join a: %s b: %s -> %s " (show a) (show b) (show res) ; res let widen a b = - let () = Printf.printf "Widen a: %s b: %s\n" (show a) (show b) in if Environment.equal a.env b.env then join a b else @@ -378,7 +367,6 @@ struct let remove_rels_with_var x var env = Timing.wrap "remove_rels_with_var" remove_rels_with_var x var env let forget_vars t vars = - let () = Printf.printf "forget_vars m:\n%s" (show t) in if is_bot t || is_top_env t || vars = [] then t else @@ -414,7 +402,6 @@ struct let b_length = Vector.length b in let b = Vector.mapi (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b in let b = Vector.set_nth b (Environment.dim_of_var env var) Mpqf.one in - let () = Printf.printf "Before Matrix.rref_vec x:\n%s b:\n%s\n" (Matrix.show x) (Vector.show b) in match Matrix.rref_vec x b with | None -> bot () | some_matrix -> {d = some_matrix; env = env} @@ -424,9 +411,9 @@ struct in let affineEq_vec = get_coeff_vec t texp in if is_bot t then t else let m = Option.get t.d in match affineEq_vec with - | Some v when is_top_env t -> let () = Printf.printf "After affineEq_vec m:\n%s\n" (Vector.show v) in + | Some v when is_top_env t -> if is_invertible v then t else assign_uninvertible_rel m var v t.env - | Some v -> let () = Printf.printf "After affineEq_vec m:\n%s\n" (Vector.show v) in + | Some v -> if is_invertible v then let t' = assign_invertible_rels (Matrix.copy m) var v t.env in {d = t'.d; env = t'.env} else let new_m = Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env in assign_uninvertible_rel new_m var v t.env @@ -459,15 +446,13 @@ struct res let assign_var_parallel t vv's = - let () = Printf.printf "Before assign_var_parallel m:\n%s\n" (show t) in let assigned_vars = List.map fst vv's in let t = add_vars t assigned_vars in let primed_vars = List.init (List.length assigned_vars) (fun i -> Var.of_string (Int.to_string i ^"'")) in (* TODO: we use primed vars in analysis, conflict? *) let t_primed = add_vars t primed_vars in let multi_t = List.fold_left2 (fun t' v_prime (_,v') -> assign_var t' v_prime v') t_primed primed_vars vv's in - let () = Printf.printf "After assign_var_parallel multi_t:\n%s\n" (show multi_t) in match multi_t.d with - | Some m when not @@ is_top_env multi_t -> let () = Printf.printf "Matrix in Domain m:\n%s\n" (Matrix.show m) in + | Some m when not @@ is_top_env multi_t -> let replace_col m x y = let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in let col_x = Matrix.get_col m dim_x in @@ -475,7 +460,6 @@ struct in let m_cp = Matrix.copy m in let switched_m = List.fold_left2 replace_col m_cp primed_vars assigned_vars in - let () = Printf.printf "Switched Matrix in Domain switched_m:\n%s\n" (Matrix.show switched_m) in let res = drop_vars {d = Some switched_m; env = multi_t.env} primed_vars ~del:true in let x = Option.get res.d in (match Matrix.normalize x with From 9ea8cc251c81f8ecb66f392d1eb0df2b25097695 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 12 Dec 2024 16:28:37 +0100 Subject: [PATCH 115/240] Remove old copies in AffineEqualityDomain --- .../apron/affineEqualityDomain.apron.ml | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index bdc715127d..63f785a861 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -36,7 +36,7 @@ struct m else ( Array.modifyi (+) ch.dim; - let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in + let m' = if not del then Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in remove_zero_rows @@ del_cols m' ch.dim) let dim_remove ch m ~del = Timing.wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del @@ -81,17 +81,16 @@ struct in Vector.set_nth zero_vec ((Vector.length zero_vec) - 1) (of_union x) | Var x -> - let zero_vec_cp = Vector.copy zero_vec in let entry_only v = Vector.set_nth v (Environment.dim_of_var t.env x) Mpqf.one in begin match t.d with | Some m -> let row = Matrix.find_opt (fun r -> Vector.nth r (Environment.dim_of_var t.env x) =: Mpqf.one) m in begin match row with | Some v when is_const_vec v -> - Vector.set_nth zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)) - | _ -> entry_only zero_vec_cp + Vector.set_nth zero_vec ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)) + | _ -> entry_only zero_vec end - | None -> entry_only zero_vec_cp end + | None -> entry_only zero_vec end | Unop (Neg, e, _, _) -> neg @@ convert_texpr e | Unop (Cast, e, _, _) -> convert_texpr e (*Ignore since casts in apron are used for floating point nums and rounding in contrast to CIL casts*) | Unop (Sqrt, e, _, _) -> raise NotLinear @@ -292,7 +291,6 @@ struct Matrix.remove_row a r in let case_three a b col_a col_b max = - let col_a, col_b = Vector.copy col_a, Vector.copy col_b in let col_a, col_b = Vector.keep_vals col_a max, Vector.keep_vals col_b max in if Vector.equal col_a col_b then (a, b, max) @@ -339,9 +337,9 @@ struct let sup_env = Environment.lce a.env b.env in let mod_x = dim_add (Environment.dimchange a.env sup_env) x in let mod_y = dim_add (Environment.dimchange b.env sup_env) y in - {d = Some (lin_disjunc 0 0 (Matrix.copy mod_x) (Matrix.copy mod_y)); env = sup_env} + {d = Some (lin_disjunc 0 0 mod_x mod_y); env = sup_env} | x, y when Matrix.equal x y -> {d = Some x; env = a.env} - | x, y -> {d = Some(lin_disjunc 0 0 (Matrix.copy x) (Matrix.copy y)); env = a.env} + | x, y -> {d = Some(lin_disjunc 0 0 x y); env = a.env} let join a b = Timing.wrap "join" (join a) b @@ -372,7 +370,7 @@ struct else let m = Option.get t.d in let rem_from m = List.fold_left (fun m' x -> remove_rels_with_var m' x t.env) m vars in - {d = Some (Matrix.remove_zero_rows @@ rem_from (Matrix.copy m)); env = t.env} + {d = Some (Matrix.remove_zero_rows @@ rem_from m); env = t.env} let forget_vars t vars = let res = forget_vars t vars in @@ -414,7 +412,7 @@ struct | Some v when is_top_env t -> if is_invertible v then t else assign_uninvertible_rel m var v t.env | Some v -> - if is_invertible v then let t' = assign_invertible_rels (Matrix.copy m) var v t.env in {d = t'.d; env = t'.env} + if is_invertible v then let t' = assign_invertible_rels m var v t.env in {d = t'.d; env = t'.env} else let new_m = Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env in assign_uninvertible_rel new_m var v t.env | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env); env = t.env} @@ -458,8 +456,7 @@ struct let col_x = Matrix.get_col m dim_x in Matrix.set_col m col_x dim_y in - let m_cp = Matrix.copy m in - let switched_m = List.fold_left2 replace_col m_cp primed_vars assigned_vars in + let switched_m = List.fold_left2 replace_col m primed_vars assigned_vars in let res = drop_vars {d = Some switched_m; env = multi_t.env} primed_vars ~del:true in let x = Option.get res.d in (match Matrix.normalize x with From ca91d4838cd1e8e8268bc37f72c0552f0a379ee5 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 12 Dec 2024 17:10:21 +0100 Subject: [PATCH 116/240] Adapt sparseVector functions to tail recursive --- .../sparseImplementation/sparseVector.ml | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 2fc3e16e5f..20b400756c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -36,9 +36,10 @@ module SparseVector: AbstractVector = let keep_vals v n = if n >= v.len then v else - {entries = take_while (fun (idx, _) -> idx < n) v.entries; len=n} + {entries = List.take_while (fun (idx, _) -> idx < n) v.entries; len=n} + (* Maybe use the function below instead of this one ?*) let remove_nth v n = let dec_idx v = List.map (fun (a,b) -> (a-1, b)) v @@ -68,39 +69,37 @@ module SparseVector: AbstractVector = (* Note: It is assumed and necessary here that idx is sorted!!! *) let remove_at_indices v idx = - let rec remove_indices_helper vec idx deleted_count = + let rec remove_indices_helper vec idx deleted_count acc = match vec, idx with - | [], [] -> [] + | [], [] -> List.rev acc | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> failwith "remove at indices: no more columns to delete" - | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) (* Removing zero (also in next iteration, else failwith ) *) - | ((col_idx, value) :: xs), [] -> (col_idx - deleted_count, value) :: remove_indices_helper xs [] deleted_count - | ((col_idx, value) :: xs), (y :: ys) when y = col_idx -> remove_indices_helper xs ys (deleted_count + 1) - | ((col_idx, value) :: xs), (y :: ys) when y < col_idx -> remove_indices_helper vec ys (deleted_count + 1) - | ((col_idx, value) :: xs), (y :: ys) -> (col_idx - deleted_count, value) :: remove_indices_helper xs idx deleted_count + | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) acc (* Removing zero (also in next iteration, else failwith ) *) + | ((col_idx, value) :: xs), [] -> remove_indices_helper xs [] deleted_count ((col_idx - deleted_count, value) :: acc) + | ((col_idx, value) :: xs), (y :: ys) when y = col_idx -> remove_indices_helper xs ys (deleted_count + 1) acc + | ((col_idx, value) :: xs), (y :: ys) when y < col_idx -> remove_indices_helper vec ys (deleted_count + 1) acc + | ((col_idx, value) :: xs), (y :: ys) -> remove_indices_helper xs idx deleted_count ((col_idx - deleted_count, value) :: acc) in - {entries = remove_indices_helper v.entries idx 0; len = v.len - List.length idx} + {entries = remove_indices_helper v.entries idx 0 []; len = v.len - List.length idx} let insert_zero_at_indices v idx count = - let rec add_indices_helper vec idx added_count = + let rec add_indices_helper vec idx added_count acc = match vec, idx with - | [], [] -> [] - | [], (y :: ys) -> [] (* inserting at the end only means changing the dimension *) - | ((col_idx, value) :: xs), [] -> (col_idx + added_count, value) :: add_indices_helper xs [] added_count - | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) - | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> add_indices_helper vec ys (added_count + count) - | ((col_idx, value) :: xs), ((i, count) :: ys) -> (col_idx + added_count, value) :: add_indices_helper xs idx added_count + | [], _ -> List.rev acc (* inserting at the end only means changing the dimension *) + | ((col_idx, value) :: xs), [] -> add_indices_helper xs [] added_count ((col_idx + added_count, value) :: acc) + | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) acc + | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> add_indices_helper vec ys (added_count + count) acc + | ((col_idx, value) :: xs), ((i, count) :: ys) -> add_indices_helper xs idx added_count ((col_idx + added_count, value) :: acc) in - {entries = add_indices_helper v.entries idx 0; len = v.len + count} + {entries = add_indices_helper v.entries idx 0 []; len = v.len + count} let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" else - (* of_list @@ List.mapi (fun i x -> if i = n then num else x) (to_list v) *) let rec set_nth_helper vec acc = match vec with | [] -> if num <>: A.zero then List.rev ((n, num) :: acc) else List.rev acc | (idx, value) :: xs when n = idx -> if num <>: A.zero then List.rev_append ((idx, num) :: acc) xs else List.rev_append acc xs - | (idx, value) :: xs when n < idx -> if num <>: A.zero then List.rev_append ((n, num) :: acc) vec else List.rev_append acc ((idx, value) :: xs) + | (idx, value) :: xs when n < idx -> if num <>: A.zero then List.rev_append ((n, num) :: acc) vec else List.rev_append acc vec | x :: xs -> set_nth_helper xs (x :: acc) in {entries = set_nth_helper v.entries []; len = v.len} From 6883084363a7a1dbc3e3af238e198aa246da5d26 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 13 Dec 2024 13:29:35 +0100 Subject: [PATCH 117/240] added Timingwraps to vector functions and alternative to findivalopt --- .../arrayImplementation/arrayVector.ml | 1 + .../sparseImplementation/listMatrix.ml | 21 ++++++++++--------- .../sparseImplementation/sparseVector.ml | 11 ++++++++++ src/cdomains/affineEquality/vector.ml | 2 ++ 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 622a12e328..0705853357 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -132,4 +132,5 @@ module ArrayVector: AbstractVector = let starting_from_nth n v = failwith "TODO / deprecated" + let find_first_non_zero v = failwith "TODO" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index d43e858138..02d9896a7b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -166,11 +166,14 @@ module ListMatrix: AbstractMatrix = let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m + let swap_rows m j k = Timing.wrap "swap rows" (swap_rows m j) k + let normalize m = let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m in + let dec_mat_2D m row_idx col_idx = Timing.wrap "dec_mat_2D" (dec_mat_2D m row_idx) col_idx in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) (* The last column represents the constant in the affeq *) let find_first_pivot m' row_idx col_idx = @@ -178,7 +181,7 @@ module ListMatrix: AbstractMatrix = let max_piv_col_idx = num_cols m' - 2 in (* col at num_cols - 1 is the constant of the affeq *) (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> - let row_first_non_zero = V.findi_val_opt ((<>:) A.zero) row in + let row_first_non_zero = V.find_first_non_zero row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) | Some (idx, value) -> (* let () = Printf.printf "We found first non-zero at index %i in row %i\n" idx i in *) @@ -187,10 +190,11 @@ module ListMatrix: AbstractMatrix = in if piv_col = (max_piv_col_idx + 1) then None else Some (row_idx + piv_row, col_idx + piv_col, piv_val) in + let find_first_pivot m' row_idx col_idx = Timing.wrap "find_first_pivot" (find_first_pivot m' row_idx) col_idx in let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) let col_count = num_cols m in let row_is_valid row = (* TODO: Vector findi_opt *) - match V.findi_val_opt ((<>:) A.zero) row with + match V.find_first_non_zero row with | Some (idx, _) -> if idx < col_count - 1 then true else false (* If all cofactors of the affeq are zero, but the constant is non-zero, the row is invalid *) | None -> true (* Full zero row is valid *) in @@ -214,15 +218,12 @@ module ListMatrix: AbstractMatrix = let m' = main_loop m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) - (*m must be in rref form and contain the same num of cols as v*) - (*If m is empty then v is simply normalized and returned*) - (* TODO: OPTIMIZE! *) - let rref_vec m v = + let rref_vec m v = match normalize @@ append_matrices m (init_with_vec v) with - | Some res -> Some (remove_zero_rows res) - | None -> None + | Some m -> Some (remove_zero_rows m) + | None -> None + + let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 20b400756c..b895befc14 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -118,6 +118,8 @@ module SparseVector: AbstractVector = if new_val = A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} + let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v + (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) let map2_f_preserves_zero f v1 v2 = let f_rem_zero acc idx e1 e2 = @@ -138,6 +140,7 @@ module SparseVector: AbstractVector = if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else to_vector (List.rev (aux [] v1.entries v2.entries)) v1.len + let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries @@ -201,6 +204,14 @@ module SparseVector: AbstractVector = else find_zero_or_val xs idx in find_zero_or_val v.entries (-1) + let findi_val_opt f v = Timing.wrap "findi_val_opt" (findi_val_opt f) v + + let find_first_non_zero v = + if v.entries = [] then None + else Some (List.hd v.entries) + + let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v + let map f v = of_list (List.map f (to_list v)) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index f52f6eadbb..11b33df151 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -49,6 +49,8 @@ sig (* Returns optional tuple of position and value which was found*) val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t + val find_first_non_zero : t -> (int * num) option + val find_opt: (num -> bool) -> t -> num Option.t val map: (num -> num) -> t -> t From 61caba26fc086dd00b3f77a736c5a3b1a8f58859 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 13 Dec 2024 17:21:38 +0100 Subject: [PATCH 118/240] implemented different rref_vec that doesn't use normalize --- array.txt | 2150 +++++++++++++++ list.txt | 2318 +++++++++++++++++ rref_vec.txt | 1256 +++++++++ sparse.txt | 1294 +++++++++ .../arrayImplementation/arrayVector.ml | 3 + .../sparseImplementation/listMatrix.ml | 94 +- .../sparseImplementation/sparseVector.ml | 6 + src/cdomains/affineEquality/vector.ml | 2 + 8 files changed, 7101 insertions(+), 22 deletions(-) create mode 100644 array.txt create mode 100644 list.txt create mode 100644 rref_vec.txt create mode 100644 sparse.txt diff --git a/array.txt b/array.txt new file mode 100644 index 0000000000..215bda4a77 --- /dev/null +++ b/array.txt @@ -0,0 +1,2150 @@ +./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none tests/regression/77-lin2vareq/20-function_call2.c +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +Matrix in Domain m: + +Switched Matrix in Domain switched_m: + +Before normalizing we have m: +After normalizing we have m: +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[1 0 0 0 ] + +Before Matrix.rref_vec x: + b: +[-1 1 0 0 ] + +Before rref_vec we have m: +v: [-1 1 0 0 ] + +Before normalizing we have m: +[-1 1 0 0 ] +After normalizing we have m: +[1 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 -1 0 0 ] + +After affineEq_vec m: +[0 1 0 0 ] + +Before reduce_col 2 of m: +[1 -1 0 0 ] + +After reduce_col 2 of m: +[1 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 -1 0 0 ] + b: +[0 -1 1 0 ] + +Before rref_vec we have m: +[1 -1 0 0 ] +v: [0 -1 1 0 ] + +Before normalizing we have m: +[1 -1 0 0 ] +[0 -1 1 0 ] +After normalizing we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] + +After affineEq_vec m: +[0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 1 0 0 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 1 0 ] + +Before reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before assign_var_parallel m: +[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +After affineEq_vec m: +[0 0 0 0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[1 0 0 0 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [1 0 0 0 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[1 0 0 0 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 1 0 0 0 0 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 1 0 0 0 0 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 1 0 0 0 0 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 0 1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 0 1 0 0 0 0 0 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 0 1 0 0 0 0 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After assign_var_parallel multi_t: +[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +Matrix in Domain m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Switched Matrix in Domain switched_m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before dim_remove m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After dim_remove m': +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 -1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 -1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 -1 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 -1 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 1 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 1 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 0 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 0 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 0 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 0 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 8 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + b: +[1 0 0 0 0 0 0 8 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +v: [1 0 0 0 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +[1 0 0 0 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 1 0 0 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 -1 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + b: +[0 1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +v: [0 1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +[0 1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +forget_vars m: +[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After affineEq_vec m: +[0 0 0 0 1 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +forget_vars m: +[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +forget_vars m: +[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +After dim_remove m': +[1 0 0 0 8 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +Before rref_matrix m1 m2 +m1: [0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +m2: [1 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_matrix m, before removing zero rows: + [1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] +Before dim_remove m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 0 of m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + b: +[1 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +v: [1 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After dim_remove m': +[1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[1 0 0 0 ] + +Before Matrix.rref_vec x: + b: +[-1 1 0 0 ] + +Before rref_vec we have m: +v: [-1 1 0 0 ] + +Before normalizing we have m: +[-1 1 0 0 ] +After normalizing we have m: +[1 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 -1 0 0 ] + +After affineEq_vec m: +[0 1 0 0 ] + +Before reduce_col 2 of m: +[1 -1 0 0 ] + +After reduce_col 2 of m: +[1 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 -1 0 0 ] + b: +[0 -1 1 0 ] + +Before rref_vec we have m: +[1 -1 0 0 ] +v: [0 -1 1 0 ] + +Before normalizing we have m: +[1 -1 0 0 ] +[0 -1 1 0 ] +After normalizing we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] + +After affineEq_vec m: +[0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 1 0 0 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 1 0 ] + +Before reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before assign_var_parallel m: +[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +After affineEq_vec m: +[0 0 0 0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[1 0 0 0 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [1 0 0 0 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[1 0 0 0 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 1 0 0 0 0 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 1 0 0 0 0 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 1 0 0 0 0 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 0 1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 0 1 0 0 0 0 0 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 0 1 0 0 0 0 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After assign_var_parallel multi_t: +[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +Matrix in Domain m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Switched Matrix in Domain switched_m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before dim_remove m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After dim_remove m': +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 -1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 -1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 -1 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 -1 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 1 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 1 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 0 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 0 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 0 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 0 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 8 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + b: +[1 0 0 0 0 0 0 8 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +v: [1 0 0 0 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +[1 0 0 0 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 1 0 0 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 -1 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + b: +[0 1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +v: [0 1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +[0 1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +forget_vars m: +[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After affineEq_vec m: +[0 0 0 0 1 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +forget_vars m: +[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +forget_vars m: +[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +After dim_remove m': +[1 0 0 0 8 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +Before rref_matrix m1 m2 +m1: [0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +m2: [1 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_matrix m, before removing zero rows: + [1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] +Before dim_remove m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 0 of m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + b: +[1 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +v: [1 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After dim_remove m': +[1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +[Info][Deadcode] Logical lines of code (LLoC) summary: + live: 10 + dead: 0 + total lines: 10 +See result/index.xml diff --git a/list.txt b/list.txt new file mode 100644 index 0000000000..6f85b69219 --- /dev/null +++ b/list.txt @@ -0,0 +1,2318 @@ +./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none tests/regression/77-lin2vareq/20-function_call2.c +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +Matrix in Domain m: + +Switched Matrix in Domain switched_m: + +Before normalizing we have m: +After normalizing we have m: +Before add_empty_columns m: +indices: 0,0,0, +Occ_cols is: +(0,3) +After add_empty_columns m: + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[1 0 0 0 ] + +Before Matrix.rref_vec x: + b: +[-1 1 0 0 ] + +Before rref_vec we have m: +v: [-1 1 0 0 ] + +Before normalizing we have m: +[-1 1 0 0 ] +After normalizing we have m: +[1 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 -1 0 0 ] + +After affineEq_vec m: +[0 1 0 0 ] + +Before reduce_col 2 of m: +[1 -1 0 0 ] + +After reduce_col 2 of m: +[1 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 -1 0 0 ] + b: +[0 -1 1 0 ] + +Before rref_vec we have m: +[1 -1 0 0 ] +v: [0 -1 1 0 ] + +Before normalizing we have m: +[1 -1 0 0 ] +[0 -1 1 0 ] +After normalizing we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0,1,2, +Occ_cols is: +(0,1)(1,1)(2,1) +After add_empty_columns m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 1 0 0 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 1 0 ] + +Before reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0,1,2, +Occ_cols is: +(0,1)(1,1)(2,1) +After add_empty_columns m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before assign_var_parallel m: +[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +Before add_empty_columns m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +indices: 0,0,0, +Occ_cols is: +(0,3) +After add_empty_columns m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[1 0 0 0 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [1 0 0 0 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[1 0 0 0 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 1 0 0 0 0 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 1 0 0 0 0 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 1 0 0 0 0 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 0 1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 0 1 0 0 0 0 0 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 0 1 0 0 0 0 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After assign_var_parallel multi_t: +[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +Matrix in Domain m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Switched Matrix in Domain switched_m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before dim_remove m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After dim_remove m': +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 -1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 -1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 -1 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 -1 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 1 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 1 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 0 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 0 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 0 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 0 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +indices: 0, +Occ_cols is: +(0,1) +After add_empty_columns m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 8 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + b: +[1 0 0 0 0 0 0 8 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +v: [1 0 0 0 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +[1 0 0 0 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +indices: 2,3,4, +Occ_cols is: +(2,1)(3,1)(4,1) +After add_empty_columns m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 -1 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After affineEq_vec m: +[0 0 1 0 0 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 -1 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + b: +[0 1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +v: [0 1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +[0 1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +forget_vars m: +[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After affineEq_vec m: +[0 0 0 0 1 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +forget_vars m: +[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +forget_vars m: +[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +After dim_remove m': +[1 0 0 0 8 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0, +Occ_cols is: +(0,1) +After add_empty_columns m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before rref_matrix m1 m2 +m1: [0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +m2: [1 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_matrix m, before removing zero rows: + [1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] +Before dim_remove m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 0 of m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0, +Occ_cols is: +(0,1) +After add_empty_columns m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + b: +[1 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +v: [1 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After dim_remove m': +[1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before add_empty_columns m: +indices: 0,0,0, +Occ_cols is: +(0,3) +After add_empty_columns m: + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[1 0 0 0 ] + +Before Matrix.rref_vec x: + b: +[-1 1 0 0 ] + +Before rref_vec we have m: +v: [-1 1 0 0 ] + +Before normalizing we have m: +[-1 1 0 0 ] +After normalizing we have m: +[1 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 -1 0 0 ] + +After affineEq_vec m: +[0 1 0 0 ] + +Before reduce_col 2 of m: +[1 -1 0 0 ] + +After reduce_col 2 of m: +[1 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 -1 0 0 ] + b: +[0 -1 1 0 ] + +Before rref_vec we have m: +[1 -1 0 0 ] +v: [0 -1 1 0 ] + +Before normalizing we have m: +[1 -1 0 0 ] +[0 -1 1 0 ] +After normalizing we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 -1 0 ] +[0 1 -1 0 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0,1,2, +Occ_cols is: +(0,1)(1,1)(2,1) +After add_empty_columns m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 1 0 0 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 1 0 ] + +Before reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +After reduce_col 4 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + b: +[0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +v: [0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 -1 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0,1,2, +Occ_cols is: +(0,1)(1,1)(2,1) +After add_empty_columns m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] + +Before assign_var_parallel m: +[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +Before add_empty_columns m: +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +indices: 0,0,0, +Occ_cols is: +(0,3) +After add_empty_columns m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 1 0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[1 0 0 0 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [1 0 0 0 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[1 0 0 0 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 1 0 0 0 0 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 1 0 0 0 0 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 1 0 0 0 0 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 0 1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + b: +[0 0 1 0 0 0 0 0 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +v: [0 0 1 0 0 0 0 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After assign_var_parallel multi_t: +[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] +Matrix in Domain m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 0 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 0 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After set_col m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Switched Matrix in Domain switched_m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before dim_remove m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +After dim_remove m': +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 1 0 0 0 0 -1 0 ] +[0 1 0 0 0 1 0 0 -1 0 ] +[0 0 1 0 0 0 0 1 -1 0 ] +[0 0 0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 1 0 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 -1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 -1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 1 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 -1 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 -1 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [0 0 1 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 1 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [1 0 0 0 -1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[1 0 0 0 -1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +v: [-1 0 0 0 1 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[-1 0 0 0 1 0 0 ] +After normalizing we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +[0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +[1 0 0 0 0 -1 0 ] +[0 1 0 0 0 -1 0 ] +[0 0 1 0 0 -1 0 ] +[0 0 0 1 0 -1 0 ] +[0 0 0 0 1 -1 0 ] +indices: 0, +Occ_cols is: +(0,1) +After add_empty_columns m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 8 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + b: +[1 0 0 0 0 0 0 8 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +v: [1 0 0 0 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +[1 0 0 0 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 0 -1 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 1 0 0 -1 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +After dim_remove m': +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 0 1 0 -1 0 ] +[0 0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +indices: 2,3,4, +Occ_cols is: +(2,1)(3,1)(4,1) +After add_empty_columns m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 -1 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After affineEq_vec m: +[0 0 1 0 0 0 0 0 ] + +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 0 0 0 -1 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + b: +[0 1 -1 0 0 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +v: [0 1 -1 0 0 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] +[0 1 -1 0 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +forget_vars m: +[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 1 -1 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] +[0 0 0 1 0 -1 0 0 ] + +After affineEq_vec m: +[0 0 0 0 1 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 0 -1 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 1 -1 0 0 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 1 -1 0 0 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +forget_vars m: +[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 1 -1 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 1 0 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before Matrix.rref_vec x: +[1 0 0 0 0 0 0 8 ] + b: +[0 0 0 0 0 1 -1 0 ] + +Before rref_vec we have m: +[1 0 0 0 0 0 0 8 ] +v: [0 0 0 0 0 1 -1 0 ] + +Before normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After normalizing we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +forget_vars m: +[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 1 -1 0 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] +[0 0 0 0 0 0 0 0 ] + +Before dim_remove m: +[1 0 0 0 0 0 0 8 ] +Before reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 1 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 3 of m: +[1 0 0 0 0 0 0 8 ] + +Before reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +After reduce_col 5 of m: +[1 0 0 0 0 0 0 8 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +After dim_remove m': +[1 0 0 0 8 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 0 0 8 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0, +Occ_cols is: +(0,1) +After add_empty_columns m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before rref_matrix m1 m2 +m1: [0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +m2: [1 0 0 0 8 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 8 ] +After normalizing we have m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_matrix m, before removing zero rows: + [1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] +Before dim_remove m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 0 of m: +[1 0 0 0 8 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After dim_remove m': +[1 0 -1 0 ] +[0 1 -1 0 ] +Before del_cols cols_length=1 +m: +[0 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before add_empty_columns m: +[1 0 -1 0 ] +[0 1 -1 0 ] +indices: 0, +Occ_cols is: +(0,1) +After add_empty_columns m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After affineEq_vec m: +[0 0 0 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 0 of m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + b: +[1 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +v: [1 0 0 0 0 ] + +Before normalizing we have m: +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +[1 0 0 0 0 ] +After normalizing we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +After rref_vec, before removing zero rows, we have m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +Before dim_remove m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] +Before reduce_col 1 of m: +[1 0 0 0 0 ] +[0 1 0 -1 0 ] +[0 0 1 -1 0 ] + +After reduce_col 1 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +Before reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 1 -1 0 ] + +After reduce_col 2 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After reduce_col 3 of m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +After dim_remove m': +[1 0 ] +Before del_cols cols_length=3 +m: +[1 0 0 0 0 ] +[0 0 0 0 0 ] +[0 0 0 0 0 ] + +[Info][Deadcode] Logical lines of code (LLoC) summary: + live: 10 + dead: 0 + total lines: 10 +See result/index.xml diff --git a/rref_vec.txt b/rref_vec.txt new file mode 100644 index 0000000000..4cccc943b1 --- /dev/null +++ b/rref_vec.txt @@ -0,0 +1,1256 @@ +./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set ana.relation.privatization top --set sem.int.signed_overflow assume_none tests/regression/63-affeq/03-guard-check.c -v +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +Matrix in Domain m: + +Switched Matrix in Domain switched_m: + +Before normalizing we have m: +After normalizing we have m: +Before add_empty_columns m: +indices: 0,0,0,0,0,0, +After add_empty_columns m: + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[0 0 0 0 0 0 0 ] + +Before Matrix.rref_vec x: + b: +[0 1 0 0 0 0 0 ] + +Before rref_vec we have m: +v: [0 1 0 0 0 0 0 ] + +After rref_vec, before removing zero rows, we have m: +[0 1 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 ] + +Before reduce_col 2 of m: +[0 1 0 0 0 0 0 ] + +After reduce_col 2 of m: +[0 1 0 0 0 0 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 0 ] + b: +[0 0 1 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 0 ] +v: [0 0 1 0 0 0 0 ] + +pivot positions are: (0,1) + +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 ] + +Before reduce_col 5 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + +After reduce_col 5 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + b: +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +v: [0 0 0 0 0 1 0 ] + +pivot positions are: (0,1)(1,2) + +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After affineEq_vec m: +[0 0 0 1 1 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + b: +[1 0 0 -1 -1 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,1)(1,2)(2,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 -1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 -1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 -1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before map2i m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] +v:[-1 0 0 0 ] + +After map2i m: +[1 0 0 -2 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before remove_row 3 of m: +[1 0 0 -2 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before keep_vals: +col_a: [-1 0 0 0 ] + col_b: [-1 0 0 0 ] + +After keep_vals: +col_a: [-1 0 0 ] + col_b: [-1 0 0 ] + +Before keep_vals: +col_a: [0 0 0 0 ] + col_b: [0 0 0 0 ] + +After keep_vals: +col_a: [0 0 0 0 ] + col_b: [0 0 0 0 ] + +join a: [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] b: [|f#303-x#301-y#302=0; i#298=0; k#299=0; x#301=0; z#300=0|] -> [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [2 0 0 -2 -2 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 2 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-2 0 0 2 2 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -2 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before dim_remove m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +Before reduce_col 0 of m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 0 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 1 of m: +[0 0 0 0 0 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 1 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 2 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 2 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 3 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 3 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 4 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 4 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 5 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 5 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before del_cols cols_length=6 +m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +After dim_remove m': +Before del_cols cols_length=6 +m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before add_empty_columns m: +indices: 0,0,0,0,0,0, +After add_empty_columns m: + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[0 0 0 0 0 0 0 ] + +Before Matrix.rref_vec x: + b: +[0 1 0 0 0 0 0 ] + +Before rref_vec we have m: +v: [0 1 0 0 0 0 0 ] + +After rref_vec, before removing zero rows, we have m: +[0 1 0 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 ] + +Before reduce_col 2 of m: +[0 1 0 0 0 0 0 ] + +After reduce_col 2 of m: +[0 1 0 0 0 0 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 0 ] + b: +[0 0 1 0 0 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 0 ] +v: [0 0 1 0 0 0 0 ] + +pivot positions are: (0,1) + +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + +After affineEq_vec m: +[0 0 0 0 0 0 0 ] + +Before reduce_col 5 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + +After reduce_col 5 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] + b: +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +v: [0 0 0 0 0 1 0 ] + +pivot positions are: (0,1)(1,2) + +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After affineEq_vec m: +[0 0 0 1 1 0 0 ] + +Before reduce_col 0 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 0 of m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before Matrix.rref_vec x: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + b: +[1 0 0 -1 -1 0 0 ] + +Before rref_vec we have m: +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,1)(1,2)(2,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 -1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 -1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 -1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [0 0 0 1 0 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before map2i m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] +v:[-1 0 0 0 ] + +After map2i m: +[1 0 0 -2 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before remove_row 3 of m: +[1 0 0 -2 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 1 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before keep_vals: +col_a: [-1 0 0 0 ] + col_b: [-1 0 0 0 ] + +After keep_vals: +col_a: [-1 0 0 ] + col_b: [-1 0 0 ] + +Before keep_vals: +col_a: [0 0 0 0 ] + col_b: [0 0 0 0 ] + +After keep_vals: +col_a: [0 0 0 0 ] + col_b: [0 0 0 0 ] + +join a: [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] b: [|f#303-x#301-y#302=0; i#298=0; k#299=0; x#301=0; z#300=0|] -> [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [2 0 0 -2 -2 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 2 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-2 0 0 2 2 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -2 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [1 0 0 -1 -1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is 1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before rref_vec we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +v: [-1 0 0 1 1 0 0 ] + +pivot positions are: (0,0)(1,1)(2,2)(3,5) + +v_at_piv is -1 +piv row is: [1 0 0 -1 -1 0 0 ] + +scaled row is: [0 0 0 0 0 0 0 ] + +v_at_piv is 0 +v_at_piv is 0 +v_at_piv is 0 +After rref_vec, before removing zero rows, we have m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before dim_remove m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] +Before reduce_col 0 of m: +[1 0 0 -1 -1 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 0 of m: +[0 0 0 0 0 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 1 of m: +[0 0 0 0 0 0 0 ] +[0 1 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 1 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 2 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 1 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 2 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 3 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 3 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 4 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 4 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +Before reduce_col 5 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 1 0 ] + +After reduce_col 5 of m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +Before del_cols cols_length=6 +m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +After dim_remove m': +Before del_cols cols_length=6 +m: +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] +[0 0 0 0 0 0 0 ] + +[Info][Deadcode] Logical lines of code (LLoC) summary: + live: 23 + dead: 0 + total lines: 23 +[Warning][Deadcode][CWE-571] condition 'i == 0' is always true (tests/regression/63-affeq/03-guard-check.c:16:9-16:15) +[Warning][Deadcode][CWE-571] condition 'i != 1' is always true (tests/regression/63-affeq/03-guard-check.c:23:9-23:15) +[Warning][Deadcode][CWE-571] condition 'i > -1' is always true (tests/regression/63-affeq/03-guard-check.c:28:9-28:15) +[Warning][Deadcode][CWE-571] condition 'i >= -1' is always true (tests/regression/63-affeq/03-guard-check.c:35:9-35:16) +See result/index.xml diff --git a/sparse.txt b/sparse.txt new file mode 100644 index 0000000000..4a98bd2d95 --- /dev/null +++ b/sparse.txt @@ -0,0 +1,1294 @@ +./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none --set ana.relation.privatization top tests/regression/63-affeq/01-rel_simple.c -v +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +Matrix in Domain m: + +Switched Matrix in Domain switched_m: + +Before normalizing we have m: +After normalizing we have m: +Before add_empty_columns m: + +After add_empty_columns m: + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[ 0 0 0 2] + +Before Matrix.rref_vec x: + b: +[ 1 0 0 2] + +Before rref_vec we have m: +v: [ 1 0 0 2] + +Before normalizing we have m: +[ 1 0 0 2] +After normalizing we have m: +[ 1 0 0 2] +After affineEq_vec m: +[ 0 0 1 5] + +Before reduce_col 1 of m: +[ 1 0 0 2] + +After reduce_col 1 of m: +[ 1 0 0 2] + +Before Matrix.rref_vec x: +[ 1 0 0 2] + b: +[ 0 1 -1 5] + +Before rref_vec we have m: +[ 1 0 0 2] +v: [ 0 1 -1 5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +After affineEq_vec m: +[ 0 0 1 5] + +Before reduce_col 1 of m: +[ 1 0 0 2] + +After reduce_col 1 of m: +[ 1 0 0 2] + +Before Matrix.rref_vec x: +[ 1 0 0 2] + b: +[ 0 1 -1 5] + +Before rref_vec we have m: +[ 1 0 0 2] +v: [ 0 1 -1 5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +Before rref_vec we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +v: [ 0 -1 0 -6] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 -1 0 -6] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 0 -1 -1] +Before rref_vec we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +v: [ 0 1 0 6] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 1 0 6] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +v: [ 0 -1 1 -5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 -1 1 -5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 0 0 0] +Before rref_vec we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +v: [ 0 1 -1 5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 1 -1 5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +[ 0 0 0 0] +After affineEq_vec m: +[ 0 0 0 3] + +Before reduce_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +After reduce_col 0 of m: +[ 0 0 0 0] +[ 0 1 -1 5] + +Before Matrix.rref_vec x: +[ 0 1 -1 5] + b: +[ 1 0 0 3] + +Before rref_vec we have m: +[ 0 1 -1 5] +v: [ 1 0 0 3] + +Before normalizing we have m: +[ 0 1 -1 5] +[ 1 0 0 3] +After normalizing we have m: +[ 1 0 0 3] +[ 0 1 -1 5] +After affineEq_vec m: +[ 0 1 0 3] + +get_col 1 of m: +[ 1 0 0 3] +[ 0 1 -1 5] + +[ 0 1] + +Before map2 we have m: +[ 1 0 0 3] +[ 0 1 -1 5] + +After map2 we have m: +[ 1 0 0 3] +[ 0 1 -1 8] + +Before normalizing we have m: +[ 1 0 0 3] +[ 0 1 -1 8] +After normalizing we have m: +[ 1 0 0 3] +[ 0 1 -1 8] +get_col 0 of m: +[ 1 0 0 3] +[ 0 1 -1 8] + +[ 1 0] + +get_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 1 0] + +get_col 1 of m: +[ 1 0 0 3] +[ 0 1 -1 8] + +[ 0 1] + +get_col 1 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 1] + +get_col 2 of m: +[ 1 0 0 3] +[ 0 1 -1 8] + +[ 0 -1] + +get_col 2 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 -1] + +Before keep_vals: +col_a: [ 0 -1] + col_b: [ 0 -1] + +After keep_vals: +col_a: [ 0 -1] + col_b: [ 0 -1] + +get_col 3 of m: +[ 1 0 0 3] +[ 0 1 -1 8] + +[ 3 8] + +get_col 3 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 2 5] + +Before keep_vals: +col_a: [ 2 5] + col_b: [ 3 8] + +After keep_vals: +col_a: [ 2 5] + col_b: [ 3 8] + +Before rev col_a: [ 2 5] + col_b: [ 3 8] + +After rev col_a: [ 5 2] + col_b: [ 8 3] + +Before multiply_by_t col_a: [ -1 -3] +Before map2i m: +[ 1 0 0 3] +[ 0 1 -1 8] +v:[ -1 -3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] + +Before multiply_by_t col_a: [ -1 -3] +Before map2i m: +[ 1 0 0 2] +[ 0 1 -1 5] +v:[ -1 -3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] + +join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|i#320-3=0; j#321-k#322-8=0|] -> [|3i#320-j#321+k#322-1=0|] +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +get_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 1 0] + +get_col 1 of m: +[ 1 -1/3 1/3 1/3] + +[ -1/3] + +get_col 1 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 1] + +Before map2i m: +[ 1 0 0 2] +[ 0 1 -1 5] +v:[ -1/3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +leq a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> true +Widen a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +get_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 1 0] + +get_col 1 of m: +[ 1 -1/3 1/3 1/3] + +[ -1/3] + +get_col 1 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 1] + +Before map2i m: +[ 1 0 0 2] +[ 0 1 -1 5] +v:[ -1/3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +After affineEq_vec m: +[ 0 0 1 5] + +Before reduce_col 1 of m: +[ 1 0 0 2] + +After reduce_col 1 of m: +[ 1 0 0 2] + +Before Matrix.rref_vec x: +[ 1 0 0 2] + b: +[ 0 1 -1 5] + +Before rref_vec we have m: +[ 1 0 0 2] +v: [ 0 1 -1 5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 1 0 0 100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 1 0 0 100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 1 1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 1 1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 -1 -1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 -1 -1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +After affineEq_vec m: +[ 1 0 0 1] + +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +Before map2 we have m: +[ 1 -1/3 1/3 1/3] + +After map2 we have m: +[ 1 -1/3 1/3 4/3] + +Before normalizing we have m: +[ 1 -1/3 1/3 4/3] +After normalizing we have m: +[ 1 -1/3 1/3 4/3] +After affineEq_vec m: +[ 0 1 0 3] + +get_col 1 of m: +[ 1 -1/3 1/3 4/3] + +[ -1/3] + +Before map2 we have m: +[ 1 -1/3 1/3 4/3] + +After map2 we have m: +[ 1 -1/3 1/3 1/3] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +get_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 1 0] + +get_col 1 of m: +[ 1 -1/3 1/3 1/3] + +[ -1/3] + +get_col 1 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 1] + +Before map2i m: +[ 1 0 0 2] +[ 0 1 -1 5] +v:[ -1/3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +join a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +leq a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -> true +Widen a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] +join a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +After affineEq_vec m: +[ 0 0 1 5] + +Before reduce_col 1 of m: +[ 1 0 0 2] + +After reduce_col 1 of m: +[ 1 0 0 2] + +Before Matrix.rref_vec x: +[ 1 0 0 2] + b: +[ 0 1 -1 5] + +Before rref_vec we have m: +[ 1 0 0 2] +v: [ 0 1 -1 5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 1 0 0 100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 1 0 0 100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 1 1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 1 1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 -1 -1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 -1 -1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +After affineEq_vec m: +[ 1 0 0 1] + +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +Before map2 we have m: +[ 1 -1/3 1/3 1/3] + +After map2 we have m: +[ 1 -1/3 1/3 4/3] + +Before normalizing we have m: +[ 1 -1/3 1/3 4/3] +After normalizing we have m: +[ 1 -1/3 1/3 4/3] +After affineEq_vec m: +[ 0 1 0 3] + +get_col 1 of m: +[ 1 -1/3 1/3 4/3] + +[ -1/3] + +Before map2 we have m: +[ 1 -1/3 1/3 4/3] + +After map2 we have m: +[ 1 -1/3 1/3 1/3] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +get_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 1 0] + +get_col 1 of m: +[ 1 -1/3 1/3 1/3] + +[ -1/3] + +get_col 1 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 1] + +Before map2i m: +[ 1 0 0 2] +[ 0 1 -1 5] +v:[ -1/3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 1 0 0 100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 1 0 0 100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 1 1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 1 1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 -1 -1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 -1 -1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +Before dim_remove m: +[ 1 -1/3 1/3 1/3] +Before reduce_col 0 of m: +[ 1 -1/3 1/3 1/3] + +After reduce_col 0 of m: +[ 0 0 0 0] + +Before reduce_col 1 of m: +[ 0 0 0 0] + +After reduce_col 1 of m: +[ 0 0 0 0] + +Before reduce_col 2 of m: +[ 0 0 0 0] + +After reduce_col 2 of m: +[ 0 0 0 0] + +Before del_cols cols_length=3 sorted_length=3 +m: +[ 0 0 0 0] + +After dim_remove m': +Before del_cols cols_length=3 sorted_length=3 +m: +[ 0 0 0 0] + +Before add_empty_columns m: + +After add_empty_columns m: + +Before assign_var_parallel m: +⊤ +After assign_var_parallel multi_t: +⊤ +After affineEq_vec m: +[ 0 0 0 2] + +Before Matrix.rref_vec x: + b: +[ 1 0 0 2] + +Before rref_vec we have m: +v: [ 1 0 0 2] + +Before normalizing we have m: +[ 1 0 0 2] +After normalizing we have m: +[ 1 0 0 2] +After affineEq_vec m: +[ 0 0 1 5] + +Before reduce_col 1 of m: +[ 1 0 0 2] + +After reduce_col 1 of m: +[ 1 0 0 2] + +Before Matrix.rref_vec x: +[ 1 0 0 2] + b: +[ 0 1 -1 5] + +Before rref_vec we have m: +[ 1 0 0 2] +v: [ 0 1 -1 5] + +Before normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +After normalizing we have m: +[ 1 0 0 2] +[ 0 1 -1 5] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 1 0 0 100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 1 0 0 100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 1 1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 1 1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 -1 -1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 -1 -1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +[Warning][Assert] Assertion "(3 * i - j) + k == 1" is unknown. Expected: SUCCESS -> failed (tests/regression/63-affeq/01-rel_simple.c:13:9-13:44) +After affineEq_vec m: +[ 1 0 0 1] + +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +Before map2 we have m: +[ 1 -1/3 1/3 1/3] + +After map2 we have m: +[ 1 -1/3 1/3 4/3] + +Before normalizing we have m: +[ 1 -1/3 1/3 4/3] +After normalizing we have m: +[ 1 -1/3 1/3 4/3] +After affineEq_vec m: +[ 0 1 0 3] + +get_col 1 of m: +[ 1 -1/3 1/3 4/3] + +[ -1/3] + +Before map2 we have m: +[ 1 -1/3 1/3 4/3] + +After map2 we have m: +[ 1 -1/3 1/3 1/3] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +get_col 0 of m: +[ 1 -1/3 1/3 1/3] + +[ 1] + +get_col 0 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 1 0] + +get_col 1 of m: +[ 1 -1/3 1/3 1/3] + +[ -1/3] + +get_col 1 of m: +[ 1 0 0 2] +[ 0 1 -1 5] + +[ 0 1] + +Before map2i m: +[ 1 0 0 2] +[ 0 1 -1 5] +v:[ -1/3] + +After map2i m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +Before remove_row 1 of m: +[ 1 -1/3 1/3 1/3] +[ 0 1 -1 5] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 2 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +get_col 3 of m: +[ 1 -1/3 1/3 1/3] + +[ 1/3] + +Before keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +After keep_vals: +col_a: [ 1/3] + col_b: [ 1/3] + +join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 1 0 0 100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 1 0 0 100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -1 0 0 -100] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -1 0 0 -100] +After normalizing we have m: +[ 1 -301/900 301/900 1/900] +[ 0 1/300 -1/300 299/300] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 0 0] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 0 0] +After normalizing we have m: +[ 1 -1/3 2/3 2/3] +[ 0 0 1 1] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ 3 -1 1 1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 3 -1 1 1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +Before rref_vec we have m: +[ 1 -1/3 1/3 1/3] +v: [ -3 1 -1 -1] + +Before normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ -3 1 -1 -1] +After normalizing we have m: +[ 1 -1/3 1/3 1/3] +[ 0 0 0 0] +[Warning][Assert] Assertion "(3 * i - j) + k == 1" is unknown. Expected: SUCCESS -> failed (tests/regression/63-affeq/01-rel_simple.c:17:5-17:40) +Before dim_remove m: +[ 1 -1/3 1/3 1/3] +Before reduce_col 0 of m: +[ 1 -1/3 1/3 1/3] + +After reduce_col 0 of m: +[ 0 0 0 0] + +Before reduce_col 1 of m: +[ 0 0 0 0] + +After reduce_col 1 of m: +[ 0 0 0 0] + +Before reduce_col 2 of m: +[ 0 0 0 0] + +After reduce_col 2 of m: +[ 0 0 0 0] + +Before del_cols cols_length=3 sorted_length=3 +m: +[ 0 0 0 0] + +After dim_remove m': +Before del_cols cols_length=3 sorted_length=3 +m: +[ 0 0 0 0] + +[Info][Deadcode] Logical lines of code (LLoC) summary: + live: 9 + dead: 0 + total lines: 9 +See result/index.xml diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 622a12e328..390ae07fdb 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -132,4 +132,7 @@ module ArrayVector: AbstractVector = let starting_from_nth n v = failwith "TODO / deprecated" + let find_first_non_zero v = + failwith "TODO" + end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index d7a280fa8f..0dc0bf14ac 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -44,11 +44,11 @@ module ListMatrix: AbstractMatrix = let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in let rec count_sorted_occ acc cols last count = - match cols with - | [] -> if count > 0 then (last, count) :: acc else acc - | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) - | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in - count_sorted_occ acc xs x 1 + match cols with + | [] -> if count > 0 then (last, count) :: acc else acc + | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) + | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in + count_sorted_occ acc xs x 1 in let occ_cols = List.rev @@ count_sorted_occ [] sorted_cols 0 0 in let () = Printf.printf "After add_empty_columns m:\n%s\n" (show (List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m)) in @@ -116,7 +116,7 @@ module ListMatrix: AbstractMatrix = V.zero_vec (num_cols m) else let row_value = V.nth row j in - if row_value = A.zero then row + if row_value =: A.zero then row else (let s = row_value /: pivot in sub_scaled_row row pivot_row s) ) m)) in @@ -137,12 +137,11 @@ module ListMatrix: AbstractMatrix = if pivot_element = A.zero then m else List.mapi (fun idx row -> let row_value = V.nth row j in - if row_value = A.zero then row + if row_value =: A.zero then row else (let s = row_value /: pivot_element in V.map2_f_preserves_zero (fun x y -> x -: s *: y) row v) ) m - let del_col m j = if num_cols m = 1 then empty () else @@ -237,17 +236,68 @@ module ListMatrix: AbstractMatrix = let () = Printf.printf "After normalizing we have m:\n%s" (show m') in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) + (* This function return a tuple of row index and pivot position (column) in m *) + (* TODO: maybe we could use a Hashmap instead of a list? *) + let get_pivot_positions (m : t) : (int * int) list = + List.rev @@ List.fold_lefti ( + fun acc i row -> match V.find_first_non_zero row with + | None -> acc + | Some (pivot_col, _) -> (i, pivot_col) :: acc + ) [] m + + (* Inserts the vector v with pivot at piv_idx at the correct position in m. m has to be in rref form. *) + let insert_v_according_to_piv m v piv_idx pivot_positions = + match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with + | None -> append_row m v + | Some (row_idx, _) -> let (before, after) = List.split_at row_idx m in + before @ (v :: after) + + let rref_vec (m : t) (v : V.t) : t option = + let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in + if is_empty m then (* In this case, v is normalized and returned *) + match V.find_first_non_zero v with + | None -> let () = Printf.printf "After rref_vec there is no normalization\n " in None + | Some (_, value) -> + let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v in + let res = init_with_vec normalized_v in + let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in + Some res + else (* We try to normalize v and check if a contradiction arises. If not, we insert v at the appropriate place in m (depending on the pivot) *) + let pivot_positions = get_pivot_positions m in + let () = Printf.printf "pivot positions are: %s\n\n" (List.fold_right (fun (row, piv) s -> "(" ^ (Int.to_string row) ^ "," ^ (Int.to_string piv) ^ ")" ^ s) pivot_positions "") in + let v_after_elim = List.fold_left ( + fun acc (row_idx, pivot_position) -> + let v_at_piv = V.nth acc pivot_position in + if v_at_piv =: A.zero then + acc + else + let piv_row = List.nth m row_idx in + sub_scaled_row acc piv_row v_at_piv + ) v pivot_positions + in + match V.find_first_non_zero v_after_elim with (* now we check for contradictions and finally insert v *) + | None -> let () = Printf.printf "After rref_vec we have m:\n%s\n" (show m) in + Some m (* v is zero vector and was therefore already covered by zero *) + | Some (idx, value) -> + if idx = (num_cols m - 1) then + let () = Printf.printf "After rref_vec there is no normalization\n " in None + else + let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v_after_elim in + let res = insert_v_according_to_piv m normalized_v idx pivot_positions in + let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in + Some res + (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) (* TODO: OPTIMIZE! *) - let rref_vec m v = + (*let rref_vec m v = let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in match normalize @@ append_matrices m (init_with_vec v) with | Some res -> let () = Printf.printf "After rref_vec, before removing zero rows, we have m:\n%s\n" (show res) in Some (remove_zero_rows res) - | None -> let () = Printf.printf "After rref_vec there is no normalization\n " in None + | None -> let () = Printf.printf "After rref_vec there is no normalization\n " in None*) (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) @@ -280,18 +330,18 @@ module ListMatrix: AbstractMatrix = in let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in if num_rows m1 > num_rows m2 then false else - let rec is_covered_by_helper m1 m2 = - match m1 with - | [] -> true - | v1::vs1 -> - let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in - match first_non_zero with - | None -> true (* vs1 must also be zero-vectors because of rref *) - | Some (idx, _) -> - let linearly_indep = is_linearly_independent_rref v1 m2 in - if linearly_indep then false else is_covered_by_helper vs1 m2 - in is_covered_by_helper m1 m2 - + let rec is_covered_by_helper m1 m2 = + match m1 with + | [] -> true + | v1::vs1 -> + let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in + match first_non_zero with + | None -> true (* vs1 must also be zero-vectors because of rref *) + | Some (idx, _) -> + let linearly_indep = is_linearly_independent_rref v1 m2 in + if linearly_indep then false else is_covered_by_helper vs1 m2 + in is_covered_by_helper m1 m2 + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 1b31bfe2c7..7e8e5612e6 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -203,6 +203,12 @@ module SparseVector: AbstractVector = else find_zero_or_val xs idx in find_zero_or_val v.entries (-1) + let find_first_non_zero v = + if v.entries = [] then None + else Some (List.hd v.entries) + + let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v + let map f v = of_list (List.map f (to_list v)) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index f52f6eadbb..11b33df151 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -49,6 +49,8 @@ sig (* Returns optional tuple of position and value which was found*) val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t + val find_first_non_zero : t -> (int * num) option + val find_opt: (num -> bool) -> t -> num Option.t val map: (num -> num) -> t -> t From c9be718cac1b1c2919801cf6b16a7f93592c75ac Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 13 Dec 2024 18:13:05 +0100 Subject: [PATCH 119/240] new rref_vec should be faster --- .../sparseImplementation/listMatrix.ml | 70 +++++++++++++++---- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 02d9896a7b..8a5313760f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -218,10 +218,52 @@ module ListMatrix: AbstractMatrix = let m' = main_loop m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - let rref_vec m v = + let get_pivot_positions (m : t) : (int * int) list = + List.rev @@ List.fold_lefti ( + fun acc i row -> match V.find_first_non_zero row with + | None -> acc + | Some (pivot_col, _) -> (i, pivot_col) :: acc + ) [] m + + (* Inserts the vector v with pivot at piv_idx at the correct position in m. m has to be in rref form. *) + let insert_v_according_to_piv m v piv_idx pivot_positions = + match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with + | None -> append_row m v + | Some (row_idx, _) -> let (before, after) = List.split_at row_idx m in + before @ (v :: after) + + let rref_vec (m : t) (v : V.t) : t option = + if is_empty m then (* In this case, v is normalized and returned *) + match V.find_first_non_zero v with + | None -> None + | Some (_, value) -> + let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v in + Some (init_with_vec normalized_v) + else (* We try to normalize v and check if a contradiction arises. If not, we insert v at the appropriate place in m (depending on the pivot) *) + let pivot_positions = get_pivot_positions m in + let v_after_elim = List.fold_left ( + fun acc (row_idx, pivot_position) -> + let v_at_piv = V.nth acc pivot_position in + if v_at_piv =: A.zero then + acc + else + let piv_row = List.nth m row_idx in + sub_scaled_row acc piv_row v_at_piv + ) v pivot_positions + in + match V.find_first_non_zero v_after_elim with (* now we check for contradictions and finally insert v *) + | None -> Some m (* v is zero vector and was therefore already covered by zero *) + | Some (idx, value) -> + if idx = (num_cols m - 1) then + None + else + let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v_after_elim in + Some (insert_v_according_to_piv m normalized_v idx pivot_positions) + + (*let rref_vec m v = match normalize @@ append_matrices m (init_with_vec v) with - | Some m -> Some (remove_zero_rows m) | None -> None + | Some m -> Some (remove_zero_rows m) *) let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v @@ -254,18 +296,18 @@ module ListMatrix: AbstractMatrix = is_linearly_independent_rref new_v m' in if num_rows m1 > num_rows m2 then false else - let rec is_covered_by_helper m1 m2 = - match m1 with - | [] -> true - | v1::vs1 -> - let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in - match first_non_zero with - | None -> true (* vs1 must also be zero-vectors because of rref *) - | Some (idx, _) -> - let linearly_indep = is_linearly_independent_rref v1 m2 in - if linearly_indep then false else is_covered_by_helper vs1 m2 - in is_covered_by_helper m1 m2 - + let rec is_covered_by_helper m1 m2 = + match m1 with + | [] -> true + | v1::vs1 -> + let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in + match first_non_zero with + | None -> true (* vs1 must also be zero-vectors because of rref *) + | Some (idx, _) -> + let linearly_indep = is_linearly_independent_rref v1 m2 in + if linearly_indep then false else is_covered_by_helper vs1 m2 + in is_covered_by_helper m1 m2 + let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = From fb1f36a0812e72d897f51ce058c1da38a0c4e9f6 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 13 Dec 2024 18:17:52 +0100 Subject: [PATCH 120/240] removed files with debug logs that I pushed by accident --- array.txt | 2150 -------------------------------------------------- rref_vec.txt | 1256 ----------------------------- sparse.txt | 1294 ------------------------------ 3 files changed, 4700 deletions(-) delete mode 100644 array.txt delete mode 100644 rref_vec.txt delete mode 100644 sparse.txt diff --git a/array.txt b/array.txt deleted file mode 100644 index 215bda4a77..0000000000 --- a/array.txt +++ /dev/null @@ -1,2150 +0,0 @@ -./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none tests/regression/77-lin2vareq/20-function_call2.c -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -Matrix in Domain m: - -Switched Matrix in Domain switched_m: - -Before normalizing we have m: -After normalizing we have m: -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[1 0 0 0 ] - -Before Matrix.rref_vec x: - b: -[-1 1 0 0 ] - -Before rref_vec we have m: -v: [-1 1 0 0 ] - -Before normalizing we have m: -[-1 1 0 0 ] -After normalizing we have m: -[1 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 -1 0 0 ] - -After affineEq_vec m: -[0 1 0 0 ] - -Before reduce_col 2 of m: -[1 -1 0 0 ] - -After reduce_col 2 of m: -[1 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 -1 0 0 ] - b: -[0 -1 1 0 ] - -Before rref_vec we have m: -[1 -1 0 0 ] -v: [0 -1 1 0 ] - -Before normalizing we have m: -[1 -1 0 0 ] -[0 -1 1 0 ] -After normalizing we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] - -After affineEq_vec m: -[0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 1 0 0 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 1 0 ] - -Before reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before assign_var_parallel m: -[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -After affineEq_vec m: -[0 0 0 0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[1 0 0 0 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [1 0 0 0 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[1 0 0 0 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 1 0 0 0 0 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 1 0 0 0 0 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 1 0 0 0 0 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 0 1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 0 1 0 0 0 0 0 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 0 1 0 0 0 0 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After assign_var_parallel multi_t: -[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -Matrix in Domain m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Switched Matrix in Domain switched_m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before dim_remove m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After dim_remove m': -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 -1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 -1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 -1 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 -1 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 1 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 1 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 0 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 0 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 0 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 0 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 8 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - b: -[1 0 0 0 0 0 0 8 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -v: [1 0 0 0 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -[1 0 0 0 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 1 0 0 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 -1 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - b: -[0 1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -v: [0 1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -[0 1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -forget_vars m: -[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After affineEq_vec m: -[0 0 0 0 1 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -forget_vars m: -[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -forget_vars m: -[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -After dim_remove m': -[1 0 0 0 8 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -Before rref_matrix m1 m2 -m1: [0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -m2: [1 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_matrix m, before removing zero rows: - [1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] -Before dim_remove m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 0 of m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - b: -[1 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -v: [1 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After dim_remove m': -[1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[1 0 0 0 ] - -Before Matrix.rref_vec x: - b: -[-1 1 0 0 ] - -Before rref_vec we have m: -v: [-1 1 0 0 ] - -Before normalizing we have m: -[-1 1 0 0 ] -After normalizing we have m: -[1 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 -1 0 0 ] - -After affineEq_vec m: -[0 1 0 0 ] - -Before reduce_col 2 of m: -[1 -1 0 0 ] - -After reduce_col 2 of m: -[1 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 -1 0 0 ] - b: -[0 -1 1 0 ] - -Before rref_vec we have m: -[1 -1 0 0 ] -v: [0 -1 1 0 ] - -Before normalizing we have m: -[1 -1 0 0 ] -[0 -1 1 0 ] -After normalizing we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] - -After affineEq_vec m: -[0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 1 0 0 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 1 0 ] - -Before reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before assign_var_parallel m: -[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -After affineEq_vec m: -[0 0 0 0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[1 0 0 0 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [1 0 0 0 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[1 0 0 0 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 1 0 0 0 0 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 1 0 0 0 0 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 1 0 0 0 0 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 0 1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 0 1 0 0 0 0 0 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 0 1 0 0 0 0 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After assign_var_parallel multi_t: -[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -Matrix in Domain m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Switched Matrix in Domain switched_m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before dim_remove m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After dim_remove m': -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 -1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 -1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 -1 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 -1 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 1 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 1 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 0 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 0 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 0 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 0 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 8 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - b: -[1 0 0 0 0 0 0 8 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -v: [1 0 0 0 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -[1 0 0 0 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 1 0 0 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 -1 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - b: -[0 1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -v: [0 1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -[0 1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -forget_vars m: -[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After affineEq_vec m: -[0 0 0 0 1 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -forget_vars m: -[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -forget_vars m: -[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -After dim_remove m': -[1 0 0 0 8 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -Before rref_matrix m1 m2 -m1: [0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -m2: [1 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_matrix m, before removing zero rows: - [1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] -Before dim_remove m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 0 of m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - b: -[1 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -v: [1 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After dim_remove m': -[1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -[Info][Deadcode] Logical lines of code (LLoC) summary: - live: 10 - dead: 0 - total lines: 10 -See result/index.xml diff --git a/rref_vec.txt b/rref_vec.txt deleted file mode 100644 index 4cccc943b1..0000000000 --- a/rref_vec.txt +++ /dev/null @@ -1,1256 +0,0 @@ -./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set ana.relation.privatization top --set sem.int.signed_overflow assume_none tests/regression/63-affeq/03-guard-check.c -v -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -Matrix in Domain m: - -Switched Matrix in Domain switched_m: - -Before normalizing we have m: -After normalizing we have m: -Before add_empty_columns m: -indices: 0,0,0,0,0,0, -After add_empty_columns m: - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[0 0 0 0 0 0 0 ] - -Before Matrix.rref_vec x: - b: -[0 1 0 0 0 0 0 ] - -Before rref_vec we have m: -v: [0 1 0 0 0 0 0 ] - -After rref_vec, before removing zero rows, we have m: -[0 1 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 ] - -Before reduce_col 2 of m: -[0 1 0 0 0 0 0 ] - -After reduce_col 2 of m: -[0 1 0 0 0 0 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 0 ] - b: -[0 0 1 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 0 ] -v: [0 0 1 0 0 0 0 ] - -pivot positions are: (0,1) - -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 ] - -Before reduce_col 5 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - -After reduce_col 5 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - b: -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -v: [0 0 0 0 0 1 0 ] - -pivot positions are: (0,1)(1,2) - -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After affineEq_vec m: -[0 0 0 1 1 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - b: -[1 0 0 -1 -1 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,1)(1,2)(2,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 -1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 -1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 -1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before map2i m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] -v:[-1 0 0 0 ] - -After map2i m: -[1 0 0 -2 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before remove_row 3 of m: -[1 0 0 -2 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before keep_vals: -col_a: [-1 0 0 0 ] - col_b: [-1 0 0 0 ] - -After keep_vals: -col_a: [-1 0 0 ] - col_b: [-1 0 0 ] - -Before keep_vals: -col_a: [0 0 0 0 ] - col_b: [0 0 0 0 ] - -After keep_vals: -col_a: [0 0 0 0 ] - col_b: [0 0 0 0 ] - -join a: [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] b: [|f#303-x#301-y#302=0; i#298=0; k#299=0; x#301=0; z#300=0|] -> [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [2 0 0 -2 -2 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 2 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-2 0 0 2 2 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -2 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before dim_remove m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -Before reduce_col 0 of m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 0 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 1 of m: -[0 0 0 0 0 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 1 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 2 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 2 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 3 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 3 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 4 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 4 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 5 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 5 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before del_cols cols_length=6 -m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -After dim_remove m': -Before del_cols cols_length=6 -m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -indices: 0,0,0,0,0,0, -After add_empty_columns m: - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[0 0 0 0 0 0 0 ] - -Before Matrix.rref_vec x: - b: -[0 1 0 0 0 0 0 ] - -Before rref_vec we have m: -v: [0 1 0 0 0 0 0 ] - -After rref_vec, before removing zero rows, we have m: -[0 1 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 ] - -Before reduce_col 2 of m: -[0 1 0 0 0 0 0 ] - -After reduce_col 2 of m: -[0 1 0 0 0 0 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 0 ] - b: -[0 0 1 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 0 ] -v: [0 0 1 0 0 0 0 ] - -pivot positions are: (0,1) - -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 ] - -Before reduce_col 5 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - -After reduce_col 5 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] - b: -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -v: [0 0 0 0 0 1 0 ] - -pivot positions are: (0,1)(1,2) - -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After affineEq_vec m: -[0 0 0 1 1 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - b: -[1 0 0 -1 -1 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,1)(1,2)(2,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 -1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 -1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 -1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [0 0 0 1 0 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before map2i m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] -v:[-1 0 0 0 ] - -After map2i m: -[1 0 0 -2 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before remove_row 3 of m: -[1 0 0 -2 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 1 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before keep_vals: -col_a: [-1 0 0 0 ] - col_b: [-1 0 0 0 ] - -After keep_vals: -col_a: [-1 0 0 ] - col_b: [-1 0 0 ] - -Before keep_vals: -col_a: [0 0 0 0 ] - col_b: [0 0 0 0 ] - -After keep_vals: -col_a: [0 0 0 0 ] - col_b: [0 0 0 0 ] - -join a: [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] b: [|f#303-x#301-y#302=0; i#298=0; k#299=0; x#301=0; z#300=0|] -> [|f#303-x#301-y#302=0; i#298=0; k#299=0; z#300=0|] -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [2 0 0 -2 -2 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 2 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-2 0 0 2 2 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -2 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [1 0 0 -1 -1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is 1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before rref_vec we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -v: [-1 0 0 1 1 0 0 ] - -pivot positions are: (0,0)(1,1)(2,2)(3,5) - -v_at_piv is -1 -piv row is: [1 0 0 -1 -1 0 0 ] - -scaled row is: [0 0 0 0 0 0 0 ] - -v_at_piv is 0 -v_at_piv is 0 -v_at_piv is 0 -After rref_vec, before removing zero rows, we have m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before dim_remove m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] -Before reduce_col 0 of m: -[1 0 0 -1 -1 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 0 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 1 of m: -[0 0 0 0 0 0 0 ] -[0 1 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 1 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 2 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 2 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 3 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 3 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 4 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 4 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -Before reduce_col 5 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 1 0 ] - -After reduce_col 5 of m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before del_cols cols_length=6 -m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -After dim_remove m': -Before del_cols cols_length=6 -m: -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -[Info][Deadcode] Logical lines of code (LLoC) summary: - live: 23 - dead: 0 - total lines: 23 -[Warning][Deadcode][CWE-571] condition 'i == 0' is always true (tests/regression/63-affeq/03-guard-check.c:16:9-16:15) -[Warning][Deadcode][CWE-571] condition 'i != 1' is always true (tests/regression/63-affeq/03-guard-check.c:23:9-23:15) -[Warning][Deadcode][CWE-571] condition 'i > -1' is always true (tests/regression/63-affeq/03-guard-check.c:28:9-28:15) -[Warning][Deadcode][CWE-571] condition 'i >= -1' is always true (tests/regression/63-affeq/03-guard-check.c:35:9-35:16) -See result/index.xml diff --git a/sparse.txt b/sparse.txt deleted file mode 100644 index 4a98bd2d95..0000000000 --- a/sparse.txt +++ /dev/null @@ -1,1294 +0,0 @@ -./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none --set ana.relation.privatization top tests/regression/63-affeq/01-rel_simple.c -v -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -Matrix in Domain m: - -Switched Matrix in Domain switched_m: - -Before normalizing we have m: -After normalizing we have m: -Before add_empty_columns m: - -After add_empty_columns m: - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[ 0 0 0 2] - -Before Matrix.rref_vec x: - b: -[ 1 0 0 2] - -Before rref_vec we have m: -v: [ 1 0 0 2] - -Before normalizing we have m: -[ 1 0 0 2] -After normalizing we have m: -[ 1 0 0 2] -After affineEq_vec m: -[ 0 0 1 5] - -Before reduce_col 1 of m: -[ 1 0 0 2] - -After reduce_col 1 of m: -[ 1 0 0 2] - -Before Matrix.rref_vec x: -[ 1 0 0 2] - b: -[ 0 1 -1 5] - -Before rref_vec we have m: -[ 1 0 0 2] -v: [ 0 1 -1 5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -After affineEq_vec m: -[ 0 0 1 5] - -Before reduce_col 1 of m: -[ 1 0 0 2] - -After reduce_col 1 of m: -[ 1 0 0 2] - -Before Matrix.rref_vec x: -[ 1 0 0 2] - b: -[ 0 1 -1 5] - -Before rref_vec we have m: -[ 1 0 0 2] -v: [ 0 1 -1 5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -Before rref_vec we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -v: [ 0 -1 0 -6] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 -1 0 -6] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 0 -1 -1] -Before rref_vec we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -v: [ 0 1 0 6] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 1 0 6] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -v: [ 0 -1 1 -5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 -1 1 -5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 0 0 0] -Before rref_vec we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -v: [ 0 1 -1 5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 1 -1 5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -[ 0 0 0 0] -After affineEq_vec m: -[ 0 0 0 3] - -Before reduce_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -After reduce_col 0 of m: -[ 0 0 0 0] -[ 0 1 -1 5] - -Before Matrix.rref_vec x: -[ 0 1 -1 5] - b: -[ 1 0 0 3] - -Before rref_vec we have m: -[ 0 1 -1 5] -v: [ 1 0 0 3] - -Before normalizing we have m: -[ 0 1 -1 5] -[ 1 0 0 3] -After normalizing we have m: -[ 1 0 0 3] -[ 0 1 -1 5] -After affineEq_vec m: -[ 0 1 0 3] - -get_col 1 of m: -[ 1 0 0 3] -[ 0 1 -1 5] - -[ 0 1] - -Before map2 we have m: -[ 1 0 0 3] -[ 0 1 -1 5] - -After map2 we have m: -[ 1 0 0 3] -[ 0 1 -1 8] - -Before normalizing we have m: -[ 1 0 0 3] -[ 0 1 -1 8] -After normalizing we have m: -[ 1 0 0 3] -[ 0 1 -1 8] -get_col 0 of m: -[ 1 0 0 3] -[ 0 1 -1 8] - -[ 1 0] - -get_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 1 0] - -get_col 1 of m: -[ 1 0 0 3] -[ 0 1 -1 8] - -[ 0 1] - -get_col 1 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 1] - -get_col 2 of m: -[ 1 0 0 3] -[ 0 1 -1 8] - -[ 0 -1] - -get_col 2 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 -1] - -Before keep_vals: -col_a: [ 0 -1] - col_b: [ 0 -1] - -After keep_vals: -col_a: [ 0 -1] - col_b: [ 0 -1] - -get_col 3 of m: -[ 1 0 0 3] -[ 0 1 -1 8] - -[ 3 8] - -get_col 3 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 2 5] - -Before keep_vals: -col_a: [ 2 5] - col_b: [ 3 8] - -After keep_vals: -col_a: [ 2 5] - col_b: [ 3 8] - -Before rev col_a: [ 2 5] - col_b: [ 3 8] - -After rev col_a: [ 5 2] - col_b: [ 8 3] - -Before multiply_by_t col_a: [ -1 -3] -Before map2i m: -[ 1 0 0 3] -[ 0 1 -1 8] -v:[ -1 -3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] - -Before multiply_by_t col_a: [ -1 -3] -Before map2i m: -[ 1 0 0 2] -[ 0 1 -1 5] -v:[ -1 -3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] - -join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|i#320-3=0; j#321-k#322-8=0|] -> [|3i#320-j#321+k#322-1=0|] -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -get_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 1 0] - -get_col 1 of m: -[ 1 -1/3 1/3 1/3] - -[ -1/3] - -get_col 1 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 1] - -Before map2i m: -[ 1 0 0 2] -[ 0 1 -1 5] -v:[ -1/3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -leq a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> true -Widen a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -get_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 1 0] - -get_col 1 of m: -[ 1 -1/3 1/3 1/3] - -[ -1/3] - -get_col 1 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 1] - -Before map2i m: -[ 1 0 0 2] -[ 0 1 -1 5] -v:[ -1/3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -After affineEq_vec m: -[ 0 0 1 5] - -Before reduce_col 1 of m: -[ 1 0 0 2] - -After reduce_col 1 of m: -[ 1 0 0 2] - -Before Matrix.rref_vec x: -[ 1 0 0 2] - b: -[ 0 1 -1 5] - -Before rref_vec we have m: -[ 1 0 0 2] -v: [ 0 1 -1 5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 1 0 0 100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 1 0 0 100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 1 1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 1 1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 -1 -1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 -1 -1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -After affineEq_vec m: -[ 1 0 0 1] - -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -Before map2 we have m: -[ 1 -1/3 1/3 1/3] - -After map2 we have m: -[ 1 -1/3 1/3 4/3] - -Before normalizing we have m: -[ 1 -1/3 1/3 4/3] -After normalizing we have m: -[ 1 -1/3 1/3 4/3] -After affineEq_vec m: -[ 0 1 0 3] - -get_col 1 of m: -[ 1 -1/3 1/3 4/3] - -[ -1/3] - -Before map2 we have m: -[ 1 -1/3 1/3 4/3] - -After map2 we have m: -[ 1 -1/3 1/3 1/3] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -get_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 1 0] - -get_col 1 of m: -[ 1 -1/3 1/3 1/3] - -[ -1/3] - -get_col 1 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 1] - -Before map2i m: -[ 1 0 0 2] -[ 0 1 -1 5] -v:[ -1/3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -join a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -leq a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -> true -Widen a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -join a: [|3i#320-j#321+k#322-1=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -After affineEq_vec m: -[ 0 0 1 5] - -Before reduce_col 1 of m: -[ 1 0 0 2] - -After reduce_col 1 of m: -[ 1 0 0 2] - -Before Matrix.rref_vec x: -[ 1 0 0 2] - b: -[ 0 1 -1 5] - -Before rref_vec we have m: -[ 1 0 0 2] -v: [ 0 1 -1 5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 1 0 0 100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 1 0 0 100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 1 1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 1 1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 -1 -1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 -1 -1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -After affineEq_vec m: -[ 1 0 0 1] - -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -Before map2 we have m: -[ 1 -1/3 1/3 1/3] - -After map2 we have m: -[ 1 -1/3 1/3 4/3] - -Before normalizing we have m: -[ 1 -1/3 1/3 4/3] -After normalizing we have m: -[ 1 -1/3 1/3 4/3] -After affineEq_vec m: -[ 0 1 0 3] - -get_col 1 of m: -[ 1 -1/3 1/3 4/3] - -[ -1/3] - -Before map2 we have m: -[ 1 -1/3 1/3 4/3] - -After map2 we have m: -[ 1 -1/3 1/3 1/3] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -get_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 1 0] - -get_col 1 of m: -[ 1 -1/3 1/3 1/3] - -[ -1/3] - -get_col 1 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 1] - -Before map2i m: -[ 1 0 0 2] -[ 0 1 -1 5] -v:[ -1/3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 1 0 0 100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 1 0 0 100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 1 1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 1 1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 -1 -1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 -1 -1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -Before dim_remove m: -[ 1 -1/3 1/3 1/3] -Before reduce_col 0 of m: -[ 1 -1/3 1/3 1/3] - -After reduce_col 0 of m: -[ 0 0 0 0] - -Before reduce_col 1 of m: -[ 0 0 0 0] - -After reduce_col 1 of m: -[ 0 0 0 0] - -Before reduce_col 2 of m: -[ 0 0 0 0] - -After reduce_col 2 of m: -[ 0 0 0 0] - -Before del_cols cols_length=3 sorted_length=3 -m: -[ 0 0 0 0] - -After dim_remove m': -Before del_cols cols_length=3 sorted_length=3 -m: -[ 0 0 0 0] - -Before add_empty_columns m: - -After add_empty_columns m: - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[ 0 0 0 2] - -Before Matrix.rref_vec x: - b: -[ 1 0 0 2] - -Before rref_vec we have m: -v: [ 1 0 0 2] - -Before normalizing we have m: -[ 1 0 0 2] -After normalizing we have m: -[ 1 0 0 2] -After affineEq_vec m: -[ 0 0 1 5] - -Before reduce_col 1 of m: -[ 1 0 0 2] - -After reduce_col 1 of m: -[ 1 0 0 2] - -Before Matrix.rref_vec x: -[ 1 0 0 2] - b: -[ 0 1 -1 5] - -Before rref_vec we have m: -[ 1 0 0 2] -v: [ 0 1 -1 5] - -Before normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -After normalizing we have m: -[ 1 0 0 2] -[ 0 1 -1 5] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 1 0 0 100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 1 0 0 100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 1 1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 1 1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 -1 -1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 -1 -1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -[Warning][Assert] Assertion "(3 * i - j) + k == 1" is unknown. Expected: SUCCESS -> failed (tests/regression/63-affeq/01-rel_simple.c:13:9-13:44) -After affineEq_vec m: -[ 1 0 0 1] - -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -Before map2 we have m: -[ 1 -1/3 1/3 1/3] - -After map2 we have m: -[ 1 -1/3 1/3 4/3] - -Before normalizing we have m: -[ 1 -1/3 1/3 4/3] -After normalizing we have m: -[ 1 -1/3 1/3 4/3] -After affineEq_vec m: -[ 0 1 0 3] - -get_col 1 of m: -[ 1 -1/3 1/3 4/3] - -[ -1/3] - -Before map2 we have m: -[ 1 -1/3 1/3 4/3] - -After map2 we have m: -[ 1 -1/3 1/3 1/3] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -get_col 0 of m: -[ 1 -1/3 1/3 1/3] - -[ 1] - -get_col 0 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 1 0] - -get_col 1 of m: -[ 1 -1/3 1/3 1/3] - -[ -1/3] - -get_col 1 of m: -[ 1 0 0 2] -[ 0 1 -1 5] - -[ 0 1] - -Before map2i m: -[ 1 0 0 2] -[ 0 1 -1 5] -v:[ -1/3] - -After map2i m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -Before remove_row 1 of m: -[ 1 -1/3 1/3 1/3] -[ 0 1 -1 5] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 2 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -get_col 3 of m: -[ 1 -1/3 1/3 1/3] - -[ 1/3] - -Before keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -After keep_vals: -col_a: [ 1/3] - col_b: [ 1/3] - -join a: [|i#320-2=0; j#321-k#322-5=0|] b: [|3i#320-j#321+k#322-1=0|] -> [|3i#320-j#321+k#322-1=0|] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 1 0 0 100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 1 0 0 100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -1 0 0 -100] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -1 0 0 -100] -After normalizing we have m: -[ 1 -301/900 301/900 1/900] -[ 0 1/300 -1/300 299/300] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 0 0] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 0 0] -After normalizing we have m: -[ 1 -1/3 2/3 2/3] -[ 0 0 1 1] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ 3 -1 1 1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 3 -1 1 1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -Before rref_vec we have m: -[ 1 -1/3 1/3 1/3] -v: [ -3 1 -1 -1] - -Before normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ -3 1 -1 -1] -After normalizing we have m: -[ 1 -1/3 1/3 1/3] -[ 0 0 0 0] -[Warning][Assert] Assertion "(3 * i - j) + k == 1" is unknown. Expected: SUCCESS -> failed (tests/regression/63-affeq/01-rel_simple.c:17:5-17:40) -Before dim_remove m: -[ 1 -1/3 1/3 1/3] -Before reduce_col 0 of m: -[ 1 -1/3 1/3 1/3] - -After reduce_col 0 of m: -[ 0 0 0 0] - -Before reduce_col 1 of m: -[ 0 0 0 0] - -After reduce_col 1 of m: -[ 0 0 0 0] - -Before reduce_col 2 of m: -[ 0 0 0 0] - -After reduce_col 2 of m: -[ 0 0 0 0] - -Before del_cols cols_length=3 sorted_length=3 -m: -[ 0 0 0 0] - -After dim_remove m': -Before del_cols cols_length=3 sorted_length=3 -m: -[ 0 0 0 0] - -[Info][Deadcode] Logical lines of code (LLoC) summary: - live: 9 - dead: 0 - total lines: 9 -See result/index.xml From 0535677dcb85e0b6ba0d292fc44e259ee14314e4 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 13 Dec 2024 22:55:30 +0100 Subject: [PATCH 121/240] Add apply_with_c_f_preserves_zero --- .../affineEquality/arrayImplementation/arrayVector.ml | 2 ++ .../affineEquality/sparseImplementation/sparseVector.ml | 4 ++++ src/cdomains/affineEquality/vector.ml | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 0705853357..893bbda68b 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -133,4 +133,6 @@ module ArrayVector: AbstractVector = failwith "TODO / deprecated" let find_first_non_zero v = failwith "TODO" + + let apply_with_c_f_preserves_zero f c v = failwith "TODO" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index b895befc14..5294816914 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -183,6 +183,10 @@ module SparseVector: AbstractVector = if v.len <> v'.len then failwith "Unequal vector length" else of_list (List.map2 f (to_list v) (to_list v')) + let apply_with_c_f_preserves_zero f c v = + let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in + {entries = entries'; len = v.len} + let apply_with_c f c v = (* TODO: optimize! *) of_list @@ List.map (fun value -> f value c) (to_list v) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 11b33df151..62a0229743 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -30,6 +30,8 @@ sig val apply_with_c: (num -> num -> num) -> num -> t -> t + val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t + val apply_with_c_with: (num -> num -> num) -> num -> t -> unit val zero_vec: int -> t From c776a2bd0a843f780ddf56ace28d774d0e683b9f Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 13 Dec 2024 22:58:44 +0100 Subject: [PATCH 122/240] Changed some calls in Domain to zero preserving --- src/cdomains/apron/affineEqualityDomain.apron.ml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 63f785a861..d832af53d5 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -97,17 +97,17 @@ struct | Binop (Add, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in - Vector.map2 (+:) v1 v2 + Vector.map2_f_preserves_zero (+:) v1 v2 | Binop (Sub, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in - Vector.map2 (+:) v1 (neg @@ v2) + Vector.map2_f_preserves_zero (+:) v1 (neg @@ v2) | Binop (Mul, e1, e2, _, _) -> let v1 = convert_texpr e1 in let v2 = convert_texpr e2 in begin match to_constant_opt v1, to_constant_opt v2 with - | _, Some c -> Vector.apply_with_c ( *:) c v1 - | Some c, _ -> Vector.apply_with_c ( *:) c v2 + | _, Some c -> Vector.apply_with_c_f_preserves_zero ( *:) c v1 + | Some c, _ -> Vector.apply_with_c_f_preserves_zero ( *:) c v2 | _, _ -> raise NotLinear end | Binop _ -> raise NotLinear @@ -302,10 +302,10 @@ struct let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in let a_r, b_r = Matrix.get_row a r, Matrix.get_row b r in - let col_a = Vector.map2 (-:) col_a col_b in + let col_a = Vector.map2_f_preserves_zero (-:) col_a col_b in let col_a = Vector.rev col_a in let multiply_by_t m t = - Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2 (fun u j -> u -: (beta *: j)) x t) else x) m col_a; + Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2_f_preserves_zero (fun u j -> u -: (beta *: j)) x t) else x) m col_a; in Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) @@ -384,7 +384,7 @@ struct let j0 = Environment.dim_of_var env var in let a_j0 = Matrix.get_col x j0 in (*Corresponds to Axj0*) let b0 = Vector.nth b j0 in - let a_j0 = Vector.apply_with_c (/:) b0 a_j0 in (*Corresponds to Axj0/Bj0*) + let a_j0 = Vector.apply_with_c_f_preserves_zero (/:) b0 a_j0 in (*Corresponds to Axj0/Bj0*) let recalc_entries m rd_a = Matrix.map2 (fun x y -> Vector.map2i (fun j z d -> if j = j0 then y else if Vector.compare_length_with b (j + 1) > 0 then z -: y *: d From d3b18aa02d092e1df9f37d897dff241a063b6b52 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 14 Dec 2024 17:00:20 +0100 Subject: [PATCH 123/240] Change rref_matrix without append and normalize, still have to benchmark --- .../affineEquality/sparseImplementation/listMatrix.ml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 0dc0bf14ac..f0b9a08b32 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -302,11 +302,18 @@ module ListMatrix: AbstractMatrix = (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) (*TODO: OPTIMIZE!*) + (* let rref_matrix m1 m2 = let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in match normalize @@ append_matrices m1 m2 with | Some m -> let () = Printf.printf "After rref_matrix m, before removing zero rows:\n %s\n" (show m) in Some (remove_zero_rows m) | None -> let () = Printf.printf "No normalization for rref_matrix found" in None + *) + + let rref_matrix (m1 : t) (m2 : t) = + let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in + fst @@ List.fold_while (fun acc _ -> Option.is_some acc) + (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m let delete_row_with_pivots row pivots m2 = failwith "TODO" From eba9d498586c050fd2563d0ea637960972b19e3c Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 14 Dec 2024 17:12:25 +0100 Subject: [PATCH 124/240] Remove some warnings of deprecated code --- .../arrayImplementation/arrayVector.ml | 1 - .../sparseImplementation/listMatrix.ml | 38 ------------------- 2 files changed, 39 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 390ae07fdb..3d045c49aa 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -134,5 +134,4 @@ module ArrayVector: AbstractVector = let find_first_non_zero v = failwith "TODO" - end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index f0b9a08b32..7e9be147ae 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -85,9 +85,6 @@ module ListMatrix: AbstractMatrix = let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 - let sub_rows (minu : V.t) (subt : V.t) : V.t = - V.map2_f_preserves_zero (-:) minu subt - let div_row (row : V.t) (pivot : A.t) : V.t = V.map_f_preserves_zero (fun a -> a /: pivot) row @@ -174,18 +171,6 @@ module ListMatrix: AbstractMatrix = let init_with_vec v = [v] - let get_pivot_positions m = - List.mapi (fun i row -> V.findi (fun z -> z =: A.one) row) m - - let sub_rows (minu : V.t) (subt : V.t) : V.t = - V.map2_f_preserves_zero (-:) minu subt - - let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_f_preserves_zero (fun a -> a /: pivot) row - - let swap_rows m j k = - List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m - let normalize m = let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in let col_count = num_cols m in @@ -287,7 +272,6 @@ module ListMatrix: AbstractMatrix = let () = Printf.printf "After rref_vec we have m:\n%s\n" (show res) in Some res - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) @@ -309,15 +293,11 @@ module ListMatrix: AbstractMatrix = | Some m -> let () = Printf.printf "After rref_matrix m, before removing zero rows:\n %s\n" (show m) in Some (remove_zero_rows m) | None -> let () = Printf.printf "No normalization for rref_matrix found" in None *) - let rref_matrix (m1 : t) (m2 : t) = let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in fst @@ List.fold_while (fun acc _ -> Option.is_some acc) (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m - let delete_row_with_pivots row pivots m2 = - failwith "TODO" - let is_covered_by m1 m2 = let rec is_linearly_independent_rref v m = let pivot_opt = V.findi_val_opt ((<>:) A.zero) v in @@ -369,44 +349,26 @@ module ListMatrix: AbstractMatrix = (*If m is empty then v is simply normalized and returned*) failwith "deprecated" - let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v let rref_with m = failwith "deprecated" let reduce_col_with m j = failwith "deprecated" - let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j - - - let rref_with m = Timing.wrap "rref_with" rref_with m - let normalize_with m = failwith "deprecated" - let normalize_with m = Timing.wrap "normalize_with" normalize_with m - - let set_col_with m new_col n = failwith "deprecated" - let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n - let map2_with f m v = failwith "deprecated" - let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v - let map2i_with f m v = failwith "deprecated" - let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v - let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) failwith "deprecated" - - let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 - end \ No newline at end of file From dd0000eedd6e444dfae5f96517b60dbdd58c33e9 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 17 Dec 2024 15:23:45 +0100 Subject: [PATCH 125/240] Merge branch 'benchmarks' into master --- src/cdomains/affineEquality/sparseImplementation/listMatrix.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 3f910dafc0..9d951a9532 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -87,7 +87,7 @@ module ListMatrix: AbstractMatrix = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m let sub_scaled_row row1 row2 s = - V.map2_f_preserves_zero (fun x y -> x -: s *: y) row1 row2 + V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row1 row2 let reduce_col m j = if is_empty m then m From 2e80b94c1f75585a75a07d9efa1f7642518d010b Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 17 Dec 2024 15:37:32 +0100 Subject: [PATCH 126/240] removed second remove_nth --- .../sparseImplementation/sparseVector.ml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index f854bd550f..8994b2c20b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -38,23 +38,6 @@ module SparseVector: AbstractVector = if n >= v.len then v else {entries = List.take_while (fun (idx, _) -> idx < n) v.entries; len=n} - - (* Maybe use the function below instead of this one ?*) - let remove_nth v n = - let dec_idx v = - List.map (fun (a,b) -> (a-1, b)) v - in - let rec remove_nth_vec v n = - match v with - | x::xs -> - if fst x = n then dec_idx xs else - if fst x > n then dec_idx (x::xs) else - x::(remove_nth_vec xs n) - | [] -> [] - in - if n >= v.len then v else (*could be left out but maybe performance??*) - {entries = remove_nth_vec v.entries n; len = v.len - 1} - (* TODO: Which of both remmove_nth should we use *) let remove_nth v n = if n >= v.len then failwith "Out of bounds" From 1fa998f7c947c48276e65c73d49522782112a3e8 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 17 Dec 2024 16:01:34 +0100 Subject: [PATCH 127/240] Remove deprecated _with functions from Vector and Matrix interface --- .../arrayImplementation/arrayMatrix.ml | 17 ++-------- .../arrayImplementation/arrayVector.ml | 8 ----- src/cdomains/affineEquality/matrix.ml | 14 -------- .../sparseImplementation/listMatrix.ml | 32 ------------------- .../sparseImplementation/sparseVector.ml | 25 --------------- src/cdomains/affineEquality/vector.ml | 19 +---------- 6 files changed, 4 insertions(+), 111 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index a3d1199be9..ac21c08fbe 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -265,13 +265,13 @@ module ArrayMatrix: AbstractMatrix = (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) (*let v = V.to_array v in - if is_empty m then + if is_empty m then match Array.findi (fun x -> x <>: A.zero) v with | exception Not_found -> None | i -> if i = Array.length v - 1 then None else let v_i = v.(i) in Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) - else + else let pivot_elements = get_pivot_positions m in rref_vec_helper m pivot_elements v*) normalize @@ append_row m v @@ -355,10 +355,7 @@ module ArrayMatrix: AbstractMatrix = m.(i) <- V.to_array @@ f (V.of_array m.(i)) (V.nth v i) done - (* Deprecated - let map2 f m v = - let f' x y = V.to_array @@ f (V.of_array x) y in Array.map2 f' m (V.to_array v) - *) + let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v let map2 f m v = let () = Printf.printf "Before map2 we have m:\n%s\n" (show m) in @@ -367,8 +364,6 @@ module ArrayMatrix: AbstractMatrix = let () = Printf.printf "After map2 we have m:\n%s\n" (show m') in m' - let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v - let map2i_with f m v = if num_rows m = V.length v then Array.iter2i (fun i x y -> m.(i) <- V.to_array @@ f i (V.of_array x) y) m (V.to_array v) @@ -379,12 +374,6 @@ module ArrayMatrix: AbstractMatrix = let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v - (* Deprecated - let map2i f m v = - let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in - let range_array = Array.init (V.length v) Fun.id in - Array.map2 f' m (Array.combine range_array (V.to_array v)) - *) let map2i f m v = let () = Printf.printf "Before map2i m:\n%sv:%s\n" (show m) (V.show v) in let m' = copy m in diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 75cfab93d5..735246ada0 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -63,8 +63,6 @@ module ArrayVector: AbstractVector = let f' i = uncurry (f i) in Array.mapi f' (Array.combine v1 v2) (* TODO: iter2i? *) - let map2i_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f i x y) v1 v2 - let find2i f v1 v2 = Array.findi (uncurry f) (Array.combine v1 v2) (* TODO: iter2i? *) @@ -72,14 +70,8 @@ module ArrayVector: AbstractVector = let of_array v = v - let apply_with_c_with f c v = Array.modify (fun x -> f x c) v - - let rev_with v = Array.rev_in_place v - let rev v = Array.rev v - let map_with f v = Array.modify f v - let map f v = Array.map f v let map2_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f x y) v1 v2 diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index 3b45c12f91..0dffe8c44e 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -33,36 +33,22 @@ sig val reduce_col: t -> int -> t - val reduce_col_with: t -> int -> unit - val normalize: t -> t Option.t (*Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution*) - val normalize_with: t -> bool - val rref_vec: t -> vec -> t Option.t (* added to remove side effects in affineEqualityDomain*) - val rref_vec_with: t -> vec -> t Option.t - val rref_matrix: t -> t -> t Option.t (* this as well *) - val rref_matrix_with: t -> t -> t Option.t - val find_opt: (vec -> bool) -> t -> vec option val map2: (vec -> num -> vec) -> t -> vec -> t - val map2_with: (vec -> num -> vec) -> t -> vec -> unit - val map2: (vec -> num -> vec) -> t -> vec -> t (* why is this here twice??*) val map2i: (int -> vec-> num -> vec) -> t -> vec -> t - val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit - val set_col: t -> vec -> int -> t - val set_col_with: t -> vec -> int -> t - val init_with_vec: vec -> t val remove_zero_rows: t -> t diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 9d951a9532..72fac804ea 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -307,36 +307,4 @@ module ListMatrix: AbstractMatrix = let map2 f m v = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m - - - (* ------------------------- Deprecated ------------------------*) - - let rref_vec_with m v = - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) - (*m must be in rref form and contain the same num of cols as v*) - (*If m is empty then v is simply normalized and returned*) - failwith "deprecated" - - let rref_with m = - failwith "deprecated" - - let reduce_col_with m j = - failwith "deprecated" - - let normalize_with m = - failwith "deprecated" - - let set_col_with m new_col n = - failwith "deprecated" - - let map2_with f m v = - failwith "deprecated" - - let map2i_with f m v = - failwith "deprecated" - - let rref_matrix_with m1 m2 = - (*Similar to rref_vec_with but takes two matrices instead.*) - (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - failwith "deprecated" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 8994b2c20b..3c4a700f71 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -270,29 +270,4 @@ module SparseVector: AbstractVector = | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) in "["^list_str t^"\n" - - (* ------------------- Deprecated ------------------- *) - let mapi_with f v = - failwith "mapi_with deprecated" - - let map2i_with f v v' = - failwith "map2i_with deprecated" - - - let rev_with v = - failwith "rev_with deprecated" - - let map_with f v = - failwith "map_with deprecated" - - - let map2_with f v v' = - failwith "map2_with deprecated" - - let apply_with_c_with f m v = - failwith "apply_with_c_with deprecated" - - let set_nth_with f n num = ( - failwith "set_nth_with deprecated") - end diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 62a0229743..cf56a2da48 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -16,8 +16,6 @@ sig val set_nth: t -> int -> num -> t - val set_nth_with: t -> int -> num -> unit - val insert_val_at: int -> num -> t -> t val map_f_preserves_zero: (num -> num) -> t -> t @@ -32,8 +30,6 @@ sig val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t - val apply_with_c_with: (num -> num -> num) -> num -> t -> unit - val zero_vec: int -> t val is_zero_vec: t -> bool @@ -44,8 +40,6 @@ sig val map2: (num -> num -> num) -> t -> t -> t - val map2_with: (num -> num -> num) -> t -> t -> unit - val findi: (num -> bool) -> t -> int (* Returns optional tuple of position and value which was found*) @@ -57,8 +51,6 @@ sig val map: (num -> num) -> t -> t - val map_with: (num -> num) -> t -> unit - val map: (num -> num) -> t -> t val compare_length_with: t -> int -> int @@ -74,21 +66,12 @@ sig val exists: (num -> bool) -> t -> bool val exists2: (num -> num -> bool) -> t -> t -> bool - val rev: t -> t - - val rev_with: t -> unit - - val rev: t -> t - + val map2i: (int -> num -> num -> num) -> t -> t -> t - val map2i_with: (int -> num -> num -> num) -> t -> t -> unit - val mapi: (int -> num -> num) -> t -> t - val mapi_with: (int -> num -> num) -> t -> unit - val mapi: (int -> num -> num) -> t -> t val find2i: (num -> num -> bool) -> t -> t -> int From 1ea8040f690e464f10589fee47664a65517fdb7c Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 17 Dec 2024 16:02:15 +0100 Subject: [PATCH 128/240] Remove deprecated _with functions from Vector and Matrix interface --- src/cdomains/affineEquality/vector.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index cf56a2da48..b8f73d15b9 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -67,7 +67,7 @@ sig val exists2: (num -> num -> bool) -> t -> t -> bool val rev: t -> t - + val map2i: (int -> num -> num -> num) -> t -> t -> t val mapi: (int -> num -> num) -> t -> t @@ -88,5 +88,4 @@ sig (* Returns the part of the vector starting from index n*) val starting_from_nth : int -> t -> t - end \ No newline at end of file From fd5689abe6fbc056b823b4c5d7e82ff8e5bc204e Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 17 Dec 2024 16:23:33 +0100 Subject: [PATCH 129/240] commenting some functions --- .../sparseImplementation/listMatrix.ml | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 9d951a9532..eb46b17d3b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -89,6 +89,7 @@ module ListMatrix: AbstractMatrix = let sub_scaled_row row1 row2 s = V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row1 row2 + (* Reduces the jth column with the last row that has a non-zero element in this column. *) let reduce_col m j = if is_empty m then m else @@ -101,7 +102,7 @@ module ListMatrix: AbstractMatrix = match (find_pivot (num_rows m - 1) (List.rev m)) with | None -> m (* column is already filled with zeroes *) | Some (row_idx, pivot) -> - let pivot_row = List.nth m row_idx in + let pivot_row = List.nth m row_idx in (* use the pivot row to reduce all entries in column j to zero, then "delete" the pivot row *) List.mapi (fun idx row -> if idx = row_idx then V.zero_vec (num_cols m) @@ -214,10 +215,12 @@ module ListMatrix: AbstractMatrix = let insert_v_according_to_piv m v piv_idx pivot_positions = match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with | None -> append_row m v - | Some (row_idx, _) -> let (before, after) = List.split_at row_idx m in + | Some (row_idx, _) -> let (before, after) = List.split_at row_idx m in (* TODO: Optimize *) before @ (v :: after) - let rref_vec (m : t) (v : V.t) : t option = + (* This function yields the same result as appending v to m, normalizing and removing zero rows would. *) + (* m must be in rref form and must contain the same number of columns as v *) + let rref_vec m v = if is_empty m then (* In this case, v is normalized and returned *) match V.find_first_non_zero v with | None -> None @@ -237,7 +240,7 @@ module ListMatrix: AbstractMatrix = ) v pivot_positions in match V.find_first_non_zero v_after_elim with (* now we check for contradictions and finally insert v *) - | None -> Some m (* v is zero vector and was therefore already covered by zero *) + | None -> Some m (* v is zero vector and was therefore already covered by m *) | Some (idx, value) -> if idx = (num_cols m - 1) then None @@ -245,30 +248,19 @@ module ListMatrix: AbstractMatrix = let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v_after_elim in Some (insert_v_according_to_piv m normalized_v idx pivot_positions) - (*let rref_vec m v = - match normalize @@ append_matrices m (init_with_vec v) with - | None -> None - | Some m -> Some (remove_zero_rows m) *) - let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v - - (*Similar to rref_vec_with but takes two matrices instead.*) - (*ToDo Could become inefficient for large matrices since pivot_elements are always recalculated + many row additions*) - (*TODO: OPTIMIZE!*) - (* - let rref_matrix m1 m2 = - match normalize @@ append_matrices m1 m2 with - | Some m -> Some (remove_zero_rows m) - | None -> None - - *) + + (* This should yield the same result as appending m2 to m1, normalizing and removing zero rows. However, it is usually faster. *) + (* Both input matrices are assumed to be in rref form *) let rref_matrix (m1 : t) (m2 : t) = let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in fst @@ List.fold_while (fun acc _ -> Option.is_some acc) - (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m + (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m (* TODO: pivot_positions are recalculated at each step, but since they need to be adjusted after each step it might not make sense to keep track of them here.*) let rref_matrix m1 m2 = Timing.wrap "rref_matrix" (rref_matrix m1) m2 + (* Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) + (* Both input matrices must be in rref form! *) let is_covered_by m1 m2 = let rec is_linearly_independent_rref v m = let pivot_opt = V.findi_val_opt ((<>:) A.zero) v in From 618643553ec58172ef43d4a46be7cad44b7004ca Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 17 Dec 2024 17:02:27 +0100 Subject: [PATCH 130/240] is_cons_vec --- .../arrayImplementation/arrayVector.ml | 22 ++++++++++--------- .../sparseImplementation/sparseVector.ml | 6 +++++ src/cdomains/affineEquality/vector.ml | 2 ++ .../apron/affineEqualityDomain.apron.ml | 5 ++--- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 735246ada0..a95e764f16 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -57,6 +57,8 @@ module ArrayVector: AbstractVector = let is_zero_vec v = not (Array.exists (fun x -> x <>: A.zero) v) + let is_const_vec v = failwith "Never implemented!" + let nth = Array.get let map2i f v1 v2 = @@ -104,29 +106,29 @@ module ArrayVector: AbstractVector = let find_opt f v = - failwith "TODO" + failwith "Never implemented!" - let map_f_preserves_zero f v = failwith "TODO" - let map2_f_preserves_zero f v1 v2 = failwith "TODO" + let map_f_preserves_zero f v = failwith "Never implemented!" + let map2_f_preserves_zero f v1 v2 = failwith "Never implemented!" let fold_left_f_preserves_zero f acc v = - failwith "TODO" + failwith "Never implemented!" let fold_left2_f_preserves_zero f acc v v' = - failwith "TODO" + failwith "Never implemented!" let findi_val_opt f v = - failwith "TODO" + failwith "Never implemented!" let exists2 f v1 v1 = - failwith "TODO / deprecated" + failwith "Never implemented!" let starting_from_nth n v = - failwith "TODO / deprecated" + failwith "Never implemented!" let find_first_non_zero v = - failwith "TODO" + failwith "Never implemented!" let apply_with_c_f_preserves_zero f c v = - failwith "TODO" + failwith "Never implemented!" end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 3c4a700f71..6589296884 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -149,6 +149,12 @@ module SparseVector: AbstractVector = let is_zero_vec v = (v.entries = []) + let is_const_vec v = + match v.entries with + | [] -> false + | (xi,xv)::[] -> if xi = v.len - 1 then false else true + | _ -> false + let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") else diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index b8f73d15b9..61a18ff7c2 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -34,6 +34,8 @@ sig val is_zero_vec: t -> bool + val is_const_vec: t -> bool + val nth: t -> int -> num val length: t -> int diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index d832af53d5..15fc35fa59 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -66,9 +66,8 @@ struct let open Apron.Texpr1 in let exception NotLinear in let zero_vec = Vector.zero_vec @@ Environment.size t.env + 1 in - let neg v = Vector.map Mpqf.neg v in - let is_const_vec v = Vector.compare_length_with (Vector.filteri (fun i x -> (*Inefficient*) - Vector.compare_length_with v (i + 1) > 0 && x <>: Mpqf.zero) v) 1 = 0 + let neg v = Vector.map_f_preserves_zero Mpqf.neg v in + let is_const_vec = Vector.is_const_vec in let rec convert_texpr = function (*If x is a constant, replace it with its const. val. immediately*) From d42bf5fc0b8298306d177842766eed482219a414 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 17 Dec 2024 17:34:14 +0100 Subject: [PATCH 131/240] replace the last findi_val_opt --- .../affineEquality/sparseImplementation/listMatrix.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index fd073c4721..1751d364f9 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -263,12 +263,12 @@ module ListMatrix: AbstractMatrix = (* Both input matrices must be in rref form! *) let is_covered_by m1 m2 = let rec is_linearly_independent_rref v m = - let pivot_opt = V.findi_val_opt ((<>:) A.zero) v in + let pivot_opt = V.find_first_non_zero v in match pivot_opt with | None -> false (* When we found no pivot, the vector is already A.zero. *) | Some (pivot_id, pivot) -> let m' = List.drop_while (fun v2 -> - match V.findi_val_opt ((<>:) A.zero) v2 with + match V.find_first_non_zero v2 with | None -> true (* In this case, m2 only has zero rows after that *) | Some (idx', _) -> idx' < pivot_id ) m in @@ -283,7 +283,7 @@ module ListMatrix: AbstractMatrix = match m1 with | [] -> true | v1::vs1 -> - let first_non_zero = V.findi_val_opt ((<>:) A.zero) v1 in + let first_non_zero = V.find_first_non_zero v1 in match first_non_zero with | None -> true (* vs1 must also be zero-vectors because of rref *) | Some (idx, _) -> From 0088812199de5642c675c3a2ed0e5b1b313b265d Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 17 Dec 2024 17:37:08 +0100 Subject: [PATCH 132/240] ein paar maps ausgetauscht --- .../arrayImplementation/arrayVector.ml | 3 ++ .../sparseImplementation/sparseVector.ml | 34 ++++++++++++------- src/cdomains/affineEquality/vector.ml | 4 +++ .../apron/affineEqualityDomain.apron.ml | 4 +-- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index a95e764f16..911e96fd4b 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -111,6 +111,9 @@ module ArrayVector: AbstractVector = let map_f_preserves_zero f v = failwith "Never implemented!" let map2_f_preserves_zero f v1 v2 = failwith "Never implemented!" + let mapi_f_preserves_zero f v = failwith "Never implemented!" + let map2i_f_preserves_zero f v v' = failwith "Never implemented!" + let fold_left_f_preserves_zero f acc v = failwith "Never implemented!" diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 6589296884..0640e31a86 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -95,6 +95,9 @@ module SparseVector: AbstractVector = ) [] v.entries in {entries = entries'; len = v.len + 1} + let map f v = + of_list (List.map f (to_list v)) + let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( fun (idx, value) -> let new_val = f value in @@ -103,6 +106,10 @@ module SparseVector: AbstractVector = let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v + let map2 f v v' = (* TODO: Optimize! *) + if v.len <> v'.len then failwith "Unequal vector length" else + of_list (List.map2 f (to_list v) (to_list v')) + (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) let map2_f_preserves_zero f v1 v2 = let f_rem_zero acc idx e1 e2 = @@ -125,6 +132,20 @@ module SparseVector: AbstractVector = let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 + let map2i f v v' = (* TODO: optimize! *) + of_list (List.map2i f (to_list v) (to_list v')) + + let map2i_f_preserves_zero f v v' = failwith "TODO" + + let mapi f v = (* TODO: optimize! *) + of_list (List.mapi f (to_list v)) + + let mapi_f_preserves_zero f v = + let entries' = List.filter_map ( + fun (idx, value) -> let new_val = f idx value in + if new_val = A.zero then None else Some (idx, new_val)) v.entries in + {entries = entries'; len = v.len} + let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries @@ -168,10 +189,6 @@ module SparseVector: AbstractVector = let length v = v.len - let map2 f v v' = (* TODO: Optimize! *) - if v.len <> v'.len then failwith "Unequal vector length" else - of_list (List.map2 f (to_list v) (to_list v')) - let apply_with_c_f_preserves_zero f c v = let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} @@ -206,9 +223,6 @@ module SparseVector: AbstractVector = let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v - let map f v = - of_list (List.map f (to_list v)) - let compare_length_with v n = Int.compare v.len n @@ -234,12 +248,6 @@ module SparseVector: AbstractVector = let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in {entries = entries'; len = v.len} - let map2i f v v' = (* TODO: optimize! *) - of_list (List.map2i f (to_list v) (to_list v')) - - let mapi f v = (* TODO: optimize! *) - of_list (List.mapi f (to_list v)) - let find2i f v v' = (* TODO: optimize! *) fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 61a18ff7c2..956c6aa1ea 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -72,8 +72,12 @@ sig val map2i: (int -> num -> num -> num) -> t -> t -> t + val map2i_f_preserves_zero: (int -> num -> num -> num) -> t -> t -> t + val mapi: (int -> num -> num) -> t -> t + val mapi_f_preserves_zero: (int -> num -> num) -> t -> t + val mapi: (int -> num -> num) -> t -> t val find2i: (num -> num -> bool) -> t -> t -> int diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 15fc35fa59..2e9676382f 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -286,7 +286,7 @@ struct if s >= Matrix.num_cols a then a else let case_two a r col_b = let a_r = Matrix.get_row a r in - let a = Matrix.map2i (fun i x y -> if i < r then Vector.map2 (fun u j -> u +: y *: j) x a_r else x) a col_b; in + let a = Matrix.map2i (fun i x y -> if i < r then Vector.map2_f_preserves_zero (fun u j -> u +: y *: j) x a_r else x) a col_b; in Matrix.remove_row a r in let case_three a b col_a col_b max = @@ -397,7 +397,7 @@ struct let assign_invertible_rels x var b env = Timing.wrap "assign_invertible" (assign_invertible_rels x var b) env in let assign_uninvertible_rel x var b env = let b_length = Vector.length b in - let b = Vector.mapi (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b in + let b = Vector.mapi_f_preserves_zero (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b in let b = Vector.set_nth b (Environment.dim_of_var env var) Mpqf.one in match Matrix.rref_vec x b with | None -> bot () From 92802e5dbe63cd43a8812049caef5846fe74a383 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Wed, 18 Dec 2024 14:47:59 +0100 Subject: [PATCH 133/240] Optimize non zero-preserving Vector.map and Vector.map2i --- .../sparseImplementation/sparseVector.ml | 37 ++++++++- .../sparseMatrixImplementationTest.ml | 83 ++++++++++++++----- 2 files changed, 98 insertions(+), 22 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 0640e31a86..aab73454a4 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -96,7 +96,19 @@ module SparseVector: AbstractVector = {entries = entries'; len = v.len + 1} let map f v = + (* of_list (List.map f (to_list v)) + *) + let f_zero = f A.zero in + let rec map2_helper acc vec i = + match vec with + | [] when i >= v.len || f_zero =: A.zero -> List.rev acc + | [] -> map2_helper ((i, f_zero) :: acc) [] (i + 1) + | (idx, value) :: xs when idx = i -> let new_val = f value in if new_val <>: A.zero then map2_helper ((idx, new_val) :: acc) xs (i + 1) else map2_helper acc xs (i + 1) + | (idx, _) :: xs when idx > i -> if f_zero <>: A.zero then map2_helper ((i, f_zero) :: acc) vec (i + 1) else map2_helper acc vec (i + 1) + | (_, _) :: _ -> failwith "This should not happen" + in + {entries = map2_helper [] v.entries 0; len = v.len} let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( @@ -132,8 +144,29 @@ module SparseVector: AbstractVector = let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 - let map2i f v v' = (* TODO: optimize! *) - of_list (List.map2i f (to_list v) (to_list v')) + let map2i f v1 v2 = (* TODO: optimize! *) + if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else + (*of_list (List.map2i f (to_list v) (to_list v'))*) + let f_rem_zero idx acc e1 e2 = + let r = f idx e1 e2 in + if r =: A.zero then acc else (idx, r)::acc + in + let rec aux acc vec1 vec2 i = + match vec1, vec2 with + | [], [] when i = v1.len -> acc + | [], [] -> aux (f_rem_zero i acc A.zero A.zero) [] [] (i + 1) + | [], (yidx, yval)::ys when i = yidx -> aux (f_rem_zero i acc A.zero yval) [] ys (i + 1) + | (xidx, xval)::xs, [] when i = xidx -> aux (f_rem_zero i acc xval A.zero) xs [] (i + 1) + | [], (_, _)::_ | (_, _)::_, [] -> aux (f_rem_zero i acc A.zero A.zero) vec1 vec2 (i + 1) (* When one vec is not zero_vec, but has implicit zeroes at front *) + | (xidx, xval)::xs, (yidx, yval)::ys -> + if xidx <> i && yidx <> i then aux (f_rem_zero i acc A.zero A.zero) vec1 vec2 (i+1) (* When both vectors have implicit zeroes at front *) + else + match xidx - yidx with (* Here at least one of the idx is i, which is the smaller one *) + | d when d < 0 -> aux (f_rem_zero i acc xval A.zero) xs vec2 (i + 1) + | d when d > 0 -> aux (f_rem_zero i acc A.zero yval) vec1 ys (i + 1) + | _ -> aux (f_rem_zero i acc xval yval) xs ys (i + 1) + in + {entries = List.rev (aux [] v1.entries v2.entries 0); len = v1.len} let map2i_f_preserves_zero f v v' = failwith "TODO" diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 0fe269d15e..b562760a45 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -8,9 +8,12 @@ open SparseVector open ListMatrix open ArrayVector open ArrayMatrix +open ConvenienceOps + module D = SharedFunctions.Mpqf module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) +include ConvenienceOps(D) (** Shorthands for common functions. *) let int x = D.of_int x @@ -303,25 +306,65 @@ let int_domain_to_rational _ = in normalize_and_assert int_matrix normalized_matrix -let tests = - "SparseMatrixImplementationTest" - >::: [ - "can solve a standard normalization" >:: standard_normalize; - "does sort already reduzed" >:: does_just_sort; - "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - "can handle float domain" >:: does_handle_floats; - "can handle fraction domain" >:: does_handle_fractions; - "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" >:: does_not_change_normalized_matrix; - "m1 is covered by m2" >:: is_covered_by_simple; - "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; - "zero vector is covered by m2" >:: is_zero_vec_covered; - "m1 is not covered by m2" >:: is_not_covered; - "m1 is covered by m2 with big matrix" >:: is_covered_big; - "does not change an empty matrix" >:: normalize_empty; - "can correctly normalize a two column matrix" >:: normalize_two_columns; - "can handle a rational solution" >:: int_domain_to_rational; - "m1 is covered by m2 with big matrix2" >:: is_covered_big2; - ] + +let vectorMap2i _ = + let v1 = Vector.of_list [int 0; int 1; int 0; int 2; int 3; int 0; int 4; int 0; int 1] in + let v2 = Vector.of_list [int 4; int 0; int 0; int 0; int 5; int 6; int 0; int 0; int 2] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [int 0; int 1; int 0; int 6; int 32; int 30; int 24; int 0; int 24] in + assert_equal expected result + + +let vectorMap2i_empty _ = + let v1 = Vector.of_list [] in + let v2 = Vector.of_list [] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [] in + assert_equal expected result + +let vectorMap2i_one_zero _ = + let v1 = Vector.of_list [int 0; int 0; int 0; int 0] in + let v2 = Vector.of_list [int 1; int 2; int 3; int 4] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [int 0; int 2; int 6; int 12] in + assert_equal expected result + +let vectorMap _ = + let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 3; int 4; int 0; int 0; int 5] in + let result = Vector.map (fun x -> x +: int 1) v1 in + let expected = Vector.of_list [int 1; int 2; int 3; int 1; int 1; int 4; int 5; int 1; int 1; int 6] in + assert_equal expected result + +let vectorMap_zero_preserving_normal _ = + let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 4; int 5; int 0; int 0;] in + let result = Vector.map (fun x -> x *: x) v1 in + let expected = Vector.of_list [int 0; int 1; int 4; int 0; int 0; int 16; int 25; int 0; int 0;] in + assert_equal expected result + + let tests = + "SparseMatrixImplementationTest" + >::: [ + "can solve a standard normalization" >:: standard_normalize; + "does sort already reduzed" >:: does_just_sort; + "does eliminate dependent rows" >:: does_eliminate_dependent_rows; + "can handle float domain" >:: does_handle_floats; + "can handle fraction domain" >:: does_handle_fractions; + "does negate negative matrix" >:: does_negate_negative; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; + "m1 is covered by m2" >:: is_covered_by_simple; + "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; + "zero vector is covered by m2" >:: is_zero_vec_covered; + "m1 is not covered by m2" >:: is_not_covered; + "m1 is covered by m2 with big matrix" >:: is_covered_big; + "does not change an empty matrix" >:: normalize_empty; + "can correctly normalize a two column matrix" >:: normalize_two_columns; + "can handle a rational solution" >:: int_domain_to_rational; + "m1 is covered by m2 with big matrix2" >:: is_covered_big2; + "map2i two vectors" >:: vectorMap2i; + "map2i two empty vectors" >:: vectorMap2i_empty; + "map2i one zero vector" >:: vectorMap2i_one_zero; + "map one vector" >:: vectorMap; + "map zero preserving normal" >:: vectorMap_zero_preserving_normal; + ] let () = run_test_tt_main tests From 2c8901f4fb9e61fa71d707311f4758147c4039ce Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 19 Dec 2024 10:19:33 +0100 Subject: [PATCH 134/240] added test from lin2vareq to affeq that found mistake in dim_add --- tests/regression/63-affeq/21-function_call.c | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/regression/63-affeq/21-function_call.c diff --git a/tests/regression/63-affeq/21-function_call.c b/tests/regression/63-affeq/21-function_call.c new file mode 100644 index 0000000000..723b75e14a --- /dev/null +++ b/tests/regression/63-affeq/21-function_call.c @@ -0,0 +1,21 @@ +// SKIP PARAM: --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none +// This test was added from 77-lin2vareq because it found mistakes in dim_add that weren't detected by the other tests +#include + +int check_equal(int x, int y, int z) { + __goblint_check(x == y); + __goblint_check(z == y); + __goblint_check(x == z); + return 8; +} + +int main(void) { + int x, y, z; + + y = x; + z = y; + + check_equal(x, y, z); + + return 0; +} From 4411280f9fe552bc361cc3471d2ec34ff8f6b4f2 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 19 Dec 2024 15:37:19 +0100 Subject: [PATCH 135/240] Implement zero preserving Array Vector functions by calling normal functions --- .../arrayImplementation/arrayMatrix.ml | 3 ++- .../arrayImplementation/arrayVector.ml | 20 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index ac21c08fbe..af849eef0c 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -318,7 +318,8 @@ module ArrayMatrix: AbstractMatrix = let is_covered_by m1 m2 = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) (*Both input matrices must be in rref form!*) - let () = Printf.printf "Is m1 covered by m2?\n m1:\n%sm2:\n%s" (show m1) (show m2) in + let () = Printf.printf "is_covered_by m1: \n%s " (show m1) in + let () = Printf.printf "is_covered_by m2 \n%s " (show m2) in if num_rows m1 > num_rows m2 then false else let p2 = lazy (get_pivot_positions m2) in try ( diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 911e96fd4b..e90a5afbce 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -57,7 +57,9 @@ module ArrayVector: AbstractVector = let is_zero_vec v = not (Array.exists (fun x -> x <>: A.zero) v) - let is_const_vec v = failwith "Never implemented!" + let is_const_vec v = + compare_length_with (filteri (fun i x -> (*Inefficient*) + compare_length_with v (i + 1) > 0 && x <>: A.zero) v) 1 = 0 let nth = Array.get @@ -108,11 +110,17 @@ module ArrayVector: AbstractVector = let find_opt f v = failwith "Never implemented!" - let map_f_preserves_zero f v = failwith "Never implemented!" - let map2_f_preserves_zero f v1 v2 = failwith "Never implemented!" + let map_f_preserves_zero f v = + map f v - let mapi_f_preserves_zero f v = failwith "Never implemented!" - let map2i_f_preserves_zero f v v' = failwith "Never implemented!" + let map2_f_preserves_zero f v1 v2 = + map2 f v1 v2 + + let mapi_f_preserves_zero f v = + mapi f v + + let map2i_f_preserves_zero f v v' = + map2i f v v' let fold_left_f_preserves_zero f acc v = failwith "Never implemented!" @@ -133,5 +141,5 @@ module ArrayVector: AbstractVector = failwith "Never implemented!" let apply_with_c_f_preserves_zero f c v = - failwith "Never implemented!" + apply_with_c f c v end \ No newline at end of file From 012104f392ed1879ad8806c8b392102293bc28a6 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 19 Dec 2024 16:44:40 +0100 Subject: [PATCH 136/240] assert_rref --- .../sparseImplementation/listMatrix.ml | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 1751d364f9..6e7affc654 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -151,7 +151,7 @@ module ListMatrix: AbstractMatrix = let init_with_vec v = [v] - + let normalize m = let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = @@ -211,6 +211,25 @@ module ListMatrix: AbstractMatrix = | Some (pivot_col, _) -> (i, pivot_col) :: acc ) [] m + let assert_rref m = + let pivot_l = get_pivot_positions m in + let rec validate m i = + match m with + | [] -> () + | v::vs when (V.is_zero_vec v) -> + if List.exists (fun v -> not @@ V.is_zero_vec v) vs + then raise (Invalid_argument "Matrix not in rref: zero row!") + else () + | v::vs -> + let rec validate_vec pl = + match pivot_l with + | [] -> true + | (pr, pc)::ps -> + let target = if pr <> i then A.zero else A.one in + if V.nth v pc <> target then false else validate_vec ps + in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") + in validate m 0 + (* Inserts the vector v with pivot at piv_idx at the correct position in m. m has to be in rref form. *) let insert_v_according_to_piv m v piv_idx pivot_positions = match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with From 37190f4fe6ddbc6b59a6e91a29ec51fe2df2c6fa Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 19 Dec 2024 16:44:54 +0100 Subject: [PATCH 137/240] assert_rref --- .../affineEquality/sparseImplementation/listMatrix.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6e7affc654..f5e91f092d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -151,7 +151,7 @@ module ListMatrix: AbstractMatrix = let init_with_vec v = [v] - + let normalize m = let col_count = num_cols m in let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = @@ -268,7 +268,7 @@ module ListMatrix: AbstractMatrix = Some (insert_v_according_to_piv m normalized_v idx pivot_positions) let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v - + (* This should yield the same result as appending m2 to m1, normalizing and removing zero rows. However, it is usually faster. *) (* Both input matrices are assumed to be in rref form *) let rref_matrix (m1 : t) (m2 : t) = From d7da9c759c9b07196fdafe1f0c125169bce8f430 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 19 Dec 2024 17:01:41 +0100 Subject: [PATCH 138/240] small bugfix assert_rref --- src/cdomains/affineEquality/sparseImplementation/listMatrix.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index f5e91f092d..263ac8addf 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -226,7 +226,7 @@ module ListMatrix: AbstractMatrix = | [] -> true | (pr, pc)::ps -> let target = if pr <> i then A.zero else A.one in - if V.nth v pc <> target then false else validate_vec ps + if V.nth v pc <>: target then false else validate_vec ps in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") in validate m 0 From bb151813d27f50ca03df1dc4204256e6a07c1e83 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 19 Dec 2024 21:09:50 +0100 Subject: [PATCH 139/240] Bugfix rref_vec using reduce_col_with_vec --- .../sparseImplementation/listMatrix.ml | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 263ac8addf..e004eb9071 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -113,16 +113,6 @@ module ListMatrix: AbstractMatrix = sub_scaled_row row pivot_row s) ) m - let reduce_col_with_vec m j v = - let pivot_element = V.nth v j in - if pivot_element = A.zero then m - else List.mapi (fun idx row -> - let row_value = V.nth row j in - if row_value =: A.zero then row - else (let s = row_value /: pivot_element in - V.map2_f_preserves_zero (fun x y -> x -: s *: y) row v) - ) m - let del_col m j = if num_cols m = 1 then empty () else @@ -202,14 +192,6 @@ module ListMatrix: AbstractMatrix = let m' = main_loop m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - (* This function return a tuple of row index and pivot position (column) in m *) - (* TODO: maybe we could use a Hashmap instead of a list? *) - let get_pivot_positions (m : t) : (int * int) list = - List.rev @@ List.fold_lefti ( - fun acc i row -> match V.find_first_non_zero row with - | None -> acc - | Some (pivot_col, _) -> (i, pivot_col) :: acc - ) [] m let assert_rref m = let pivot_l = get_pivot_positions m in @@ -230,11 +212,33 @@ module ListMatrix: AbstractMatrix = in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") in validate m 0 - (* Inserts the vector v with pivot at piv_idx at the correct position in m. m has to be in rref form. *) + (* This function return a tuple of row index and pivot position (column) in m *) + (* TODO: maybe we could use a Hashmap instead of a list? *) + let get_pivot_positions (m : t) : (int * int) list = + List.rev @@ List.fold_lefti ( + fun acc i row -> match V.find_first_non_zero row with + | None -> acc + | Some (pivot_col, _) -> (i, pivot_col) :: acc + ) [] m + + (* Sets the jth column to zero by subtracting multiples of v *) + let reduce_col_with_vec m j v = + let pivot_element = V.nth v j in + if pivot_element = A.zero then m + else List.mapi (fun idx row -> + let row_value = V.nth row j in + if row_value =: A.zero then row + else (let s = row_value /: pivot_element in + V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row v) + ) m + + (* Inserts the vector v with pivot at piv_idx at the correct position in m. m has to be in rref form and v is only <>: A.zero on piv_idx or idx not included in piv_positions *) let insert_v_according_to_piv m v piv_idx pivot_positions = + let reduced_m = reduce_col_with_vec m piv_idx v in match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with - | None -> append_row m v - | Some (row_idx, _) -> let (before, after) = List.split_at row_idx m in (* TODO: Optimize *) + | None -> append_row reduced_m v + | Some (row_idx, _) -> + let (before, after) = List.split_at row_idx reduced_m in (* TODO: Optimize *) before @ (v :: after) (* This function yields the same result as appending v to m, normalizing and removing zero rows would. *) From 0678f668187422405be2739484f5dc7db0cda7e3 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 19 Dec 2024 21:24:06 +0100 Subject: [PATCH 140/240] Change order of functions because of compilation error --- .../sparseImplementation/listMatrix.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index e004eb9071..8d80aae50a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -193,6 +193,15 @@ module ListMatrix: AbstractMatrix = if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) + (* This function return a tuple of row index and pivot position (column) in m *) + (* TODO: maybe we could use a Hashmap instead of a list? *) + let get_pivot_positions (m : t) : (int * int) list = + List.rev @@ List.fold_lefti ( + fun acc i row -> match V.find_first_non_zero row with + | None -> acc + | Some (pivot_col, _) -> (i, pivot_col) :: acc + ) [] m + let assert_rref m = let pivot_l = get_pivot_positions m in let rec validate m i = @@ -212,15 +221,6 @@ module ListMatrix: AbstractMatrix = in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") in validate m 0 - (* This function return a tuple of row index and pivot position (column) in m *) - (* TODO: maybe we could use a Hashmap instead of a list? *) - let get_pivot_positions (m : t) : (int * int) list = - List.rev @@ List.fold_lefti ( - fun acc i row -> match V.find_first_non_zero row with - | None -> acc - | Some (pivot_col, _) -> (i, pivot_col) :: acc - ) [] m - (* Sets the jth column to zero by subtracting multiples of v *) let reduce_col_with_vec m j v = let pivot_element = V.nth v j in From 3b49ba558fe548af158450d4c8f755a0dcca8f1f Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 21 Dec 2024 10:04:28 +0100 Subject: [PATCH 141/240] Organize Vector and Matrix interface --- .../apron/affineEqualityAnalysis.apron.ml | 1 + src/cdomains/affineEquality/matrix.ml | 48 ++++++----- .../sparseImplementation/listMatrix.ml | 3 + .../sparseImplementation/sparseVector.ml | 1 - src/cdomains/affineEquality/vector.ml | 81 +++++++++---------- 5 files changed, 66 insertions(+), 68 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index 80d3b32874..fcb12606da 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -15,6 +15,7 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in + let module AD_A = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in (* TODO: Remove this! Just to suppress warning *) let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index 0dffe8c44e..b3433ee899 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -5,58 +5,56 @@ sig type vec type t [@@deriving eq, ord, hash] + val show: t -> string + + val copy: t -> t + val empty: unit -> t (* TODO: needs unit? *) val is_empty: t -> bool - val show: t -> string + val num_rows: t -> int - val add_empty_columns: t -> int array -> t + val num_cols: t -> int + + val init_with_vec: vec -> t val append_row: t -> vec -> t val get_row: t -> int -> vec - val del_col: t -> int -> t - - val del_cols: t -> int array -> t - val remove_row: t -> int -> t - val get_col: t -> int -> vec - - val append_matrices: t -> t -> t - - val num_rows: t -> int + val remove_zero_rows: t -> t - val num_cols: t -> int + val swap_rows: t -> int -> int -> t - val reduce_col: t -> int -> t + val add_empty_columns: t -> int array -> t - val normalize: t -> t Option.t (*Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution*) + val get_col: t -> int -> vec - val rref_vec: t -> vec -> t Option.t (* added to remove side effects in affineEqualityDomain*) + val set_col: t -> vec -> int -> t - val rref_matrix: t -> t -> t Option.t (* this as well *) + val del_col: t -> int -> t - val find_opt: (vec -> bool) -> t -> vec option + val del_cols: t -> int array -> t val map2: (vec -> num -> vec) -> t -> vec -> t - val map2: (vec -> num -> vec) -> t -> vec -> t (* why is this here twice??*) - val map2i: (int -> vec-> num -> vec) -> t -> vec -> t - val set_col: t -> vec -> int -> t + val find_opt: (vec -> bool) -> t -> vec option - val init_with_vec: vec -> t + val append_matrices: t -> t -> t - val remove_zero_rows: t -> t + val reduce_col: t -> int -> t - val is_covered_by: t -> t -> bool + val normalize: t -> t Option.t (*Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution*) - val copy: t -> t + val rref_vec: t -> vec -> t Option.t - val swap_rows: t -> int -> int -> t + val rref_matrix: t -> t -> t Option.t + + val is_covered_by: t -> t -> bool end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 8d80aae50a..e8bc108d91 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -221,6 +221,9 @@ module ListMatrix: AbstractMatrix = in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") in validate m 0 + (* TODO: Remove this! Just to suppress warning *) + let () = assert_rref (empty ()) + (* Sets the jth column to zero by subtracting multiples of v *) let reduce_col_with_vec m j v = let pivot_element = V.nth v j in diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index aab73454a4..c300b22ceb 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -3,7 +3,6 @@ open RatOps open ConvenienceOps open BatList -open BatArray open Batteries module List = BatList diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 956c6aa1ea..799df35c0e 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -6,29 +6,23 @@ sig val show: t -> string - val keep_vals: t -> int -> t - - val remove_nth: t -> int -> t - - val remove_at_indices: t -> int list -> t - - val insert_zero_at_indices: t -> (int * int) list -> int -> t + val copy: t -> t - val set_nth: t -> int -> num -> t + val of_list: num list -> t - val insert_val_at: int -> num -> t -> t + val of_array: num array -> t - val map_f_preserves_zero: (num -> num) -> t -> t + val of_sparse_list: int -> (int * num) list -> t - val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t + val to_list: t -> num list - val fold_left_f_preserves_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc + val to_array: t -> num array - val fold_left2_f_preserves_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc + val to_sparse_list: t -> (int * num) list - val apply_with_c: (num -> num -> num) -> num -> t -> t + val length: t -> int - val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t + val compare_length_with: t -> int -> int val zero_vec: int -> t @@ -38,60 +32,63 @@ sig val nth: t -> int -> num - val length: t -> int - - val map2: (num -> num -> num) -> t -> t -> t + val set_nth: t -> int -> num -> t - val findi: (num -> bool) -> t -> int + val insert_val_at: int -> num -> t -> t - (* Returns optional tuple of position and value which was found*) - val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t + val insert_zero_at_indices: t -> (int * int) list -> int -> t - val find_first_non_zero : t -> (int * num) option + val remove_nth: t -> int -> t - val find_opt: (num -> bool) -> t -> num Option.t + val remove_at_indices: t -> int list -> t - val map: (num -> num) -> t -> t + val keep_vals: t -> int -> t - val map: (num -> num) -> t -> t + (* Returns the part of the vector starting from index n*) + val starting_from_nth : int -> t -> t - val compare_length_with: t -> int -> int + val find_opt: (num -> bool) -> t -> num Option.t - val of_list: num list -> t + val findi: (num -> bool) -> t -> int - val to_list: t -> num list + val find2i: (num -> num -> bool) -> t -> t -> int - val filteri: (int -> num -> bool) -> t -> t + (* Returns optional tuple of position and value which was found*) + val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t - val append: t -> t -> t + val find_first_non_zero : t -> (int * num) option val exists: (num -> bool) -> t -> bool val exists2: (num -> num -> bool) -> t -> t -> bool - val rev: t -> t - val map2i: (int -> num -> num -> num) -> t -> t -> t + val filteri: (int -> num -> bool) -> t -> t - val map2i_f_preserves_zero: (int -> num -> num -> num) -> t -> t -> t + val map: (num -> num) -> t -> t + + val map_f_preserves_zero: (num -> num) -> t -> t val mapi: (int -> num -> num) -> t -> t val mapi_f_preserves_zero: (int -> num -> num) -> t -> t - val mapi: (int -> num -> num) -> t -> t + val map2: (num -> num -> num) -> t -> t -> t - val find2i: (num -> num -> bool) -> t -> t -> int + val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t - val to_array: t -> num array + val map2i: (int -> num -> num -> num) -> t -> t -> t - val of_array: num array -> t + val map2i_f_preserves_zero: (int -> num -> num -> num) -> t -> t -> t - val copy: t -> t + val fold_left_f_preserves_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc - val of_sparse_list: int -> (int * num) list -> t + val fold_left2_f_preserves_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc - val to_sparse_list: t -> (int * num) list + val apply_with_c: (num -> num -> num) -> num -> t -> t - (* Returns the part of the vector starting from index n*) - val starting_from_nth : int -> t -> t + val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t + + val rev: t -> t + + val append: t -> t -> t end \ No newline at end of file From 93463f2008e68b2acae2546f816e823894d1fa65 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 21 Dec 2024 18:05:51 +0100 Subject: [PATCH 142/240] Bugfix Vector is_const_vec --- .../affineEquality/sparseImplementation/sparseVector.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index c300b22ceb..bf8dd6df17 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -205,7 +205,8 @@ module SparseVector: AbstractVector = let is_const_vec v = match v.entries with | [] -> false - | (xi,xv)::[] -> if xi = v.len - 1 then false else true + | (xi, xv) :: [] -> if xi = v.len - 1 then false else true + | (xi, xv) :: (const_idx, _) :: [] -> if const_idx = v.len - 1 then true else false | _ -> false let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) From 6ae9bf167e185b3317c11bcc364bd5668846e951 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 21 Dec 2024 18:12:19 +0100 Subject: [PATCH 143/240] Remove prints in ArrayMatrix --- .../apron/affineEqualityAnalysis.apron.ml | 2 +- .../arrayImplementation/arrayMatrix.ml | 31 +++---------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index fcb12606da..be94d389d1 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -19,7 +19,7 @@ let spec_module: (module MCPSpec) Lazy.t = let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct - include SpecFunctor (Priv) (AD) (RelationPrecCompareUtil.DummyUtil) + include SpecFunctor (Priv) (AD_A) (RelationPrecCompareUtil.DummyUtil) let name () = "affeq" end in diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index af849eef0c..83907f29dd 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -39,7 +39,6 @@ module ArrayMatrix: AbstractMatrix = let copy m = Timing.wrap "copy" (copy) m let add_empty_columns m cols = - let () = Printf.printf "Before add_empty_columns m:\n%sindices: %s\n" (show m) (Array.fold_right (fun x s -> (Int.to_string x) ^ "," ^ s) cols "") in Array.modifyi (+) cols; let nnc = Array.length cols in if is_empty m || nnc = 0 then m else @@ -52,7 +51,6 @@ module ArrayMatrix: AbstractMatrix = m'.(i).(j + !offset) <- m.(i).(j); done done; - let () = Printf.printf "After add_empty_columns m:\n%s\n" (show m') in m' let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols @@ -70,7 +68,6 @@ module ArrayMatrix: AbstractMatrix = V.of_array m.(n) let remove_row m n = - let () = Printf.printf "Before remove_row %i of m:\n%s\n" n (show m) in let new_matrix = Array.make_matrix (num_rows m - 1) (num_cols m) A.zero in if not @@ is_empty new_matrix then if n = 0 then @@ -81,7 +78,6 @@ module ArrayMatrix: AbstractMatrix = Array.blit m (n + 1) new_matrix n (num_rows new_matrix - n)); new_matrix let get_col m n = - (*let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)))) in*) V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)) let get_col m n = Timing.wrap "get_col" (get_col m) n @@ -90,13 +86,11 @@ module ArrayMatrix: AbstractMatrix = for i = 0 to num_rows m - 1 do m.(i).(n) <- V.nth new_col i done; - let () = Printf.printf "After set_col m:\n%s\n" (show m) in m let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n let set_col m new_col n = - let () = Printf.printf "Before set_col m:\n%s\n" (show m) in let copy = copy m in set_col_with copy new_col n @@ -123,10 +117,8 @@ module ArrayMatrix: AbstractMatrix = let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = - let () = Printf.printf "Before reduce_col %i of m:\n%s\n" j (show m) in let copy = copy m in reduce_col_with copy j; - let () = Printf.printf "After reduce_col %i of m:\n%s\n" j (show copy) in copy let del_col m j = @@ -138,7 +130,6 @@ module ArrayMatrix: AbstractMatrix = let del_cols m cols = let n_c = Array.length cols in - let () = Printf.printf "Before del_cols cols_length=%i \nm:\n%s\n" n_c (show m) in if n_c = 0 || is_empty m then m else let m_r, m_c = num_rows m, num_cols m in @@ -210,7 +201,6 @@ module ArrayMatrix: AbstractMatrix = let reduce_col_with_vec m j v = - let () = Printf.printf "Before reduce_col_with_vec %i with vec %s of m:\n%s\n" j (V.show (V.of_array v)) (show m) in for i = 0 to num_rows m - 1 do if m.(i).(j) <>: A.zero then let beta = m.(i).(j) /: v.(j) in @@ -253,12 +243,9 @@ module ArrayMatrix: AbstractMatrix = let normalize m = let copy = copy m in - let () = Printf.printf "Before normalizing we have m:\n%s" (show m) in if normalize_with copy then - let () = Printf.printf "After normalizing we have m:\n%s" (show copy) in Some copy else - let () = Printf.printf "No normalization" in None let rref_vec_with m v = (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) @@ -279,13 +266,11 @@ module ArrayMatrix: AbstractMatrix = let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v let rref_vec m v = (* !! There was another rref_vec function that has been renamed to rref_vec_helper !!*) - let () = Printf.printf "Before rref_vec we have m:\n%sv: %s\n" (show m) (V.show v) in let m' = copy m in let v' = V.copy v in match rref_vec_with m' v' with - | Some res -> let () = Printf.printf "After rref_vec, before removing zero rows, we have m:\n%s\n" (show res) in - Some (remove_zero_rows res) - | None -> let () = Printf.printf "After rref_vec there is no normalization\n" in None + | Some res -> Some (remove_zero_rows res) + | None -> None let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) @@ -308,18 +293,15 @@ module ArrayMatrix: AbstractMatrix = let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 let rref_matrix m1 m2 = - let () = Printf.printf "Before rref_matrix m1 m2\nm1: %s\nm2: %s\n" (show m1) (show m2) in let m1' = copy m1 in let m2' = copy m2 in match rref_matrix_with m1' m2' with - | Some m -> let () = Printf.printf "After rref_matrix m:\n %s\n" (show m) in Some m - | None -> let () = Printf.printf "No normalization for rref_matrix found" in None + | Some m -> Some m + | None -> None let is_covered_by m1 m2 = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) (*Both input matrices must be in rref form!*) - let () = Printf.printf "is_covered_by m1: \n%s " (show m1) in - let () = Printf.printf "is_covered_by m2 \n%s " (show m2) in if num_rows m1 > num_rows m2 then false else let p2 = lazy (get_pivot_positions m2) in try ( @@ -337,7 +319,6 @@ module ArrayMatrix: AbstractMatrix = if m1_i. (num_cols m1 - 1) <>: A.zero then raise Stdlib.Exit done; - (*let () = Printf.printf "m1: %sand m2: %s return true in is_covered_by.\n" (show m1') (show m2') in*) true ) with Stdlib.Exit -> false;; @@ -359,10 +340,8 @@ module ArrayMatrix: AbstractMatrix = let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v let map2 f m v = - let () = Printf.printf "Before map2 we have m:\n%s\n" (show m) in let m' = copy m in map2_with f m' v; - let () = Printf.printf "After map2 we have m:\n%s\n" (show m') in m' let map2i_with f m v = @@ -376,10 +355,8 @@ module ArrayMatrix: AbstractMatrix = let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v let map2i f m v = - let () = Printf.printf "Before map2i m:\n%sv:%s\n" (show m) (V.show v) in let m' = copy m in map2i_with f m' v; - let () = Printf.printf "After map2i m:\n%s\n" (show m') in m' let swap_rows m j k = From b8ba2bbac794802073e29b94629307cbc2379297 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Sat, 21 Dec 2024 19:08:15 +0100 Subject: [PATCH 144/240] reordered function in vector so that they match the interface --- .../sparseImplementation/sparseVector.ml | 320 +++++++++--------- 1 file changed, 157 insertions(+), 163 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index bf8dd6df17..a3d499f922 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -18,7 +18,19 @@ module SparseVector: AbstractVector = len: int }[@@deriving eq, ord, hash] - let to_vector e l = {entries=e; len=l} + let copy v = v + + let of_list l = + let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l + in {entries = entries'; len = List.length l} + + let of_array a = + let len' = Array.length a in + let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in + {entries = entries'; len = len'} + + let of_sparse_list col_count ls = + {entries = ls; len = col_count} let to_list v = let[@tail_mod_cons] rec extend_zero_aux i v' = @@ -29,15 +41,83 @@ module SparseVector: AbstractVector = in (extend_zero_aux 0 v.entries) - let of_list l = - let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l - in {entries = entries'; len = List.length l} + let to_array v = + let vec = Array.make v.len A.zero in + List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; + vec - let keep_vals v n = - if n >= v.len then v else - {entries = List.take_while (fun (idx, _) -> idx < n) v.entries; len=n} + let to_sparse_list v = + v.entries + + let show v = + let t = to_list v in + let rec list_str l = + match l with + | [] -> "]" + | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) + in + "["^list_str t^"\n" + + let length v = + v.len + let compare_length_with v n = + Int.compare v.len n + + let zero_vec n = + {entries = []; len = n} + + let is_zero_vec v = (v.entries = []) + + (* Checks if exactly one variable is part of the affine equality, i.e. whether there is exactly one non-zero entry, excluding the constant at the end *) + let is_const_vec v = + match v.entries with + | [] -> false + | (idx, _) :: (const_idx , _) :: [] when const_idx = (v.len - 1) -> true + | (idx, _)::[] when idx <> v.len -1 -> true + | _ -> false + + let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) + if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") + else + let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) + | [] -> A.zero + | (col_idx, value) :: xs when col_idx > n -> A.zero + | (col_idx, value) :: xs when col_idx = n -> value + | (col_idx, value) :: xs -> nth xs + in nth v.entries + + let set_nth v n num = (* TODO: Optimize! *) + if n >= v.len then failwith "Out of bounds" + else + let rec set_nth_helper vec acc = + match vec with + | [] -> if num <>: A.zero then List.rev ((n, num) :: acc) else List.rev acc + | (idx, value) :: xs when n = idx -> if num <>: A.zero then List.rev_append ((idx, num) :: acc) xs else List.rev_append acc xs + | (idx, value) :: xs when n < idx -> if num <>: A.zero then List.rev_append ((n, num) :: acc) vec else List.rev_append acc vec + | x :: xs -> set_nth_helper xs (x :: acc) + in + {entries = set_nth_helper v.entries []; len = v.len} + + let insert_val_at n new_val v = + if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) + let entries' = List.rev @@ List.fold_left (fun acc (idx, value) -> + if idx < n then (idx, value) :: acc + else (if new_val <>: A.zero then (idx + 1, value) :: (n, new_val) :: acc else (idx + 1, value) :: acc) + ) [] v.entries in + {entries = entries'; len = v.len + 1} + + (* Note that idx is assumed to be sorted. *) + let insert_zero_at_indices v idx count = + let rec add_indices_helper vec idx added_count acc = + match vec, idx with + | [], _ -> List.rev acc (* inserting at the end only means changing the dimension *) + | ((col_idx, value) :: xs), [] -> add_indices_helper xs [] added_count ((col_idx + added_count, value) :: acc) + | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) acc + | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> add_indices_helper vec ys (added_count + count) acc + | ((col_idx, value) :: xs), ((i, count) :: ys) -> add_indices_helper xs idx added_count ((col_idx + added_count, value) :: acc) + in + {entries = add_indices_helper v.entries idx 0 []; len = v.len + count} - (* TODO: Which of both remmove_nth should we use *) let remove_nth v n = if n >= v.len then failwith "Out of bounds" else @@ -63,41 +143,61 @@ module SparseVector: AbstractVector = in {entries = remove_indices_helper v.entries idx 0 []; len = v.len - List.length idx} - let insert_zero_at_indices v idx count = - let rec add_indices_helper vec idx added_count acc = - match vec, idx with - | [], _ -> List.rev acc (* inserting at the end only means changing the dimension *) - | ((col_idx, value) :: xs), [] -> add_indices_helper xs [] added_count ((col_idx + added_count, value) :: acc) - | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) acc - | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> add_indices_helper vec ys (added_count + count) acc - | ((col_idx, value) :: xs), ((i, count) :: ys) -> add_indices_helper xs idx added_count ((col_idx + added_count, value) :: acc) - in - {entries = add_indices_helper v.entries idx 0 []; len = v.len + count} + let keep_vals v n = + if n >= v.len then v else + {entries = List.take_while (fun (idx, _) -> idx < n) v.entries; len=n} - let set_nth v n num = (* TODO: Optimize! *) - if n >= v.len then failwith "Out of bounds" + let starting_from_nth n v = + let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in + {entries = entries'; len = v.len - n} + + let find_opt f v = (* TODO: Do we need this? And optimize!!!*) + List.find_opt f (to_list v) + + let findi f v = + if f A.zero then + fst @@ List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) else - let rec set_nth_helper vec acc = - match vec with - | [] -> if num <>: A.zero then List.rev ((n, num) :: acc) else List.rev acc - | (idx, value) :: xs when n = idx -> if num <>: A.zero then List.rev_append ((idx, num) :: acc) xs else List.rev_append acc xs - | (idx, value) :: xs when n < idx -> if num <>: A.zero then List.rev_append ((n, num) :: acc) vec else List.rev_append acc vec - | x :: xs -> set_nth_helper xs (x :: acc) - in - {entries = set_nth_helper v.entries []; len = v.len} + fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) - let insert_val_at n new_val v = - if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) - let entries' = List.rev @@ List.fold_left (fun acc (idx, value) -> - if idx < n then (idx, value) :: acc - else (if new_val <>: A.zero then (idx + 1, value) :: (n, new_val) :: acc else (idx + 1, value) :: acc) - ) [] v.entries in - {entries = entries'; len = v.len + 1} + let find2i f v v' = (* TODO: optimize! *) + fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) + + (* Returns optional of (index * value) where f value evaluated to true *) + let findi_val_opt f v = + let rec find_zero_or_val vec last_col_idx = + let f0 = f A.zero in + match vec with + | [] -> if f0 && v.len <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else None + | (idx, value) :: xs -> + if f0 && idx <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) + else if f value then Some (idx, value) + else find_zero_or_val xs idx + in find_zero_or_val v.entries (-1) + + let findi_val_opt f v = Timing.wrap "findi_val_opt" (findi_val_opt f) v + + let find_first_non_zero v = + if v.entries = [] then None + else Some (List.hd v.entries) + + let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v + + let exists f v = + let c = v.len in + let rec exists_aux at f v = + match v with + | [] -> if at = 0 then false else f A.zero + | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs + in (exists_aux c f v.entries) + + let exists2 f v1 v2 = (* TODO: optimize! *) + List.exists2 f (to_list v1) (to_list v2) + + let filteri f v = (* TODO: optimize! *) + of_list (List.filteri f (to_list v)) let map f v = - (* - of_list (List.map f (to_list v)) - *) let f_zero = f A.zero in let rec map2_helper acc vec i = match vec with @@ -117,6 +217,15 @@ module SparseVector: AbstractVector = let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v + let mapi f v = (* TODO: optimize! *) + of_list (List.mapi f (to_list v)) + + let mapi_f_preserves_zero f v = + let entries' = List.filter_map ( + fun (idx, value) -> let new_val = f idx value in + if new_val = A.zero then None else Some (idx, new_val)) v.entries in + {entries = entries'; len = v.len} + let map2 f v v' = (* TODO: Optimize! *) if v.len <> v'.len then failwith "Unequal vector length" else of_list (List.map2 f (to_list v) (to_list v')) @@ -139,7 +248,7 @@ module SparseVector: AbstractVector = | _ -> aux (f_rem_zero acc xidx xval yval) xs ys in if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else - to_vector (List.rev (aux [] v1.entries v2.entries)) v1.len + {entries = List.rev (aux [] v1.entries v2.entries); len = v1.len} let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 @@ -160,24 +269,15 @@ module SparseVector: AbstractVector = | (xidx, xval)::xs, (yidx, yval)::ys -> if xidx <> i && yidx <> i then aux (f_rem_zero i acc A.zero A.zero) vec1 vec2 (i+1) (* When both vectors have implicit zeroes at front *) else - match xidx - yidx with (* Here at least one of the idx is i, which is the smaller one *) - | d when d < 0 -> aux (f_rem_zero i acc xval A.zero) xs vec2 (i + 1) - | d when d > 0 -> aux (f_rem_zero i acc A.zero yval) vec1 ys (i + 1) - | _ -> aux (f_rem_zero i acc xval yval) xs ys (i + 1) + match xidx - yidx with (* Here at least one of the idx is i, which is the smaller one *) + | d when d < 0 -> aux (f_rem_zero i acc xval A.zero) xs vec2 (i + 1) + | d when d > 0 -> aux (f_rem_zero i acc A.zero yval) vec1 ys (i + 1) + | _ -> aux (f_rem_zero i acc xval yval) xs ys (i + 1) in {entries = List.rev (aux [] v1.entries v2.entries 0); len = v1.len} let map2i_f_preserves_zero f v v' = failwith "TODO" - let mapi f v = (* TODO: optimize! *) - of_list (List.mapi f (to_list v)) - - let mapi_f_preserves_zero f v = - let entries' = List.filter_map ( - fun (idx, value) -> let new_val = f idx value in - if new_val = A.zero then None else Some (idx, new_val)) v.entries in - {entries = entries'; len = v.len} - let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries @@ -196,125 +296,19 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else (aux acc v.entries v'.entries) - - let zero_vec n = - {entries = []; len = n} - - let is_zero_vec v = (v.entries = []) - - let is_const_vec v = - match v.entries with - | [] -> false - | (xi, xv) :: [] -> if xi = v.len - 1 then false else true - | (xi, xv) :: (const_idx, _) :: [] -> if const_idx = v.len - 1 then true else false - | _ -> false - - let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) - if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") - else - let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) - | [] -> A.zero - | (col_idx, value) :: xs when col_idx > n -> A.zero - | (col_idx, value) :: xs when col_idx = n -> value - | (col_idx, value) :: xs -> nth xs - in nth v.entries - - let length v = - v.len + let apply_with_c f c v = (* TODO: optimize! *) + of_list @@ List.map (fun value -> f value c) (to_list v) let apply_with_c_f_preserves_zero f c v = let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} - let apply_with_c f c v = (* TODO: optimize! *) - of_list @@ List.map (fun value -> f value c) (to_list v) - - let findi f v = - if f A.zero then - fst @@ List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) - else - fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) - - (* Returns optional of (index * value) where f value evaluated to true *) - (*Can be optimized, dont check every zero cell*) - let findi_val_opt f v = - let rec find_zero_or_val vec last_col_idx = - let f0 = f A.zero in - match vec with - | [] -> if f0 && v.len <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else None - | (idx, value) :: xs -> - if f0 && idx <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) - else if f value then Some (idx, value) - else find_zero_or_val xs idx - in find_zero_or_val v.entries (-1) - - let findi_val_opt f v = Timing.wrap "findi_val_opt" (findi_val_opt f) v - - let find_first_non_zero v = - if v.entries = [] then None - else Some (List.hd v.entries) - - let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v - - let compare_length_with v n = - Int.compare v.len n - - let filteri f v = (* TODO: optimize! *) - of_list (List.filteri f (to_list v)) - - let append v v' = - let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in - {entries = entries'; len = v.len + v'.len} - - let exists f v = - let c = v.len in - let rec exists_aux at f v = - match v with - | [] -> if at = 0 then false else f A.zero - | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs - in (exists_aux c f v.entries) - - let exists2 f v1 v2 = (* TODO: optimize! *) - List.exists2 f (to_list v1) (to_list v2) - let rev v = let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in {entries = entries'; len = v.len} - let find2i f v v' = (* TODO: optimize! *) - fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) - - let to_array v = - let vec = Array.make v.len A.zero in - List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; - vec - - let of_array a = - let len' = Array.length a in - let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in - {entries = entries'; len = len'} - - let copy v = v - - let of_sparse_list col_count ls = - {entries = ls; len = col_count} - - let to_sparse_list v = - v.entries - - let find_opt f v = (* TODO: Do we need this? And optimize!!!*) - List.find_opt f (to_list v) - - let starting_from_nth n v = - let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in - {entries = entries'; len = v.len - n} + let append v v' = + let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in + {entries = entries'; len = v.len + v'.len} - let show v = - let t = to_list v in - let rec list_str l = - match l with - | [] -> "]" - | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) - in - "["^list_str t^"\n" end From 60f7b67e471d4fbb4cffb74aab44cb91ef2b92bf Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Mon, 23 Dec 2024 11:30:16 +0100 Subject: [PATCH 145/240] Reorder listMatrix; Some renaming --- .../sparseImplementation/listMatrix.ml | 204 +++++++++--------- 1 file changed, 100 insertions(+), 104 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index e8bc108d91..c44c5e2c9b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -21,25 +21,42 @@ module ListMatrix: AbstractMatrix = let show x = List.fold_left (^) "" (List.map (fun x -> (V.show x)) x) + let copy m = m + (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + + let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 + + let copy m = + Timing.wrap "copy" (copy) m + let empty () = [] + let is_empty = List.is_empty + let num_rows = List.length - let is_empty m = - num_rows m = 0 - (*This should be different if the implimentation is sound*) - (*m.column_count = 0*) + let num_cols m = + if m = [] then 0 else V.length (hd m) + + let init_with_vec v = + [v] - let num_cols m = if m = [] then 0 else V.length (hd m) + let append_row m row = + m @ [row] - let copy m = m - (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) + let get_row = List.nth - let copy m = - Timing.wrap "copy" (copy) m + let remove_row m n = + List.remove_at n m + + let remove_zero_rows m = + List.filter (fun row -> not (V.is_zero_vec row)) m + + let swap_rows m j k = + List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m (* This only works if Array.modifyi has been removed from dim_add *) - let add_empty_columns (m : t) (cols : int array) : t = + let add_empty_columns m cols = let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in let rec count_sorted_occ acc cols last count = @@ -55,15 +72,6 @@ module ListMatrix: AbstractMatrix = let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols - let append_row m row = - m @ [row] - - let get_row m n = - List.nth m n - - let remove_row m n = - List.remove_at n m - let get_col m n = (*let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_list @@ List.map (fun row -> V.nth row n) m)) in*) V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) @@ -71,24 +79,79 @@ module ListMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - let set_col m new_col n = + let set_col m new_col n = (* TODO: Optimize! AND CURRENTLY WRONG SEMANTICS IF VECTOR LENGTH <> NUM_ROWS! *) (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) + let del_col m j = + if num_cols m = 1 then empty () + else + List.map (fun row -> V.remove_nth row j) m + + let del_cols m cols = + let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) + if (List.length sorted_cols) = num_cols m then empty() + else + List.map (fun row -> V.remove_at_indices row sorted_cols) m + + let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols + + let map2 f m v = + let vector_length = V.length v in + List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m + + let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) + let rec map2i_min i acc m v = + match m, v with + | [], _ -> List.rev acc + | row :: rs, [] -> List.rev_append (row :: acc) rs + | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs + in + map2i_min 0 [] m (V.to_list v) + + let find_opt = List.find_opt + let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) m1 @ m2 - let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 - let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_f_preserves_zero (fun a -> a /: pivot) row - - let swap_rows m j k = - List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m + V.map_f_preserves_zero (fun a -> a /: pivot) row (* TODO: This is a case for apply_with_c *) let sub_scaled_row row1 row2 s = V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row1 row2 + (* This function return a tuple of row index and pivot position (column) in m *) + (* TODO: maybe we could use a Hashmap instead of a list? *) + let get_pivot_positions m : (int * int) list = + List.rev @@ List.fold_lefti ( + fun acc i row -> match V.find_first_non_zero row with + | None -> acc + | Some (pivot_col, _) -> (i, pivot_col) :: acc + ) [] m + + let assert_rref m = + let pivot_l = get_pivot_positions m in + let rec validate m i = + match m with + | [] -> () + | v::vs when (V.is_zero_vec v) -> + if List.exists (fun v -> not @@ V.is_zero_vec v) vs + then raise (Invalid_argument "Matrix not in rref: zero row!") + else () + | v::vs -> + let rec validate_vec pl = + match pivot_l with + | [] -> true + | (pr, pc)::ps -> + let target = if pr <> i then A.zero else A.one in + if V.nth v pc <>: target then false else validate_vec ps + in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") + in validate m 0 + + (* TODO: Remove this! Just to suppress warning *) + let () = assert_rref (empty ()) + (* Reduces the jth column with the last row that has a non-zero element in this column. *) let reduce_col m j = if is_empty m then m @@ -113,41 +176,12 @@ module ListMatrix: AbstractMatrix = sub_scaled_row row pivot_row s) ) m - let del_col m j = - if num_cols m = 1 then empty () - else - List.map (fun row -> V.remove_nth row j) m - - let del_cols m cols = - let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) - if (List.length sorted_cols) = num_cols m then empty() - else - List.map (fun row -> V.remove_at_indices row sorted_cols) m - - let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols - - let map2i f m v = - let rec map2i_min i acc m v = - match m, v with - | [], _ -> List.rev acc - | row :: rs, [] -> List.rev_append (row :: acc) rs - | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs - in - map2i_min 0 [] m (V.to_list v) - - let remove_zero_rows m = - List.filter (fun row -> not (V.is_zero_vec row)) m - - let init_with_vec v = - [v] - let normalize m = let col_count = num_cols m in - let dec_mat_2D (m : t) (row_idx : int) (col_idx : int) : t = + let cut_front_matrix m row_idx col_idx = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m in - let dec_mat_2D m row_idx col_idx = Timing.wrap "dec_mat_2D" (dec_mat_2D m row_idx) col_idx in + let cut_front_matrix m row_idx col_idx = Timing.wrap "cut_front_matrix" (cut_front_matrix m row_idx) col_idx in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) (* The last column represents the constant in the affeq *) let find_first_pivot m' row_idx col_idx = @@ -158,26 +192,25 @@ module ListMatrix: AbstractMatrix = let row_first_non_zero = V.find_first_non_zero row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) - | Some (idx, value) -> (* let () = Printf.printf "We found first non-zero at index %i in row %i\n" idx i in *) - if idx < cur_col then (i, idx, value) else (cur_row, cur_col, cur_val) - ) (num_rows m', max_piv_col_idx + 1, A.zero) m' (* Initializing with max, so num_cols m indicates that pivot is not found *) + | Some (idx, value) -> if idx < cur_col then (i, idx, value) else (cur_row, cur_col, cur_val) + ) (num_rows m', max_piv_col_idx + 1, A.zero) m' in if piv_col = (max_piv_col_idx + 1) then None else Some (row_idx + piv_row, col_idx + piv_col, piv_val) in let find_first_pivot m' row_idx col_idx = Timing.wrap "find_first_pivot" (find_first_pivot m' row_idx) col_idx in let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) let col_count = num_cols m in - let row_is_valid row = (* TODO: Vector findi_opt *) + let row_is_valid row = match V.find_first_non_zero row with | Some (idx, _) -> if idx < col_count - 1 then true else false (* If all cofactors of the affeq are zero, but the constant is non-zero, the row is invalid *) - | None -> true (* Full zero row is valid *) + | None -> true in List.for_all row_is_valid m in - let rec main_loop m m' row_idx col_idx = + let rec find_piv_and_reduce m m' row_idx col_idx = if col_idx >= (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) else match find_first_pivot m' row_idx col_idx with - | None -> m (* No pivot found means already normalized*) + | None -> m (* No pivot found means already normalized *) | Some (piv_row_idx, piv_col_idx, piv_val) -> ( (* let () = Printf.printf "The current matrix is: \n%s and the pivot is (%i, %i, %s)\n" (show m) piv_row_idx piv_col_idx (A.to_string piv_val) in *) let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in @@ -186,44 +219,13 @@ module ListMatrix: AbstractMatrix = let subtracted_m = List.mapi (fun idx row -> if idx <> row_idx then let scale = V.nth row piv_col_idx in sub_scaled_row row piv_row scale else row) normalized_m in - let m' = dec_mat_2D subtracted_m (row_idx + 1) (piv_col_idx + 1) in - main_loop subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) + let m' = cut_front_matrix subtracted_m (row_idx + 1) (piv_col_idx + 1) in + find_piv_and_reduce subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in - let m' = main_loop m m 0 0 in + let m' = find_piv_and_reduce m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - (* This function return a tuple of row index and pivot position (column) in m *) - (* TODO: maybe we could use a Hashmap instead of a list? *) - let get_pivot_positions (m : t) : (int * int) list = - List.rev @@ List.fold_lefti ( - fun acc i row -> match V.find_first_non_zero row with - | None -> acc - | Some (pivot_col, _) -> (i, pivot_col) :: acc - ) [] m - - let assert_rref m = - let pivot_l = get_pivot_positions m in - let rec validate m i = - match m with - | [] -> () - | v::vs when (V.is_zero_vec v) -> - if List.exists (fun v -> not @@ V.is_zero_vec v) vs - then raise (Invalid_argument "Matrix not in rref: zero row!") - else () - | v::vs -> - let rec validate_vec pl = - match pivot_l with - | [] -> true - | (pr, pc)::ps -> - let target = if pr <> i then A.zero else A.one in - if V.nth v pc <>: target then false else validate_vec ps - in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") - in validate m 0 - - (* TODO: Remove this! Just to suppress warning *) - let () = assert_rref (empty ()) - (* Sets the jth column to zero by subtracting multiples of v *) let reduce_col_with_vec m j v = let pivot_element = V.nth v j in @@ -319,10 +321,4 @@ module ListMatrix: AbstractMatrix = let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 - let find_opt f m = - List.find_opt f m - - let map2 f m v = - let vector_length = V.length v in - List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m end \ No newline at end of file From 8c931a7b82d64963332818f3ce6755062f0a017d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Mon, 23 Dec 2024 12:37:00 +0100 Subject: [PATCH 146/240] Optimize get_col for sparse; Some timing_wraps for matrix --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 2 +- .../sparseImplementation/listMatrix.ml | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index be94d389d1..fcb12606da 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -19,7 +19,7 @@ let spec_module: (module MCPSpec) Lazy.t = let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct - include SpecFunctor (Priv) (AD_A) (RelationPrecCompareUtil.DummyUtil) + include SpecFunctor (Priv) (AD) (RelationPrecCompareUtil.DummyUtil) let name () = "affeq" end in diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index c44c5e2c9b..a43167daff 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -72,9 +72,10 @@ module ListMatrix: AbstractMatrix = let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols - let get_col m n = - (*let () = Printf.printf "get_col %i of m:\n%s\n%s\n" n (show m) (V.show (V.of_list @@ List.map (fun row -> V.nth row n) m)) in*) - V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) + let get_col m n = (* TODO: is this optimal? *) + (* V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) *) + V.of_sparse_list (num_rows m) @@ List.filteri_map (fun i row -> let value = V.nth row n in if value <>: A.zero then Some (i, value) else None) m + let get_col m n = Timing.wrap "get_col" (get_col m) n @@ -83,6 +84,8 @@ module ListMatrix: AbstractMatrix = (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) + let set_col m new_col n = Timing.wrap "set_col" (set_col m) new_col n + let del_col m j = if num_cols m = 1 then empty () else @@ -101,6 +104,8 @@ module ListMatrix: AbstractMatrix = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m + let map2 f m v = Timing.wrap "Matrix.map2" (map2 f m) v + let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) let rec map2i_min i acc m v = match m, v with @@ -110,6 +115,8 @@ module ListMatrix: AbstractMatrix = in map2i_min 0 [] m (V.to_list v) + let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v + let find_opt = List.find_opt let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) From de6acc71cadc84f89826927de465c28a08a6dcec Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Mon, 23 Dec 2024 13:52:47 +0100 Subject: [PATCH 147/240] Fix semantics Matrix.map2, changed Matrix.map2i but might still have to optimize --- src/cdomains/affineEquality/matrix.ml | 8 ++-- .../sparseImplementation/listMatrix.ml | 44 +++++++++++-------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index b3433ee899..13bf12a4b6 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -29,6 +29,10 @@ sig val swap_rows: t -> int -> int -> t + val map2: (vec -> num -> vec) -> t -> vec -> t + + val map2i: (int -> vec-> num -> vec) -> t -> vec -> t + val add_empty_columns: t -> int array -> t val get_col: t -> int -> vec @@ -39,10 +43,6 @@ sig val del_cols: t -> int array -> t - val map2: (vec -> num -> vec) -> t -> vec -> t - - val map2i: (int -> vec-> num -> vec) -> t -> vec -> t - val find_opt: (vec -> bool) -> t -> vec option val append_matrices: t -> t -> t diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index a43167daff..c35e8b02f9 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -55,6 +55,28 @@ module ListMatrix: AbstractMatrix = let swap_rows m j k = List.mapi (fun i row -> if i = j then List.nth m k else if i = k then List.nth m j else row) m + let map2 f m v = + let vector_length = V.length v in + List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m + + let map2 f m v = Timing.wrap "Matrix.map2" (map2 f m) v + + let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) + (* + let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) + let rec map2i_min i acc m v = + match m, v with + | [], _ -> List.rev acc + | row :: rs, [] -> List.rev_append (row :: acc) rs + | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs + in + map2i_min 0 [] m (V.to_list v + *) + let vector_length = V.length v in + List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row ) m + + let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v + (* This only works if Array.modifyi has been removed from dim_add *) let add_empty_columns m cols = let cols = Array.to_list cols in @@ -80,9 +102,10 @@ module ListMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - let set_col m new_col n = (* TODO: Optimize! AND CURRENTLY WRONG SEMANTICS IF VECTOR LENGTH <> NUM_ROWS! *) + let set_col m new_col n = (* TODO: Optimize! The two commented methods have wrong semantics for wrong vector length *) (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) - List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) + (* List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) *) + map2 (fun row value -> V.set_nth row n value) m new_col let set_col m new_col n = Timing.wrap "set_col" (set_col m) new_col n @@ -100,23 +123,6 @@ module ListMatrix: AbstractMatrix = let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols - let map2 f m v = - let vector_length = V.length v in - List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m - - let map2 f m v = Timing.wrap "Matrix.map2" (map2 f m) v - - let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) - let rec map2i_min i acc m v = - match m, v with - | [], _ -> List.rev acc - | row :: rs, [] -> List.rev_append (row :: acc) rs - | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs - in - map2i_min 0 [] m (V.to_list v) - - let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v - let find_opt = List.find_opt let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) From c01b62743940f5737682d2184e49acb5cc5a6e18 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Fri, 27 Dec 2024 23:45:35 +0100 Subject: [PATCH 148/240] comments --- .../sparseImplementation/sparseVector.ml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a3d499f922..bc357e0325 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -311,4 +311,55 @@ module SparseVector: AbstractVector = let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in {entries = entries'; len = v.len + v'.len} + let exists f v = (*TODO: optimize!; maybe we shouldn't if exists is never called with a =: A.zero*) + let c = v.len in + let rec exists_aux at f v = + match v with + | [] -> if at = 0 then false else f A.zero + | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs + in (exists_aux c f v.entries) + + let exists2 f v1 v2 = (* TODO: optimize! *) + List.exists2 f (to_list v1) (to_list v2) + + let rev v = + let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in + {entries = entries'; len = v.len} + + let find2i f v v' = (* TODO: optimize! *) (*"Franzisco should do this!":~Franzisco*) + fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) + + let to_array v = + let vec = Array.make v.len A.zero in + List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; + vec + + let of_array a = + let len' = Array.length a in + let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in + {entries = entries'; len = len'} + + let copy v = v + + let of_sparse_list col_count ls = + {entries = ls; len = col_count} + + let to_sparse_list v = + v.entries + + let find_opt f v = (* TODO: Do we need this? And optimize!!!*) + List.find_opt f (to_list v) + + let starting_from_nth n v = + let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in + {entries = entries'; len = v.len - n} + + let show v = + let t = to_list v in + let rec list_str l = + match l with + | [] -> "]" + | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) + in + "["^list_str t^"\n" end From 1a33f5599aae7a768e1c46ac932df532c1f60f4e Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Sat, 28 Dec 2024 00:13:14 +0100 Subject: [PATCH 149/240] findi_f_false_at_zero --- .../sparseImplementation/sparseVector.ml | 19 +++++++++++++++++-- src/cdomains/affineEquality/vector.ml | 2 ++ .../apron/affineEqualityDomain.apron.ml | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index bc357e0325..b085eb6f5a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -252,7 +252,7 @@ module SparseVector: AbstractVector = let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 - let map2i f v1 v2 = (* TODO: optimize! *) + let map2i f v1 v2 = (*might more memory efficient, but definitly not faster (asymptotically)*) if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else (*of_list (List.map2i f (to_list v) (to_list v'))*) let f_rem_zero idx acc e1 e2 = @@ -326,9 +326,24 @@ module SparseVector: AbstractVector = let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in {entries = entries'; len = v.len} - let find2i f v v' = (* TODO: optimize! *) (*"Franzisco should do this!":~Franzisco*) + let find2i f v v' = fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) + let find2i_f_false_at_zero f v v' = (*Very welcome to change the name*) + let rec aux v1 v2 = + match v1, v2 with + | [], [] -> raise Not_found + | [], (yidx, yval)::ys -> if f A.zero yval then yidx else aux [] ys + | (xidx, xval)::xs, [] -> if f xval A.zero then xidx else aux xs [] + | (xidx, xval)::xs, (yidx, yval)::ys -> + match xidx - yidx with + | d when d < 0 -> if f xval A.zero then xidx else aux xs v2 + | d when d > 0 -> if f A.zero yval then yidx else aux v1 ys + | _ -> if f xval yval then xidx else aux xs ys + in + if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else + aux v.entries v'.entries + let to_array v = let vec = Array.make v.len A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 799df35c0e..a72bb7a78b 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -53,6 +53,8 @@ sig val find2i: (num -> num -> bool) -> t -> t -> int + val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int + (* Returns optional tuple of position and value which was found*) val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 2e9676382f..9ea34bbb2e 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -297,7 +297,7 @@ struct ( let col_a = Vector.rev col_a in let col_b = Vector.rev col_b in - let i = Vector.find2i (<>:) col_a col_b in + let i = Vector.find2i_f_false_at_zero (<>:) col_a col_b in let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in let a_r, b_r = Matrix.get_row a r, Matrix.get_row b r in From aaadeaa22b5c8d9b4ccdf05a383c58aa63452647 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 28 Dec 2024 13:55:16 +0100 Subject: [PATCH 150/240] Add find2i_f_false_at_zero to ArrayVector and remove duplicate code from sparseVector --- .../arrayImplementation/arrayVector.ml | 5 +- .../sparseImplementation/sparseVector.ml | 82 ++++--------------- 2 files changed, 19 insertions(+), 68 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index e90a5afbce..954a051dcc 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -59,7 +59,7 @@ module ArrayVector: AbstractVector = let is_const_vec v = compare_length_with (filteri (fun i x -> (*Inefficient*) - compare_length_with v (i + 1) > 0 && x <>: A.zero) v) 1 = 0 + compare_length_with v (i + 1) > 0 && x <>: A.zero) v) 1 = 0 let nth = Array.get @@ -70,6 +70,9 @@ module ArrayVector: AbstractVector = let find2i f v1 v2 = Array.findi (uncurry f) (Array.combine v1 v2) (* TODO: iter2i? *) + let find2i_f_false_at_zero f v v' = + find2i f v v' + let to_array v = v let of_array v = v diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index b085eb6f5a..10c62bc180 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -163,6 +163,21 @@ module SparseVector: AbstractVector = let find2i f v v' = (* TODO: optimize! *) fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) + let find2i_f_false_at_zero f v v' = (*Very welcome to change the name*) + let rec aux v1 v2 = + match v1, v2 with + | [], [] -> raise Not_found + | [], (yidx, yval)::ys -> if f A.zero yval then yidx else aux [] ys + | (xidx, xval)::xs, [] -> if f xval A.zero then xidx else aux xs [] + | (xidx, xval)::xs, (yidx, yval)::ys -> + match xidx - yidx with + | d when d < 0 -> if f xval A.zero then xidx else aux xs v2 + | d when d > 0 -> if f A.zero yval then yidx else aux v1 ys + | _ -> if f xval yval then xidx else aux xs ys + in + if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else + aux v.entries v'.entries + (* Returns optional of (index * value) where f value evaluated to true *) let findi_val_opt f v = let rec find_zero_or_val vec last_col_idx = @@ -310,71 +325,4 @@ module SparseVector: AbstractVector = let append v v' = let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in {entries = entries'; len = v.len + v'.len} - - let exists f v = (*TODO: optimize!; maybe we shouldn't if exists is never called with a =: A.zero*) - let c = v.len in - let rec exists_aux at f v = - match v with - | [] -> if at = 0 then false else f A.zero - | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs - in (exists_aux c f v.entries) - - let exists2 f v1 v2 = (* TODO: optimize! *) - List.exists2 f (to_list v1) (to_list v2) - - let rev v = - let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in - {entries = entries'; len = v.len} - - let find2i f v v' = - fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) - - let find2i_f_false_at_zero f v v' = (*Very welcome to change the name*) - let rec aux v1 v2 = - match v1, v2 with - | [], [] -> raise Not_found - | [], (yidx, yval)::ys -> if f A.zero yval then yidx else aux [] ys - | (xidx, xval)::xs, [] -> if f xval A.zero then xidx else aux xs [] - | (xidx, xval)::xs, (yidx, yval)::ys -> - match xidx - yidx with - | d when d < 0 -> if f xval A.zero then xidx else aux xs v2 - | d when d > 0 -> if f A.zero yval then yidx else aux v1 ys - | _ -> if f xval yval then xidx else aux xs ys - in - if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else - aux v.entries v'.entries - - let to_array v = - let vec = Array.make v.len A.zero in - List.iter (fun (idx, value) -> vec.(idx) <- value) v.entries; - vec - - let of_array a = - let len' = Array.length a in - let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in - {entries = entries'; len = len'} - - let copy v = v - - let of_sparse_list col_count ls = - {entries = ls; len = col_count} - - let to_sparse_list v = - v.entries - - let find_opt f v = (* TODO: Do we need this? And optimize!!!*) - List.find_opt f (to_list v) - - let starting_from_nth n v = - let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in - {entries = entries'; len = v.len - n} - - let show v = - let t = to_list v in - let rec list_str l = - match l with - | [] -> "]" - | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) - in - "["^list_str t^"\n" end From 48925db6061e6c98949da46b14cbbc616c38935a Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 7 Jan 2025 14:30:38 +0100 Subject: [PATCH 151/240] second version of nth, enable by setting p to false in sparseVector.ml --- .../sparseImplementation/sparseVector.ml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 10c62bc180..5a2e43e957 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -86,6 +86,20 @@ module SparseVector: AbstractVector = | (col_idx, value) :: xs -> nth xs in nth v.entries + let nth' v n = + if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") + else + let rec nth' v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) + | [] -> A.zero + | (col_idx, value) :: xs -> + if col_idx < n then nth' xs else + if col_idx = n then value else + A.zero + in nth' v.entries + + let p = true + let nth = if p then nth else nth' + let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" else From 7fd6b0bf5490904818a93fd4f0b0009bf1960d20 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 7 Jan 2025 14:31:49 +0100 Subject: [PATCH 152/240] no more p --- .../affineEquality/sparseImplementation/sparseVector.ml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 5a2e43e957..07973b2159 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -76,7 +76,7 @@ module SparseVector: AbstractVector = | (idx, _)::[] when idx <> v.len -1 -> true | _ -> false - let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) + let nth' v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") else let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) @@ -86,7 +86,7 @@ module SparseVector: AbstractVector = | (col_idx, value) :: xs -> nth xs in nth v.entries - let nth' v n = + let nth v n = if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") else let rec nth' v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) @@ -97,9 +97,6 @@ module SparseVector: AbstractVector = A.zero in nth' v.entries - let p = true - let nth = if p then nth else nth' - let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" else From 5e29f9c49ad10d51edd9ce8b9a1dee6f793bc9a2 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 7 Jan 2025 15:09:11 +0100 Subject: [PATCH 153/240] nevermind nth' --- .../sparseImplementation/sparseVector.ml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 07973b2159..10c62bc180 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -76,7 +76,7 @@ module SparseVector: AbstractVector = | (idx, _)::[] when idx <> v.len -1 -> true | _ -> false - let nth' v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) + let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") else let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) @@ -86,17 +86,6 @@ module SparseVector: AbstractVector = | (col_idx, value) :: xs -> nth xs in nth v.entries - let nth v n = - if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") - else - let rec nth' v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) - | [] -> A.zero - | (col_idx, value) :: xs -> - if col_idx < n then nth' xs else - if col_idx = n then value else - A.zero - in nth' v.entries - let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" else From 38d51d931759dc088957aff4483c56951c7628b2 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 7 Jan 2025 15:25:46 +0100 Subject: [PATCH 154/240] normalize timing wrap --- .../affineEquality/sparseImplementation/listMatrix.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index c35e8b02f9..04b2d5e31d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -237,7 +237,8 @@ module ListMatrix: AbstractMatrix = in let m' = find_piv_and_reduce m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - + + let normalize m = Timing.wrap "normalize" normalize m (* Sets the jth column to zero by subtracting multiples of v *) let reduce_col_with_vec m j v = @@ -266,7 +267,7 @@ module ListMatrix: AbstractMatrix = match V.find_first_non_zero v with | None -> None | Some (_, value) -> - let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v in + let normalized_v = div_row v value in Some (init_with_vec normalized_v) else (* We try to normalize v and check if a contradiction arises. If not, we insert v at the appropriate place in m (depending on the pivot) *) let pivot_positions = get_pivot_positions m in From 8cb9e410c91c735d0e1c3ca79425b62d9cca4cd7 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 7 Jan 2025 16:24:40 +0100 Subject: [PATCH 155/240] removed some comments --- .../affineEquality/sparseImplementation/listMatrix.ml | 9 ++++----- .../affineEquality/sparseImplementation/sparseVector.ml | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index c35e8b02f9..7198526461 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -22,7 +22,6 @@ module ListMatrix: AbstractMatrix = List.fold_left (^) "" (List.map (fun x -> (V.show x)) x) let copy m = m - (* Lists are immutable, so this should suffice? A.t is mutuable currently, but is treated like its not in ArrayMatrix*) let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 @@ -115,8 +114,8 @@ module ListMatrix: AbstractMatrix = List.map (fun row -> V.remove_nth row j) m let del_cols m cols = - let cols = Array.to_list cols in (* TODO: Is it possible to use list for Apron dimchange? *) - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) + let cols = Array.to_list cols in + let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) if (List.length sorted_cols) = num_cols m then empty() else List.map (fun row -> V.remove_at_indices row sorted_cols) m @@ -125,11 +124,11 @@ module ListMatrix: AbstractMatrix = let find_opt = List.find_opt - let append_matrices m1 m2 = (* keeps dimensions of first matrix, what if dimensions differ?*) + let append_matrices m1 m2 = m1 @ m2 let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_f_preserves_zero (fun a -> a /: pivot) row (* TODO: This is a case for apply_with_c *) + V.map_f_preserves_zero (fun a -> a /: pivot) row let sub_scaled_row row1 row2 s = V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row1 row2 diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 10c62bc180..a5e85cad2b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -79,13 +79,15 @@ module SparseVector: AbstractVector = let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") else - let rec nth v = match v with (* List.assoc would also work, but we use the fact that v is sorted *) + let rec nth v = match v with | [] -> A.zero | (col_idx, value) :: xs when col_idx > n -> A.zero | (col_idx, value) :: xs when col_idx = n -> value | (col_idx, value) :: xs -> nth xs in nth v.entries + let nth v n = Timing.wrap "V.nth" (nth v) n + let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" else From e117432f2e69f4f7d0e3726d38e6be86cc88decb Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 7 Jan 2025 17:03:55 +0100 Subject: [PATCH 156/240] Remove col variable names in vector --- .../sparseImplementation/sparseVector.ml | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a5e85cad2b..d1ed1192bf 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -29,8 +29,8 @@ module SparseVector: AbstractVector = let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in {entries = entries'; len = len'} - let of_sparse_list col_count ls = - {entries = ls; len = col_count} + let of_sparse_list count ls = + {entries = ls; len = count} let to_list v = let[@tail_mod_cons] rec extend_zero_aux i v' = @@ -81,9 +81,9 @@ module SparseVector: AbstractVector = else let rec nth v = match v with | [] -> A.zero - | (col_idx, value) :: xs when col_idx > n -> A.zero - | (col_idx, value) :: xs when col_idx = n -> value - | (col_idx, value) :: xs -> nth xs + | (idx, value) :: xs when idx > n -> A.zero + | (idx, value) :: xs when idx = n -> value + | (idx, value) :: xs -> nth xs in nth v.entries let nth v n = Timing.wrap "V.nth" (nth v) n @@ -109,41 +109,41 @@ module SparseVector: AbstractVector = {entries = entries'; len = v.len + 1} (* Note that idx is assumed to be sorted. *) - let insert_zero_at_indices v idx count = - let rec add_indices_helper vec idx added_count acc = - match vec, idx with + let insert_zero_at_indices v indices count = + let rec add_indices_helper vec cur_idx added_count acc = + match vec, cur_idx with | [], _ -> List.rev acc (* inserting at the end only means changing the dimension *) - | ((col_idx, value) :: xs), [] -> add_indices_helper xs [] added_count ((col_idx + added_count, value) :: acc) - | ((col_idx, value) :: xs), ((i, count) :: ys) when i = col_idx -> add_indices_helper vec ys (added_count + count) acc - | ((col_idx, value) :: xs), ((i, count) :: ys) when i < col_idx -> add_indices_helper vec ys (added_count + count) acc - | ((col_idx, value) :: xs), ((i, count) :: ys) -> add_indices_helper xs idx added_count ((col_idx + added_count, value) :: acc) + | (idx, value) :: xs, [] -> add_indices_helper xs [] added_count ((idx + added_count, value) :: acc) + | (idx, value) :: xs, ((i, count) :: ys) when i = idx -> add_indices_helper vec ys (added_count + count) acc + | (idx, value) :: xs, ((i, count) :: ys) when i < idx -> add_indices_helper vec ys (added_count + count) acc + | (idx, value) :: xs, ((i, count) :: ys) -> add_indices_helper xs cur_idx added_count ((idx + added_count, value) :: acc) in - {entries = add_indices_helper v.entries idx 0 []; len = v.len + count} + {entries = add_indices_helper v.entries indices 0 []; len = v.len + count} let remove_nth v n = if n >= v.len then failwith "Out of bounds" else - let new_entries = List.filter_map (fun (col_idx, value) -> - if col_idx = n then None - else if col_idx > n - then Some (col_idx - 1, value) - else Some (col_idx, value) + let new_entries = List.filter_map (fun (idx, value) -> + if idx = n then None + else if idx > n + then Some (idx - 1, value) + else Some (idx, value) ) v.entries in {entries = new_entries; len = v.len - 1} (* Note: It is assumed and necessary here that idx is sorted!!! *) - let remove_at_indices v idx = - let rec remove_indices_helper vec idx deleted_count acc = - match vec, idx with + let remove_at_indices v indices = + let rec remove_indices_helper vec cur_idx deleted_count acc = + match vec, cur_idx with | [], [] -> List.rev acc - | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> failwith "remove at indices: no more columns to delete" + | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> failwith "remove at indices: no more indices to delete" | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) acc (* Removing zero (also in next iteration, else failwith ) *) - | ((col_idx, value) :: xs), [] -> remove_indices_helper xs [] deleted_count ((col_idx - deleted_count, value) :: acc) - | ((col_idx, value) :: xs), (y :: ys) when y = col_idx -> remove_indices_helper xs ys (deleted_count + 1) acc - | ((col_idx, value) :: xs), (y :: ys) when y < col_idx -> remove_indices_helper vec ys (deleted_count + 1) acc - | ((col_idx, value) :: xs), (y :: ys) -> remove_indices_helper xs idx deleted_count ((col_idx - deleted_count, value) :: acc) + | (idx, value) :: xs, [] -> remove_indices_helper xs [] deleted_count ((idx - deleted_count, value) :: acc) + | (idx, value) :: xs, (y :: ys) when y = idx -> remove_indices_helper xs ys (deleted_count + 1) acc + | (idx, value) :: xs, (y :: ys) when y < idx -> remove_indices_helper vec ys (deleted_count + 1) acc + | (idx, value) :: xs, (y :: ys) -> remove_indices_helper xs cur_idx deleted_count ((idx - deleted_count, value) :: acc) in - {entries = remove_indices_helper v.entries idx 0 []; len = v.len - List.length idx} + {entries = remove_indices_helper v.entries indices 0 []; len = v.len - List.length indices} let keep_vals v n = if n >= v.len then v else @@ -182,12 +182,12 @@ module SparseVector: AbstractVector = (* Returns optional of (index * value) where f value evaluated to true *) let findi_val_opt f v = - let rec find_zero_or_val vec last_col_idx = + let rec find_zero_or_val vec last_idx = let f0 = f A.zero in match vec with - | [] -> if f0 && v.len <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) else None + | [] -> if f0 && v.len <> last_idx + 1 then Some (last_idx + 1, A.zero) else None | (idx, value) :: xs -> - if f0 && idx <> last_col_idx + 1 then Some (last_col_idx + 1, A.zero) + if f0 && idx <> last_idx + 1 then Some (last_idx + 1, A.zero) else if f value then Some (idx, value) else find_zero_or_val xs idx in find_zero_or_val v.entries (-1) @@ -216,15 +216,15 @@ module SparseVector: AbstractVector = let map f v = let f_zero = f A.zero in - let rec map2_helper acc vec i = + let rec map_helper acc vec i = match vec with | [] when i >= v.len || f_zero =: A.zero -> List.rev acc - | [] -> map2_helper ((i, f_zero) :: acc) [] (i + 1) - | (idx, value) :: xs when idx = i -> let new_val = f value in if new_val <>: A.zero then map2_helper ((idx, new_val) :: acc) xs (i + 1) else map2_helper acc xs (i + 1) - | (idx, _) :: xs when idx > i -> if f_zero <>: A.zero then map2_helper ((i, f_zero) :: acc) vec (i + 1) else map2_helper acc vec (i + 1) + | [] -> map_helper ((i, f_zero) :: acc) [] (i + 1) + | (idx, value) :: xs when idx = i -> let new_val = f value in if new_val <>: A.zero then map_helper ((idx, new_val) :: acc) xs (i + 1) else map_helper acc xs (i + 1) + | (idx, _) :: xs when idx > i -> if f_zero <>: A.zero then map_helper ((i, f_zero) :: acc) vec (i + 1) else map_helper acc vec (i + 1) | (_, _) :: _ -> failwith "This should not happen" in - {entries = map2_helper [] v.entries 0; len = v.len} + {entries = map_helper [] v.entries 0; len = v.len} let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( @@ -271,7 +271,6 @@ module SparseVector: AbstractVector = let map2i f v1 v2 = (*might more memory efficient, but definitly not faster (asymptotically)*) if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else - (*of_list (List.map2i f (to_list v) (to_list v'))*) let f_rem_zero idx acc e1 e2 = let r = f idx e1 e2 in if r =: A.zero then acc else (idx, r)::acc From af9e10ccd6554981b017dec017080f43077f0f80 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 7 Jan 2025 17:21:17 +0100 Subject: [PATCH 157/240] Cleanup old Matrix implementations --- .../sparseImplementation/listMatrix.ml | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index efc6f3bc2b..68560ca77d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -60,17 +60,7 @@ module ListMatrix: AbstractMatrix = let map2 f m v = Timing.wrap "Matrix.map2" (map2 f m) v - let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) - (* - let map2i f m v = (* TODO: Optimize! We should probably do it like in map2 *) - let rec map2i_min i acc m v = - match m, v with - | [], _ -> List.rev acc - | row :: rs, [] -> List.rev_append (row :: acc) rs - | row :: rs, value :: vs -> map2i_min (i + 1) (f i row value :: acc) rs vs - in - map2i_min 0 [] m (V.to_list v - *) + let map2i f m v = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row ) m @@ -97,13 +87,10 @@ module ListMatrix: AbstractMatrix = (* V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) *) V.of_sparse_list (num_rows m) @@ List.filteri_map (fun i row -> let value = V.nth row n in if value <>: A.zero then Some (i, value) else None) m - let get_col m n = Timing.wrap "get_col" (get_col m) n - let set_col m new_col n = (* TODO: Optimize! The two commented methods have wrong semantics for wrong vector length *) - (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) - (* List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) *) + let set_col m new_col n = map2 (fun row value -> V.set_nth row n value) m new_col let set_col m new_col n = Timing.wrap "set_col" (set_col m) new_col n @@ -236,7 +223,7 @@ module ListMatrix: AbstractMatrix = in let m' = find_piv_and_reduce m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - + let normalize m = Timing.wrap "normalize" normalize m (* Sets the jth column to zero by subtracting multiples of v *) From 1ab26332e3b2a7602246a765e834b8c428cd7877 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 7 Jan 2025 18:03:13 +0100 Subject: [PATCH 158/240] small changes and get_col_rref -- doesn't work? --- .../arrayImplementation/arrayMatrix.ml | 2 ++ src/cdomains/affineEquality/matrix.ml | 2 ++ .../sparseImplementation/listMatrix.ml | 16 ++++++++++++---- .../sparseImplementation/sparseVector.ml | 8 ++++---- src/cdomains/apron/affineEqualityDomain.apron.ml | 2 +- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 83907f29dd..d2120f7944 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -82,6 +82,8 @@ module ArrayMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n + let get_col_rref m n = failwith "Never implemented" + let set_col_with m new_col n = for i = 0 to num_rows m - 1 do m.(i).(n) <- V.nth new_col i diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index 13bf12a4b6..eef3407dc5 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -37,6 +37,8 @@ sig val get_col: t -> int -> vec + val get_col_rref: t -> int -> vec + val set_col: t -> vec -> int -> t val del_col: t -> int -> t diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index efc6f3bc2b..115830bca2 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -101,9 +101,17 @@ module ListMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - let set_col m new_col n = (* TODO: Optimize! The two commented methods have wrong semantics for wrong vector length *) - (* List.mapi (fun row_idx row -> V.set_nth row n (V.nth new_col row_idx)) m *) - (* List.map2 (fun row value -> V.set_nth row n value) m (V.to_list new_col) *) + let get_col_rref m n = + let rec helper acc m i = + if i > n then + acc + else + match m with + | [] -> acc + | row :: xs -> let value = V.nth row n in if value <>: A.zero then helper ((i, value) :: acc) xs (i + 1) else helper acc xs (i + 1) + in V.of_sparse_list (num_rows m) (List.rev @@ helper [] m 0) + + let set_col m new_col n = map2 (fun row value -> V.set_nth row n value) m new_col let set_col m new_col n = Timing.wrap "set_col" (set_col m) new_col n @@ -236,7 +244,7 @@ module ListMatrix: AbstractMatrix = in let m' = find_piv_and_reduce m m 0 0 in if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) - + let normalize m = Timing.wrap "normalize" normalize m (* Sets the jth column to zero by subtracting multiples of v *) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a5e85cad2b..bb0c36508b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -243,8 +243,8 @@ module SparseVector: AbstractVector = if new_val = A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} - let map2 f v v' = (* TODO: Optimize! *) - if v.len <> v'.len then failwith "Unequal vector length" else + let map2 f v v' = + if v.len <> v'.len then failwith "Unequal vector length" else of_list (List.map2 f (to_list v) (to_list v')) (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) @@ -313,8 +313,8 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else (aux acc v.entries v'.entries) - let apply_with_c f c v = (* TODO: optimize! *) - of_list @@ List.map (fun value -> f value c) (to_list v) + let apply_with_c f c v = + map (fun value -> f value c) v let apply_with_c_f_preserves_zero f c v = let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 9ea34bbb2e..4c81110add 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -310,7 +310,7 @@ struct Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) ) in - let col_a, col_b = Matrix.get_col a s, Matrix.get_col b s in + let col_a, col_b = Matrix.get_col_rref a s, Matrix.get_col_rref b s in let nth_zero v i = match Vector.nth v i with | exception Invalid_argument _ -> Mpqf.zero | x -> x From 4b2c9a715e2272b1a223832bb6d8ea707f0da07c Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 7 Jan 2025 21:26:04 +0100 Subject: [PATCH 159/240] Changed if order in get_col_rref and new calls, removed nth timing wrap --- .../sparseImplementation/listMatrix.ml | 15 +++++++++------ .../sparseImplementation/sparseVector.ml | 2 -- src/cdomains/apron/affineEqualityDomain.apron.ml | 4 ++-- .../sparseMatrixImplementationTest.ml | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6a66f94f60..74b606ad85 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -92,14 +92,17 @@ module ListMatrix: AbstractMatrix = let get_col_rref m n = let rec helper acc m i = - if i > n then - acc - else - match m with - | [] -> acc - | row :: xs -> let value = V.nth row n in if value <>: A.zero then helper ((i, value) :: acc) xs (i + 1) else helper acc xs (i + 1) + match m with + | [] -> acc + | row :: xs -> + if i > n then + acc + else + let value = V.nth row n in if value <>: A.zero then helper ((i, value) :: acc) xs (i + 1) else helper acc xs (i + 1) in V.of_sparse_list (num_rows m) (List.rev @@ helper [] m 0) + let get_col_rref m n = Timing.wrap "get_col" (get_col_rref m) n + let set_col m new_col n = map2 (fun row value -> V.set_nth row n value) m new_col diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 2cc5bb1b41..9b90582f50 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -86,8 +86,6 @@ module SparseVector: AbstractVector = | (idx, value) :: xs -> nth xs in nth v.entries - let nth v n = Timing.wrap "V.nth" (nth v) n - let set_nth v n num = (* TODO: Optimize! *) if n >= v.len then failwith "Out of bounds" else diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 4c81110add..9a7e914a92 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -381,7 +381,7 @@ struct let assign_texpr (t: VarManagement(Vc)(Mx).t) var texp = let assign_invertible_rels x var b env = let j0 = Environment.dim_of_var env var in - let a_j0 = Matrix.get_col x j0 in (*Corresponds to Axj0*) + let a_j0 = Matrix.get_col_rref x j0 in (*Corresponds to Axj0*) let b0 = Vector.nth b j0 in let a_j0 = Vector.apply_with_c_f_preserves_zero (/:) b0 a_j0 in (*Corresponds to Axj0/Bj0*) let recalc_entries m rd_a = Matrix.map2 (fun x y -> Vector.map2i (fun j z d -> @@ -452,7 +452,7 @@ struct | Some m when not @@ is_top_env multi_t -> let replace_col m x y = let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in - let col_x = Matrix.get_col m dim_x in + let col_x = Matrix.get_col_rref m dim_x in Matrix.set_col m col_x dim_y in let switched_m = List.fold_left2 replace_col m primed_vars assigned_vars in diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index b562760a45..f614bd58ca 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -341,6 +341,19 @@ let vectorMap_zero_preserving_normal _ = let expected = Vector.of_list [int 0; int 1; int 4; int 0; int 0; int 16; int 25; int 0; int 0;] in assert_equal expected result + +let get_col_rref _ = + let m = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 0; int 1; frac (-1) 3; int 0; frac 1 3; int 1]] in + + let result = Matrix.get_col_rref m 5 in + + let expected = Vector.of_list [int 0; int 0; frac 1 3] in + + assert_equal expected result + let tests = "SparseMatrixImplementationTest" >::: [ @@ -365,6 +378,7 @@ let vectorMap_zero_preserving_normal _ = "map2i one zero vector" >:: vectorMap2i_one_zero; "map one vector" >:: vectorMap; "map zero preserving normal" >:: vectorMap_zero_preserving_normal; + "get column in rref" >:: get_col_rref; ] let () = run_test_tt_main tests From ebc3412dd88d3b29c9fafc987b5c0c96dbc47916 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 7 Jan 2025 21:26:30 +0100 Subject: [PATCH 160/240] Changed if order in get_col_rref and new calls, removed nth timing wrap --- .../sparseMatrixImplementationTest.ml | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index f614bd58ca..aab7af58d2 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -323,11 +323,11 @@ let vectorMap2i_empty _ = assert_equal expected result let vectorMap2i_one_zero _ = - let v1 = Vector.of_list [int 0; int 0; int 0; int 0] in - let v2 = Vector.of_list [int 1; int 2; int 3; int 4] in - let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in - let expected = Vector.of_list [int 0; int 2; int 6; int 12] in - assert_equal expected result + let v1 = Vector.of_list [int 0; int 0; int 0; int 0] in + let v2 = Vector.of_list [int 1; int 2; int 3; int 4] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [int 0; int 2; int 6; int 12] in + assert_equal expected result let vectorMap _ = let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 3; int 4; int 0; int 0; int 5] in @@ -354,31 +354,31 @@ let get_col_rref _ = assert_equal expected result - let tests = - "SparseMatrixImplementationTest" - >::: [ - "can solve a standard normalization" >:: standard_normalize; - "does sort already reduzed" >:: does_just_sort; - "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - "can handle float domain" >:: does_handle_floats; - "can handle fraction domain" >:: does_handle_fractions; - "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" >:: does_not_change_normalized_matrix; - "m1 is covered by m2" >:: is_covered_by_simple; - "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; - "zero vector is covered by m2" >:: is_zero_vec_covered; - "m1 is not covered by m2" >:: is_not_covered; - "m1 is covered by m2 with big matrix" >:: is_covered_big; - "does not change an empty matrix" >:: normalize_empty; - "can correctly normalize a two column matrix" >:: normalize_two_columns; - "can handle a rational solution" >:: int_domain_to_rational; - "m1 is covered by m2 with big matrix2" >:: is_covered_big2; - "map2i two vectors" >:: vectorMap2i; - "map2i two empty vectors" >:: vectorMap2i_empty; - "map2i one zero vector" >:: vectorMap2i_one_zero; - "map one vector" >:: vectorMap; - "map zero preserving normal" >:: vectorMap_zero_preserving_normal; - "get column in rref" >:: get_col_rref; - ] +let tests = + "SparseMatrixImplementationTest" + >::: [ + "can solve a standard normalization" >:: standard_normalize; + "does sort already reduzed" >:: does_just_sort; + "does eliminate dependent rows" >:: does_eliminate_dependent_rows; + "can handle float domain" >:: does_handle_floats; + "can handle fraction domain" >:: does_handle_fractions; + "does negate negative matrix" >:: does_negate_negative; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; + "m1 is covered by m2" >:: is_covered_by_simple; + "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; + "zero vector is covered by m2" >:: is_zero_vec_covered; + "m1 is not covered by m2" >:: is_not_covered; + "m1 is covered by m2 with big matrix" >:: is_covered_big; + "does not change an empty matrix" >:: normalize_empty; + "can correctly normalize a two column matrix" >:: normalize_two_columns; + "can handle a rational solution" >:: int_domain_to_rational; + "m1 is covered by m2 with big matrix2" >:: is_covered_big2; + "map2i two vectors" >:: vectorMap2i; + "map2i two empty vectors" >:: vectorMap2i_empty; + "map2i one zero vector" >:: vectorMap2i_one_zero; + "map one vector" >:: vectorMap; + "map zero preserving normal" >:: vectorMap_zero_preserving_normal; + "get column in rref" >:: get_col_rref; + ] let () = run_test_tt_main tests From b0fd036d403f90c07c9a4c625d90412ba80aff06 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 15:31:48 +0100 Subject: [PATCH 161/240] Added old unit tests again --- .../sparseMatrixImplementationTest.ml | 12 ++---------- tests/unit/mainTest.ml | 7 ++----- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index aab7af58d2..f56cb7ab68 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -6,8 +6,6 @@ open Goblint_lib open OUnit2 open SparseVector open ListMatrix -open ArrayVector -open ArrayMatrix open ConvenienceOps module D = SharedFunctions.Mpqf @@ -329,15 +327,10 @@ let vectorMap2i_one_zero _ = let expected = Vector.of_list [int 0; int 2; int 6; int 12] in assert_equal expected result -let vectorMap _ = - let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 3; int 4; int 0; int 0; int 5] in - let result = Vector.map (fun x -> x +: int 1) v1 in - let expected = Vector.of_list [int 1; int 2; int 3; int 1; int 1; int 4; int 5; int 1; int 1; int 6] in - assert_equal expected result let vectorMap_zero_preserving_normal _ = let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 4; int 5; int 0; int 0;] in - let result = Vector.map (fun x -> x *: x) v1 in + let result = Vector.map_f_preserves_zero (fun x -> x *: x) v1 in let expected = Vector.of_list [int 0; int 1; int 4; int 0; int 0; int 16; int 25; int 0; int 0;] in assert_equal expected result @@ -376,9 +369,8 @@ let tests = "map2i two vectors" >:: vectorMap2i; "map2i two empty vectors" >:: vectorMap2i_empty; "map2i one zero vector" >:: vectorMap2i_one_zero; - "map one vector" >:: vectorMap; "map zero preserving normal" >:: vectorMap_zero_preserving_normal; - "get column in rref" >:: get_col_rref; + "get column when matrix in rref" >:: get_col_rref; ] let () = run_test_tt_main tests diff --git a/tests/unit/mainTest.ml b/tests/unit/mainTest.ml index 9527679fe7..eab292623f 100644 --- a/tests/unit/mainTest.ml +++ b/tests/unit/mainTest.ml @@ -14,12 +14,9 @@ let all_tests = (* etc *) "domaintest" >::: QCheck_ounit.to_ounit2_test_list Maindomaintest.all_testsuite; IntOpsTest.tests; - (* SparseMatrixImplementationTest.tests; *) (* Uncomment this to add the sparse matrix tests to all tests *) + SparseMatrixImplementationTest.tests; ] -let subset_tests = "" >::: [SparseMatrixImplementationTest.tests] - let () = print_string "\027[0;1munit: \027[0;0;00m"; - run_test_tt_main subset_tests (* Remove this and uncomment the line below to run all tests.*) -(* run_test_tt_main all_tests *) + run_test_tt_main all_tests From 6c1e2a70508294b513574a013b90da535a853013 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 9 Jan 2025 15:32:52 +0100 Subject: [PATCH 162/240] removed unused functions --- .../sparseImplementation/sparseVector.ml | 38 +------------------ src/cdomains/affineEquality/vector.ml | 18 --------- 2 files changed, 1 insertion(+), 55 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 9b90582f50..3fc442c750 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -151,18 +151,12 @@ module SparseVector: AbstractVector = let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in {entries = entries'; len = v.len - n} - let find_opt f v = (* TODO: Do we need this? And optimize!!!*) - List.find_opt f (to_list v) - - let findi f v = + let findi f v = if f A.zero then fst @@ List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) - let find2i f v v' = (* TODO: optimize! *) - fst @@ List.findi (fun _ (val1, val2) -> (uncurry f) (val1, val2)) (List.combine (to_list v) (to_list v')) - let find2i_f_false_at_zero f v v' = (*Very welcome to change the name*) let rec aux v1 v2 = match v1, v2 with @@ -206,24 +200,6 @@ module SparseVector: AbstractVector = | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs in (exists_aux c f v.entries) - let exists2 f v1 v2 = (* TODO: optimize! *) - List.exists2 f (to_list v1) (to_list v2) - - let filteri f v = (* TODO: optimize! *) - of_list (List.filteri f (to_list v)) - - let map f v = - let f_zero = f A.zero in - let rec map_helper acc vec i = - match vec with - | [] when i >= v.len || f_zero =: A.zero -> List.rev acc - | [] -> map_helper ((i, f_zero) :: acc) [] (i + 1) - | (idx, value) :: xs when idx = i -> let new_val = f value in if new_val <>: A.zero then map_helper ((idx, new_val) :: acc) xs (i + 1) else map_helper acc xs (i + 1) - | (idx, _) :: xs when idx > i -> if f_zero <>: A.zero then map_helper ((i, f_zero) :: acc) vec (i + 1) else map_helper acc vec (i + 1) - | (_, _) :: _ -> failwith "This should not happen" - in - {entries = map_helper [] v.entries 0; len = v.len} - let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( fun (idx, value) -> let new_val = f value in @@ -232,19 +208,12 @@ module SparseVector: AbstractVector = let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v - let mapi f v = (* TODO: optimize! *) - of_list (List.mapi f (to_list v)) - let mapi_f_preserves_zero f v = let entries' = List.filter_map ( fun (idx, value) -> let new_val = f idx value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} - let map2 f v v' = - if v.len <> v'.len then failwith "Unequal vector length" else - of_list (List.map2 f (to_list v) (to_list v')) - (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) let map2_f_preserves_zero f v1 v2 = let f_rem_zero acc idx e1 e2 = @@ -290,8 +259,6 @@ module SparseVector: AbstractVector = in {entries = List.rev (aux [] v1.entries v2.entries 0); len = v1.len} - let map2i_f_preserves_zero f v v' = failwith "TODO" - let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries @@ -310,9 +277,6 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else (aux acc v.entries v'.entries) - let apply_with_c f c v = - map (fun value -> f value c) v - let apply_with_c_f_preserves_zero f c v = let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index a72bb7a78b..486f5af584 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -47,12 +47,8 @@ sig (* Returns the part of the vector starting from index n*) val starting_from_nth : int -> t -> t - val find_opt: (num -> bool) -> t -> num Option.t - val findi: (num -> bool) -> t -> int - val find2i: (num -> num -> bool) -> t -> t -> int - val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int (* Returns optional tuple of position and value which was found*) @@ -62,32 +58,18 @@ sig val exists: (num -> bool) -> t -> bool - val exists2: (num -> num -> bool) -> t -> t -> bool - - val filteri: (int -> num -> bool) -> t -> t - - val map: (num -> num) -> t -> t - val map_f_preserves_zero: (num -> num) -> t -> t - val mapi: (int -> num -> num) -> t -> t - val mapi_f_preserves_zero: (int -> num -> num) -> t -> t - val map2: (num -> num -> num) -> t -> t -> t - val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t val map2i: (int -> num -> num -> num) -> t -> t -> t - val map2i_f_preserves_zero: (int -> num -> num -> num) -> t -> t -> t - val fold_left_f_preserves_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc val fold_left2_f_preserves_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc - val apply_with_c: (num -> num -> num) -> num -> t -> t - val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t val rev: t -> t From 08d1b52449745e5869dc87689827d3910fb3e87c Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 9 Jan 2025 15:34:13 +0100 Subject: [PATCH 163/240] removed unused functions --- .../affineEquality/sparseImplementation/sparseVector.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 3fc442c750..3348d8980c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -151,7 +151,7 @@ module SparseVector: AbstractVector = let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in {entries = entries'; len = v.len - n} - let findi f v = + let findi f v = if f A.zero then fst @@ List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) else From 4e04aa0e987ca3aeeb50f8f0851b1eea144a39b0 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 16:09:22 +0100 Subject: [PATCH 164/240] Adapted function descriptions in listMatrix and Remove old comments --- .../sparseImplementation/listMatrix.ml | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 74b606ad85..84a90cbebb 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -66,7 +66,6 @@ module ListMatrix: AbstractMatrix = let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v - (* This only works if Array.modifyi has been removed from dim_add *) let add_empty_columns m cols = let cols = Array.to_list cols in let sorted_cols = List.sort Stdlib.compare cols in @@ -83,13 +82,13 @@ module ListMatrix: AbstractMatrix = let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols - let get_col m n = (* TODO: is this optimal? *) - (* V.of_list @@ List.map (fun row -> V.nth row n) m (* builds full col including zeros, maybe use sparselist instead? *) *) + let get_col m n = V.of_sparse_list (num_rows m) @@ List.filteri_map (fun i row -> let value = V.nth row n in if value <>: A.zero then Some (i, value) else None) m let get_col m n = Timing.wrap "get_col" (get_col m) n + (** Same as [get_col], but [m] must be in rref *) let get_col_rref m n = let rec helper acc m i = match m with @@ -127,15 +126,15 @@ module ListMatrix: AbstractMatrix = let append_matrices m1 m2 = m1 @ m2 - let div_row (row : V.t) (pivot : A.t) : V.t = - V.map_f_preserves_zero (fun a -> a /: pivot) row + let div_row row value = + V.map_f_preserves_zero (fun a -> a /: value) row - let sub_scaled_row row1 row2 s = - V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row1 row2 + let sub_scaled_row row1 row2 factor = + V.map2_f_preserves_zero (fun x y -> x -: (factor *: y)) row1 row2 - (* This function return a tuple of row index and pivot position (column) in m *) - (* TODO: maybe we could use a Hashmap instead of a list? *) - let get_pivot_positions m : (int * int) list = + (** Returns a list of tuples of row index and pivot position (column index) of all rref-pivots of m. + m must be in [rref] *) + let get_pivot_positions m = List.rev @@ List.fold_lefti ( fun acc i row -> match V.find_first_non_zero row with | None -> acc @@ -164,7 +163,7 @@ module ListMatrix: AbstractMatrix = (* TODO: Remove this! Just to suppress warning *) let () = assert_rref (empty ()) - (* Reduces the jth column with the last row that has a non-zero element in this column. *) + (** Reduces the [j]th column with the last row that has a non-zero element in this column. *) let reduce_col m j = if is_empty m then m else @@ -188,6 +187,7 @@ module ListMatrix: AbstractMatrix = sub_scaled_row row pivot_row s) ) m + (** Transforms matrix [m] into reduced row echolon form (rref) *) let normalize m = let col_count = num_cols m in let cut_front_matrix m row_idx col_idx = @@ -224,7 +224,6 @@ module ListMatrix: AbstractMatrix = match find_first_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized *) | Some (piv_row_idx, piv_col_idx, piv_val) -> ( - (* let () = Printf.printf "The current matrix is: \n%s and the pivot is (%i, %i, %s)\n" (show m) piv_row_idx piv_col_idx (A.to_string piv_val) in *) let m = if piv_row_idx <> row_idx then swap_rows m row_idx piv_row_idx else m in let normalized_m = List.mapi (fun idx row -> if idx = row_idx then div_row row piv_val else row) m in let piv_row = (List.nth normalized_m row_idx) in @@ -235,12 +234,12 @@ module ListMatrix: AbstractMatrix = find_piv_and_reduce subtracted_m m' (row_idx + 1) (piv_col_idx + 1)) (* We start at piv_col_idx + 1 because every other col before that is zero at the bottom*) in let m' = find_piv_and_reduce m m 0 0 in - if affeq_rows_are_valid m' then Some m' else None (* TODO: We can check this for each row, using the helper function row_is_invalid *) + if affeq_rows_are_valid m' then Some m' else None let normalize m = Timing.wrap "normalize" normalize m - (* Sets the jth column to zero by subtracting multiples of v *) + (** Sets the [j]th column of [m] to zero by subtracting multiples of [v] from each row *) let reduce_col_with_vec m j v = let pivot_element = V.nth v j in if pivot_element = A.zero then m @@ -251,7 +250,10 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row v) ) m - (* Inserts the vector v with pivot at piv_idx at the correct position in m. m has to be in rref form and v is only <>: A.zero on piv_idx or idx not included in piv_positions *) + + (** Inserts vector [v] with pivot at [piv_idx] at an rref-preserving position in [m]. + [m] has to be in rref form and [v] is valid to be inserted as an rref-row into [m] + ([v] is only <>: A.zero on [piv_idx] or idx not included in [piv_positions] of [m]). *) let insert_v_according_to_piv m v piv_idx pivot_positions = let reduced_m = reduce_col_with_vec m piv_idx v in match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with @@ -260,8 +262,11 @@ module ListMatrix: AbstractMatrix = let (before, after) = List.split_at row_idx reduced_m in (* TODO: Optimize *) before @ (v :: after) - (* This function yields the same result as appending v to m, normalizing and removing zero rows would. *) - (* m must be in rref form and must contain the same number of columns as v *) + + (** This function yields the same result as appending [v] to [m], normalizing and removing zero rows. + However, it is usually faster than performing those ops manually. + [m] must be in rref form and must contain the same number of columns as [v]. + *) let rref_vec m v = if is_empty m then (* In this case, v is normalized and returned *) match V.find_first_non_zero v with @@ -292,8 +297,9 @@ module ListMatrix: AbstractMatrix = let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v - (* This should yield the same result as appending m2 to m1, normalizing and removing zero rows. However, it is usually faster. *) - (* Both input matrices are assumed to be in rref form *) + (** This should yield the same result as appending [m2] to [m1], normalizing and removing zero rows. However, it is usually faster. + [m1] and [m2] must be in rref + *) let rref_matrix (m1 : t) (m2 : t) = let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in fst @@ List.fold_while (fun acc _ -> Option.is_some acc) @@ -301,6 +307,7 @@ module ListMatrix: AbstractMatrix = let rref_matrix m1 m2 = Timing.wrap "rref_matrix" (rref_matrix m1) m2 + (* Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) (* Both input matrices must be in rref form! *) let is_covered_by m1 m2 = From 499b12b6d53b2ca0344db415d374a9d56089bb6d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 17:03:19 +0100 Subject: [PATCH 165/240] More comments and code style --- .../sparseImplementation/listMatrix.ml | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 84a90cbebb..c9a623b76a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -196,20 +196,20 @@ module ListMatrix: AbstractMatrix = let cut_front_matrix m row_idx col_idx = Timing.wrap "cut_front_matrix" (cut_front_matrix m row_idx) col_idx in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) (* The last column represents the constant in the affeq *) - let find_first_pivot m' row_idx col_idx = + let find_first_pivot m row_idx col_idx = if col_idx >= col_count then None else - let max_piv_col_idx = num_cols m' - 2 in (* col at num_cols - 1 is the constant of the affeq *) - (* Finding pivot by extracting the minimum column index of the first non zero value of each row*) + let max_piv_col_idx = num_cols m - 2 in (* col at num_cols - 1 is the constant of the affeq *) + (* Finding pivot by extracting the minimum column index of the first non zero value of each row *) let (piv_row, piv_col, piv_val) = List.fold_lefti (fun (cur_row, cur_col, cur_val) i row -> let row_first_non_zero = V.find_first_non_zero row in match row_first_non_zero with | None -> (cur_row, cur_col, cur_val) | Some (idx, value) -> if idx < cur_col then (i, idx, value) else (cur_row, cur_col, cur_val) - ) (num_rows m', max_piv_col_idx + 1, A.zero) m' + ) (num_rows m, max_piv_col_idx + 1, A.zero) m in if piv_col = (max_piv_col_idx + 1) then None else Some (row_idx + piv_row, col_idx + piv_col, piv_val) in - let find_first_pivot m' row_idx col_idx = Timing.wrap "find_first_pivot" (find_first_pivot m' row_idx) col_idx in + let find_first_pivot m row_idx col_idx = Timing.wrap "find_first_pivot" (find_first_pivot m row_idx) col_idx in let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) let col_count = num_cols m in let row_is_valid row = @@ -218,8 +218,9 @@ module ListMatrix: AbstractMatrix = | None -> true in List.for_all row_is_valid m in + (* Finds the best fitting pivot, moves the respective row at the correct position, and reduces the pivot column afterwards. Continues with next row after that until fully normalized *) let rec find_piv_and_reduce m m' row_idx col_idx = - if col_idx >= (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index is Zero, so it is normalized *) + if col_idx >= (col_count - 1) then m (* In this case the whole bottom of the matrix starting from row_index has been reduced to Zero, so it is normalized *) else match find_first_pivot m' row_idx col_idx with | None -> m (* No pivot found means already normalized *) @@ -265,8 +266,7 @@ module ListMatrix: AbstractMatrix = (** This function yields the same result as appending [v] to [m], normalizing and removing zero rows. However, it is usually faster than performing those ops manually. - [m] must be in rref form and must contain the same number of columns as [v]. - *) + [m] must be in rref form and must contain the same number of columns as [v]. *) let rref_vec m v = if is_empty m then (* In this case, v is normalized and returned *) match V.find_first_non_zero v with @@ -298,18 +298,17 @@ module ListMatrix: AbstractMatrix = let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v (** This should yield the same result as appending [m2] to [m1], normalizing and removing zero rows. However, it is usually faster. - [m1] and [m2] must be in rref - *) - let rref_matrix (m1 : t) (m2 : t) = + [m1] and [m2] must be in rref *) + let rref_matrix m1 m2 = let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in fst @@ List.fold_while (fun acc _ -> Option.is_some acc) - (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m (* TODO: pivot_positions are recalculated at each step, but since they need to be adjusted after each step it might not make sense to keep track of them here.*) + (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m let rref_matrix m1 m2 = Timing.wrap "rref_matrix" (rref_matrix m1) m2 (* Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) - (* Both input matrices must be in rref form! *) + (** Both input matrices must be in rref form! *) let is_covered_by m1 m2 = let rec is_linearly_independent_rref v m = let pivot_opt = V.find_first_non_zero v in From 5e5729c047a608d4da0611f3cf2b598656a353f6 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 9 Jan 2025 17:31:08 +0100 Subject: [PATCH 166/240] removed TODO and comments for add_empty_cols --- .../affineEquality/sparseImplementation/listMatrix.ml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index c9a623b76a..e715d8a57b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -67,8 +67,9 @@ module ListMatrix: AbstractMatrix = let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v let add_empty_columns m cols = - let cols = Array.to_list cols in + let cols = Array.to_list cols in (* cols should adhere to apron specification as described here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html*) let sorted_cols = List.sort Stdlib.compare cols in + (* This function creates a list of tuples, each specifying an index and how many zeros are to be inserted at that index *) let rec count_sorted_occ acc cols last count = match cols with | [] -> if count > 0 then (last, count) :: acc else acc @@ -251,7 +252,6 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row v) ) m - (** Inserts vector [v] with pivot at [piv_idx] at an rref-preserving position in [m]. [m] has to be in rref form and [v] is valid to be inserted as an rref-row into [m] ([v] is only <>: A.zero on [piv_idx] or idx not included in [piv_positions] of [m]). *) @@ -259,11 +259,10 @@ module ListMatrix: AbstractMatrix = let reduced_m = reduce_col_with_vec m piv_idx v in match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with | None -> append_row reduced_m v - | Some (row_idx, _) -> - let (before, after) = List.split_at row_idx reduced_m in (* TODO: Optimize *) + | Some (row_idx, _) -> + let (before, after) = List.split_at row_idx reduced_m in before @ (v :: after) - (** This function yields the same result as appending [v] to [m], normalizing and removing zero rows. However, it is usually faster than performing those ops manually. [m] must be in rref form and must contain the same number of columns as [v]. *) From 5de1ea07b7c40ddbba0fa149962b9dff74674604 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 17:36:03 +0100 Subject: [PATCH 167/240] Adapted assert_ref to validate pivot positions --- .../sparseImplementation/listMatrix.ml | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index e715d8a57b..e3710ce95e 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -143,7 +143,13 @@ module ListMatrix: AbstractMatrix = ) [] m let assert_rref m = - let pivot_l = get_pivot_positions m in + let pivot_positions = get_pivot_positions m in + let rec validate_pivot_positions cur_pivs last_col = + match cur_pivs with + | [] -> () + | (row, col) :: ps -> if col > last_col then validate_pivot_positions ps col else raise (Invalid_argument "Matrix not in rref: pivots not correctly aligned") + + in let rec validate m i = match m with | [] -> () @@ -152,14 +158,16 @@ module ListMatrix: AbstractMatrix = then raise (Invalid_argument "Matrix not in rref: zero row!") else () | v::vs -> - let rec validate_vec pl = - match pivot_l with + let rec validate_vec remaining_pivs = + match remaining_pivs with | [] -> true - | (pr, pc)::ps -> - let target = if pr <> i then A.zero else A.one in - if V.nth v pc <>: target then false else validate_vec ps - in if validate_vec pivot_l then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") - in validate m 0 + | (row_idx, col_idx) :: ps -> + let target = if row_idx <> i then A.zero else A.one in + if V.nth v col_idx <>: target then false else validate_vec ps + in if validate_vec pivot_positions then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") + in + let _ = validate_pivot_positions pivot_positions (-1) in + validate m 0 (* TODO: Remove this! Just to suppress warning *) let () = assert_rref (empty ()) From c9ad687065c0fed3f589ab466dbf73e540c38209 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 17:43:56 +0100 Subject: [PATCH 168/240] Remove assert_rref --- .../sparseImplementation/listMatrix.ml | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index e3710ce95e..ff3093aaff 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -142,36 +142,6 @@ module ListMatrix: AbstractMatrix = | Some (pivot_col, _) -> (i, pivot_col) :: acc ) [] m - let assert_rref m = - let pivot_positions = get_pivot_positions m in - let rec validate_pivot_positions cur_pivs last_col = - match cur_pivs with - | [] -> () - | (row, col) :: ps -> if col > last_col then validate_pivot_positions ps col else raise (Invalid_argument "Matrix not in rref: pivots not correctly aligned") - - in - let rec validate m i = - match m with - | [] -> () - | v::vs when (V.is_zero_vec v) -> - if List.exists (fun v -> not @@ V.is_zero_vec v) vs - then raise (Invalid_argument "Matrix not in rref: zero row!") - else () - | v::vs -> - let rec validate_vec remaining_pivs = - match remaining_pivs with - | [] -> true - | (row_idx, col_idx) :: ps -> - let target = if row_idx <> i then A.zero else A.one in - if V.nth v col_idx <>: target then false else validate_vec ps - in if validate_vec pivot_positions then validate vs (i+1) else raise (Invalid_argument "Matrix not in rref: pivot column not empty!") - in - let _ = validate_pivot_positions pivot_positions (-1) in - validate m 0 - - (* TODO: Remove this! Just to suppress warning *) - let () = assert_rref (empty ()) - (** Reduces the [j]th column with the last row that has a non-zero element in this column. *) let reduce_col m j = if is_empty m then m From 440e7a136ef66ab34885284e4738b4325c349107 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 9 Jan 2025 17:57:19 +0100 Subject: [PATCH 169/240] comments --- .../arrayImplementation/arrayVector.ml | 4 +- .../sparseImplementation/sparseVector.ml | 131 +++++++++++++++--- src/cdomains/affineEquality/vector.ml | 2 +- 3 files changed, 113 insertions(+), 24 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 954a051dcc..7f168b015f 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -46,9 +46,9 @@ module ArrayVector: AbstractVector = let copy = copy v in set_nth_with copy n new_val; copy - let insert_val_at n new_val v = + let insert_val_at v n num = if n > Array.length v then failwith "n too large" else - Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then new_val else Array.get v (i -1)) (* insert? *) + Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then num else Array.get v (i -1)) (* insert? *) let apply_with_c f c v = Array.map (fun x -> f x c) v diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 3348d8980c..606037aeb5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -68,7 +68,10 @@ module SparseVector: AbstractVector = let is_zero_vec v = (v.entries = []) - (* Checks if exactly one variable is part of the affine equality, i.e. whether there is exactly one non-zero entry, excluding the constant at the end *) + (** + [is_const_vec v] returns true if the v represents an affine equality over only one variable, i.e. a constant. + Constant vectors are of the form [0*x0*x] for some value [x] and are represented by a two element list + ,however this is not an iff relationship.*) let is_const_vec v = match v.entries with | [] -> false @@ -76,8 +79,12 @@ module SparseVector: AbstractVector = | (idx, _)::[] when idx <> v.len -1 -> true | _ -> false + (** + [nth v n] returns the [n]-th entry of [v]. + @raise Invalid_argument if [n] is out of bounds. + *) let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) - if n >= v.len then raise (Invalid_argument "Cannot access vector element (out of bounds)") + if n >= v.len then raise (Invalid_argument "Index out of bounds") else let rec nth v = match v with | [] -> A.zero @@ -86,8 +93,12 @@ module SparseVector: AbstractVector = | (idx, value) :: xs -> nth xs in nth v.entries - let set_nth v n num = (* TODO: Optimize! *) - if n >= v.len then failwith "Out of bounds" + (** + [set_nth v n num] returns [v] where the [n]-th entry has been set to [num]. + @raise Invalid_argument if [n] is out of bounds. + *) + let set_nth v n num = + if n >= v.len then raise (Invalid_argument "Index out of bounds") else let rec set_nth_helper vec acc = match vec with @@ -98,16 +109,24 @@ module SparseVector: AbstractVector = in {entries = set_nth_helper v.entries []; len = v.len} - let insert_val_at n new_val v = - if n > v.len then failwith "n too large" else (* Does this happen? Otherwise we can omit this comparison, here right now to be semantically equivalent *) + (** + [insert_val_at v n num] returns [v] where the [num] is inserted into the [n]-th position, i.e. [v] at [n] = [num]. + @raise Invalid_argument if [n] is out of bounds. + *) + let insert_val_at v n num = + if n > v.len then raise (Invalid_argument "Index out of bounds") + else let entries' = List.rev @@ List.fold_left (fun acc (idx, value) -> if idx < n then (idx, value) :: acc - else (if new_val <>: A.zero then (idx + 1, value) :: (n, new_val) :: acc else (idx + 1, value) :: acc) + else (if num <>: A.zero then (idx + 1, value) :: (n, num) :: acc else (idx + 1, value) :: acc) ) [] v.entries in {entries = entries'; len = v.len + 1} - (* Note that idx is assumed to be sorted. *) - let insert_zero_at_indices v indices count = + (** + [insert_zero_at_indices v indices num_zeros] inserts [num_zeros] into [v]. + @param indices A {b sorted} list of tuples where [fst] gives the index of the insert and [snd] the number of zeros that will be inserted. + *) + let insert_zero_at_indices v indices num_zeros = let rec add_indices_helper vec cur_idx added_count acc = match vec, cur_idx with | [], _ -> List.rev acc (* inserting at the end only means changing the dimension *) @@ -116,8 +135,12 @@ module SparseVector: AbstractVector = | (idx, value) :: xs, ((i, count) :: ys) when i < idx -> add_indices_helper vec ys (added_count + count) acc | (idx, value) :: xs, ((i, count) :: ys) -> add_indices_helper xs cur_idx added_count ((idx + added_count, value) :: acc) in - {entries = add_indices_helper v.entries indices 0 []; len = v.len + count} + {entries = add_indices_helper v.entries indices 0 []; len = v.len + num_zeros} + (** + [remove_nth v n] returns [v] where the [n]-th entry is removed, decreasing the length of the vector by one. + @raise Invalid_argument if [n] is out of bounds + *) let remove_nth v n = if n >= v.len then failwith "Out of bounds" else @@ -129,7 +152,11 @@ module SparseVector: AbstractVector = ) v.entries in {entries = new_entries; len = v.len - 1} - (* Note: It is assumed and necessary here that idx is sorted!!! *) + (** + [remove_at_indices v indices] returns [v] where all entries at the positions specified by [indices] are removed, decreasing its length by the length of [indices]. + @param indices A {b sorted} list of indices + @raise Invalid_argument if [indices] would reach out of bounds for some index. + *) let remove_at_indices v indices = let rec remove_indices_helper vec cur_idx deleted_count acc = match vec, cur_idx with @@ -157,9 +184,16 @@ module SparseVector: AbstractVector = else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) + (** + [find2i_f_false_at_zero f v v'] returns the {b index} of the first pair of entries [e, e'] from [v, v'] where [f e e' = true ]. + + Note that [f] {b must} be such that [f 0 0 = false]! + + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + *) let find2i_f_false_at_zero f v v' = (*Very welcome to change the name*) let rec aux v1 v2 = - match v1, v2 with + match v1, v2 with | [], [] -> raise Not_found | [], (yidx, yval)::ys -> if f A.zero yval then yidx else aux [] ys | (xidx, xval)::xs, [] -> if f xval A.zero then xidx else aux xs [] @@ -172,7 +206,10 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else aux v.entries v'.entries - (* Returns optional of (index * value) where f value evaluated to true *) + (** + [findi_val_opt f v] returns the first entry [e] and its index where [f e = true], if such an entry exists. + @return [(idx, e) option] + *) let findi_val_opt f v = let rec find_zero_or_val vec last_idx = let f0 = f A.zero in @@ -186,6 +223,10 @@ module SparseVector: AbstractVector = let findi_val_opt f v = Timing.wrap "findi_val_opt" (findi_val_opt f) v + (** + [find_first_non_zero v] returns the first entry [e] and its index where [e <>: 0], if such an entry exists. + @return [(idx, e) option] + *) let find_first_non_zero v = if v.entries = [] then None else Some (List.hd v.entries) @@ -200,6 +241,13 @@ module SparseVector: AbstractVector = | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs in (exists_aux c f v.entries) + (** + [map_f_preserves_zero f v] returns the mapping of [v] specified by [f]. + + Note that [f] {b must} be such that [f 0 = 0]! + + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + *) let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( fun (idx, value) -> let new_val = f value in @@ -208,14 +256,29 @@ module SparseVector: AbstractVector = let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v + (** + [mapi_f_preserves_zero f v] returns the mapping of [v] specified by [f]. + + Note that [f] {b must} be such that [f i 0 = 0] for any index [i]! + + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + *) let mapi_f_preserves_zero f v = let entries' = List.filter_map ( fun (idx, value) -> let new_val = f idx value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} - (* map for functions f such that f 0 0 = 0 since f won't be applied to if both values are zero. See also map *) - let map2_f_preserves_zero f v1 v2 = + (** + [map2_f_preserves_zero f v v'] returns the mapping of [v] and [v'] specified by [f]. + + Note that [f] {b must} be such that [f 0 0 = 0]! + + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + + @raise Invalid_argument if [v] and [v'] have unequal lengths + *) + let map2_f_preserves_zero f v v' = let f_rem_zero acc idx e1 e2 = let r = f e1 e2 in if r =: A.zero then acc else (idx, r)::acc @@ -231,20 +294,23 @@ module SparseVector: AbstractVector = | d when d > 0 -> aux (f_rem_zero acc yidx A.zero yval) v1 ys | _ -> aux (f_rem_zero acc xidx xval yval) xs ys in - if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else - {entries = List.rev (aux [] v1.entries v2.entries); len = v1.len} + if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else + {entries = List.rev (aux [] v.entries v'.entries); len = v.len} let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 - let map2i f v1 v2 = (*might more memory efficient, but definitly not faster (asymptotically)*) - if v1.len <> v2.len then raise (Invalid_argument "Unequal lengths") else + (** + @raise Invalid_argument if [v] and [v'] have unequal lengths + *) + let map2i f v v' = (*might more memory efficient, but definitly not faster (asymptotically)*) + if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else let f_rem_zero idx acc e1 e2 = let r = f idx e1 e2 in if r =: A.zero then acc else (idx, r)::acc in let rec aux acc vec1 vec2 i = match vec1, vec2 with - | [], [] when i = v1.len -> acc + | [], [] when i = v.len -> acc | [], [] -> aux (f_rem_zero i acc A.zero A.zero) [] [] (i + 1) | [], (yidx, yval)::ys when i = yidx -> aux (f_rem_zero i acc A.zero yval) [] ys (i + 1) | (xidx, xval)::xs, [] when i = xidx -> aux (f_rem_zero i acc xval A.zero) xs [] (i + 1) @@ -257,11 +323,27 @@ module SparseVector: AbstractVector = | d when d > 0 -> aux (f_rem_zero i acc A.zero yval) vec1 ys (i + 1) | _ -> aux (f_rem_zero i acc xval yval) xs ys (i + 1) in - {entries = List.rev (aux [] v1.entries v2.entries 0); len = v1.len} + {entries = List.rev (aux [] v.entries v'.entries 0); len = v.len} + + (** + [fold_left_f_preserves_zero f acc v] returns the fold of [v] on [acc] specified by [f]. + + Note that [f] {b must} be such that [f acc 0 = acc]! + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + *) let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries + (** + [fold_left2_f_preserves_zero f acc v v'] returns the fold of [v] and [v'] specified by [f]. + + Note that [f] {b must} be such that [f acc 0 0 = acc]! + + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + + @raise Invalid_argument if [v] and [v'] have unequal lengths + *) let fold_left2_f_preserves_zero f acc v v' = let rec aux acc v1 v2 = match v1, v2 with @@ -277,6 +359,13 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else (aux acc v.entries v'.entries) + (** + [apply_with_c_f_preserves_zero f c v] returns the mapping of [v] and [c] specified by [f]. + + Note that [f] {b must} be such that [f 0 c = 0]! + + {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} + *) let apply_with_c_f_preserves_zero f c v = let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in {entries = entries'; len = v.len} diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 486f5af584..f937432aba 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -34,7 +34,7 @@ sig val set_nth: t -> int -> num -> t - val insert_val_at: int -> num -> t -> t + val insert_val_at: t -> int -> num -> t val insert_zero_at_indices: t -> (int * int) list -> int -> t From db480ca88f7326351700f3e1d96ae94231cf6fda Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 17:59:13 +0100 Subject: [PATCH 170/240] Made to_list tail recursive --- .../sparseImplementation/sparseVector.ml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 606037aeb5..25f23dd99d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -32,14 +32,14 @@ module SparseVector: AbstractVector = let of_sparse_list count ls = {entries = ls; len = count} - let to_list v = - let[@tail_mod_cons] rec extend_zero_aux i v' = - match v', i with - | (xi,xv)::xs, _ -> if xi = i then xv::(extend_zero_aux (i+1) xs) else A.zero ::(extend_zero_aux (i+1) v') - | [], j when i < v.len -> A.zero :: (extend_zero_aux (i+1) v') - | [], _ -> [] - in - (extend_zero_aux 0 v.entries) + let to_list v = + let rec extend_zero_aux i v' acc = + match v' with + | (index, value) :: xs -> if index = i then extend_zero_aux (i + 1) xs (value :: acc) else extend_zero_aux (i + 1) v' (A.zero :: acc) + | [] when i < v.len -> extend_zero_aux (i + 1) v' (A.zero :: acc) + | [] -> List.rev acc + in + extend_zero_aux 0 v.entries [] let to_array v = let vec = Array.make v.len A.zero in From 971268d69ecc34d403fc38a13eb74a6d5c808dd5 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 18:01:41 +0100 Subject: [PATCH 171/240] Removed unused functions in arrayVector --- .../affineEquality/arrayImplementation/arrayVector.ml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 7f168b015f..de77bcb346 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -109,10 +109,6 @@ module ArrayVector: AbstractVector = aux (idx - 1) acc in aux (length v - 1) [] - - let find_opt f v = - failwith "Never implemented!" - let map_f_preserves_zero f v = map f v @@ -122,9 +118,6 @@ module ArrayVector: AbstractVector = let mapi_f_preserves_zero f v = mapi f v - let map2i_f_preserves_zero f v v' = - map2i f v v' - let fold_left_f_preserves_zero f acc v = failwith "Never implemented!" @@ -134,9 +127,6 @@ module ArrayVector: AbstractVector = let findi_val_opt f v = failwith "Never implemented!" - let exists2 f v1 v1 = - failwith "Never implemented!" - let starting_from_nth n v = failwith "Never implemented!" From 34bb6a581d12501613164b1ca469d167ab1e1cdd Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 9 Jan 2025 18:11:43 +0100 Subject: [PATCH 172/240] minor change to to_list, fix comments --- .../affineEquality/sparseImplementation/sparseVector.ml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 25f23dd99d..abd8109347 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -36,8 +36,7 @@ module SparseVector: AbstractVector = let rec extend_zero_aux i v' acc = match v' with | (index, value) :: xs -> if index = i then extend_zero_aux (i + 1) xs (value :: acc) else extend_zero_aux (i + 1) v' (A.zero :: acc) - | [] when i < v.len -> extend_zero_aux (i + 1) v' (A.zero :: acc) - | [] -> List.rev acc + | [] -> if i < v.len then extend_zero_aux (i + 1) v' (A.zero :: acc) else List.rev acc in extend_zero_aux 0 v.entries [] @@ -70,8 +69,7 @@ module SparseVector: AbstractVector = (** [is_const_vec v] returns true if the v represents an affine equality over only one variable, i.e. a constant. - Constant vectors are of the form [0*x0*x] for some value [x] and are represented by a two element list - ,however this is not an iff relationship.*) + Constant vectors are represented by a two element list, however this is not an iff relationship.*) let is_const_vec v = match v.entries with | [] -> false From c4be7e69817f700c9c2a0e81433d4f04d0a1b0bc Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 9 Jan 2025 18:12:00 +0100 Subject: [PATCH 173/240] List :: codestyle --- .../sparseImplementation/sparseVector.ml | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index abd8109347..18de84066a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -194,8 +194,8 @@ module SparseVector: AbstractVector = match v1, v2 with | [], [] -> raise Not_found | [], (yidx, yval)::ys -> if f A.zero yval then yidx else aux [] ys - | (xidx, xval)::xs, [] -> if f xval A.zero then xidx else aux xs [] - | (xidx, xval)::xs, (yidx, yval)::ys -> + | (xidx, xval) :: xs, [] -> if f xval A.zero then xidx else aux xs [] + | (xidx, xval) :: xs, (yidx, yval) :: ys -> match xidx - yidx with | d when d < 0 -> if f xval A.zero then xidx else aux xs v2 | d when d > 0 -> if f A.zero yval then yidx else aux v1 ys @@ -236,7 +236,7 @@ module SparseVector: AbstractVector = let rec exists_aux at f v = match v with | [] -> if at = 0 then false else f A.zero - | (xi, xv)::xs -> if f xv then true else exists_aux (at - 1) f xs + | (xi, xv) :: xs -> if f xv then true else exists_aux (at - 1) f xs in (exists_aux c f v.entries) (** @@ -279,14 +279,14 @@ module SparseVector: AbstractVector = let map2_f_preserves_zero f v v' = let f_rem_zero acc idx e1 e2 = let r = f e1 e2 in - if r =: A.zero then acc else (idx, r)::acc + if r =: A.zero then acc else (idx, r) :: acc in let rec aux acc v1 v2 = match v1, v2 with | [], [] -> acc - | [], (yidx, yval)::ys -> aux (f_rem_zero acc yidx A.zero yval) [] ys - | (xidx, xval)::xs, [] -> aux (f_rem_zero acc xidx xval A.zero) xs [] - | (xidx, xval)::xs, (yidx, yval)::ys -> + | [], (yidx, yval) :: ys -> aux (f_rem_zero acc yidx A.zero yval) [] ys + | (xidx, xval) :: xs, [] -> aux (f_rem_zero acc xidx xval A.zero) xs [] + | (xidx, xval) :: xs, (yidx, yval) :: ys -> match xidx - yidx with | d when d < 0 -> aux (f_rem_zero acc xidx xval A.zero) xs v2 | d when d > 0 -> aux (f_rem_zero acc yidx A.zero yval) v1 ys @@ -304,15 +304,15 @@ module SparseVector: AbstractVector = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else let f_rem_zero idx acc e1 e2 = let r = f idx e1 e2 in - if r =: A.zero then acc else (idx, r)::acc + if r =: A.zero then acc else (idx, r) :: acc in let rec aux acc vec1 vec2 i = match vec1, vec2 with | [], [] when i = v.len -> acc | [], [] -> aux (f_rem_zero i acc A.zero A.zero) [] [] (i + 1) - | [], (yidx, yval)::ys when i = yidx -> aux (f_rem_zero i acc A.zero yval) [] ys (i + 1) - | (xidx, xval)::xs, [] when i = xidx -> aux (f_rem_zero i acc xval A.zero) xs [] (i + 1) - | [], (_, _)::_ | (_, _)::_, [] -> aux (f_rem_zero i acc A.zero A.zero) vec1 vec2 (i + 1) (* When one vec is not zero_vec, but has implicit zeroes at front *) + | [], (yidx, yval) :: ys when i = yidx -> aux (f_rem_zero i acc A.zero yval) [] ys (i + 1) + | (xidx, xval) :: xs, [] when i = xidx -> aux (f_rem_zero i acc xval A.zero) xs [] (i + 1) + | [], (_, _) :: _ | (_, _) :: _, [] -> aux (f_rem_zero i acc A.zero A.zero) vec1 vec2 (i + 1) (* When one vec is not zero_vec, but has implicit zeroes at front *) | (xidx, xval)::xs, (yidx, yval)::ys -> if xidx <> i && yidx <> i then aux (f_rem_zero i acc A.zero A.zero) vec1 vec2 (i+1) (* When both vectors have implicit zeroes at front *) else @@ -346,9 +346,9 @@ module SparseVector: AbstractVector = let rec aux acc v1 v2 = match v1, v2 with | [], [] -> acc - | [], (yidx, yval)::ys -> aux (f acc A.zero yval) [] ys - | (xidx, xval)::xs, [] -> aux (f acc xval A.zero) xs [] - | (xidx, xval)::xs, (yidx, yval)::ys -> + | [], (yidx, yval) :: ys -> aux (f acc A.zero yval) [] ys + | (xidx, xval) :: xs, [] -> aux (f acc xval A.zero) xs [] + | (xidx, xval) :: xs, (yidx, yval) :: ys -> match xidx - yidx with | d when d < 0 -> aux (f acc xval A.zero) xs v2 | d when d > 0 -> aux (f acc A.zero yval) v1 ys From a8589e3f39ae1371cc2ee2ce0cfc64d17a8a45ac Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Thu, 9 Jan 2025 18:16:08 +0100 Subject: [PATCH 174/240] comment changes, changed raised error --- .../affineEquality/sparseImplementation/sparseVector.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 18de84066a..8a4006df81 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -140,7 +140,7 @@ module SparseVector: AbstractVector = @raise Invalid_argument if [n] is out of bounds *) let remove_nth v n = - if n >= v.len then failwith "Out of bounds" + if n >= v.len then raise (Invalid_argument "Index out of bounds") else let new_entries = List.filter_map (fun (idx, value) -> if idx = n then None @@ -159,8 +159,8 @@ module SparseVector: AbstractVector = let rec remove_indices_helper vec cur_idx deleted_count acc = match vec, cur_idx with | [], [] -> List.rev acc - | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> failwith "remove at indices: no more indices to delete" - | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) acc (* Removing zero (also in next iteration, else failwith ) *) + | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> raise (Invalid_argument "Indices out of bounds") + | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) acc | (idx, value) :: xs, [] -> remove_indices_helper xs [] deleted_count ((idx - deleted_count, value) :: acc) | (idx, value) :: xs, (y :: ys) when y = idx -> remove_indices_helper xs ys (deleted_count + 1) acc | (idx, value) :: xs, (y :: ys) when y < idx -> remove_indices_helper vec ys (deleted_count + 1) acc From 33555366e5d85f9659813cd6f18845b98746f790 Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Fri, 10 Jan 2025 13:17:12 +0100 Subject: [PATCH 175/240] Delete list.txt --- list.txt | 2318 ------------------------------------------------------ 1 file changed, 2318 deletions(-) delete mode 100644 list.txt diff --git a/list.txt b/list.txt deleted file mode 100644 index 6f85b69219..0000000000 --- a/list.txt +++ /dev/null @@ -1,2318 +0,0 @@ -./goblint --enable warn.debug --enable dbg.regression --set ana.activated[+] affeq --set sem.int.signed_overflow assume_none tests/regression/77-lin2vareq/20-function_call2.c -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -Matrix in Domain m: - -Switched Matrix in Domain switched_m: - -Before normalizing we have m: -After normalizing we have m: -Before add_empty_columns m: -indices: 0,0,0, -Occ_cols is: -(0,3) -After add_empty_columns m: - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[1 0 0 0 ] - -Before Matrix.rref_vec x: - b: -[-1 1 0 0 ] - -Before rref_vec we have m: -v: [-1 1 0 0 ] - -Before normalizing we have m: -[-1 1 0 0 ] -After normalizing we have m: -[1 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 -1 0 0 ] - -After affineEq_vec m: -[0 1 0 0 ] - -Before reduce_col 2 of m: -[1 -1 0 0 ] - -After reduce_col 2 of m: -[1 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 -1 0 0 ] - b: -[0 -1 1 0 ] - -Before rref_vec we have m: -[1 -1 0 0 ] -v: [0 -1 1 0 ] - -Before normalizing we have m: -[1 -1 0 0 ] -[0 -1 1 0 ] -After normalizing we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0,1,2, -Occ_cols is: -(0,1)(1,1)(2,1) -After add_empty_columns m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 1 0 0 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 1 0 ] - -Before reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0,1,2, -Occ_cols is: -(0,1)(1,1)(2,1) -After add_empty_columns m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before assign_var_parallel m: -[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -Before add_empty_columns m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -indices: 0,0,0, -Occ_cols is: -(0,3) -After add_empty_columns m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[1 0 0 0 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [1 0 0 0 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[1 0 0 0 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 1 0 0 0 0 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 1 0 0 0 0 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 1 0 0 0 0 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 0 1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 0 1 0 0 0 0 0 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 0 1 0 0 0 0 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After assign_var_parallel multi_t: -[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -Matrix in Domain m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Switched Matrix in Domain switched_m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before dim_remove m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After dim_remove m': -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 -1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 -1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 -1 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 -1 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 1 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 1 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 0 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 0 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 0 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 0 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -indices: 0, -Occ_cols is: -(0,1) -After add_empty_columns m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 8 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - b: -[1 0 0 0 0 0 0 8 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -v: [1 0 0 0 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -[1 0 0 0 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -indices: 2,3,4, -Occ_cols is: -(2,1)(3,1)(4,1) -After add_empty_columns m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 -1 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After affineEq_vec m: -[0 0 1 0 0 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 -1 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - b: -[0 1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -v: [0 1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -[0 1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -forget_vars m: -[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After affineEq_vec m: -[0 0 0 0 1 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -forget_vars m: -[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -forget_vars m: -[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -After dim_remove m': -[1 0 0 0 8 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0, -Occ_cols is: -(0,1) -After add_empty_columns m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before rref_matrix m1 m2 -m1: [0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -m2: [1 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_matrix m, before removing zero rows: - [1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] -Before dim_remove m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 0 of m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0, -Occ_cols is: -(0,1) -After add_empty_columns m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - b: -[1 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -v: [1 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After dim_remove m': -[1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before add_empty_columns m: -indices: 0,0,0, -Occ_cols is: -(0,3) -After add_empty_columns m: - -Before assign_var_parallel m: -⊤ -After assign_var_parallel multi_t: -⊤ -After affineEq_vec m: -[1 0 0 0 ] - -Before Matrix.rref_vec x: - b: -[-1 1 0 0 ] - -Before rref_vec we have m: -v: [-1 1 0 0 ] - -Before normalizing we have m: -[-1 1 0 0 ] -After normalizing we have m: -[1 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 -1 0 0 ] - -After affineEq_vec m: -[0 1 0 0 ] - -Before reduce_col 2 of m: -[1 -1 0 0 ] - -After reduce_col 2 of m: -[1 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 -1 0 0 ] - b: -[0 -1 1 0 ] - -Before rref_vec we have m: -[1 -1 0 0 ] -v: [0 -1 1 0 ] - -Before normalizing we have m: -[1 -1 0 0 ] -[0 -1 1 0 ] -After normalizing we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 -1 0 ] -[0 1 -1 0 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0,1,2, -Occ_cols is: -(0,1)(1,1)(2,1) -After add_empty_columns m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 1 0 0 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 1 0 ] - -Before reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -After reduce_col 4 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - b: -[0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -v: [0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 1 0 -1 0 0 ] -[0 0 0 0 0 0 0 ] -[0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0,1,2, -Occ_cols is: -(0,1)(1,1)(2,1) -After add_empty_columns m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] - -Before assign_var_parallel m: -[|x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -Before add_empty_columns m: -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -indices: 0,0,0, -Occ_cols is: -(0,3) -After add_empty_columns m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 1 0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[1 0 0 0 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [1 0 0 0 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[1 0 0 0 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 1 0 0 0 0 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 1 0 0 0 0 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 1 0 0 0 0 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 0 1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - b: -[0 0 1 0 0 0 0 0 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -v: [0 0 1 0 0 0 0 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After assign_var_parallel multi_t: -[|0'-z#324#arg=0; 1'-z#324#arg=0; 2'-z#324#arg=0; x#322#arg-z#324#arg=0; y#323#arg-z#324#arg=0|] -Matrix in Domain m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 0 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 0 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After set_col m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Switched Matrix in Domain switched_m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before dim_remove m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -After dim_remove m': -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 1 0 0 0 0 -1 0 ] -[0 1 0 0 0 1 0 0 -1 0 ] -[0 0 1 0 0 0 0 1 -1 0 ] -[0 0 0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 1 0 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 -1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 -1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 1 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 -1 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 -1 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [0 0 1 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 1 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [1 0 0 0 -1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[1 0 0 0 -1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -v: [-1 0 0 0 1 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[-1 0 0 0 1 0 0 ] -After normalizing we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -[0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -[1 0 0 0 0 -1 0 ] -[0 1 0 0 0 -1 0 ] -[0 0 1 0 0 -1 0 ] -[0 0 0 1 0 -1 0 ] -[0 0 0 0 1 -1 0 ] -indices: 0, -Occ_cols is: -(0,1) -After add_empty_columns m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 0 8 ] - -Before reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - b: -[1 0 0 0 0 0 0 8 ] - -Before rref_vec we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -v: [1 0 0 0 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -[1 0 0 0 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 0 -1 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 1 0 0 -1 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -After dim_remove m': -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 1 0 0 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 0 1 0 -1 0 ] -[0 0 0 0 0 0 0 0 ] - -Before add_empty_columns m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -indices: 2,3,4, -Occ_cols is: -(2,1)(3,1)(4,1) -After add_empty_columns m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 -1 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After affineEq_vec m: -[0 0 1 0 0 0 0 0 ] - -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 0 0 0 -1 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - b: -[0 1 -1 0 0 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -v: [0 1 -1 0 0 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] -[0 1 -1 0 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -forget_vars m: -[|#ret-8=0; x#322#arg-x#327=0; y#323#arg-z#324#arg=0|]Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 1 -1 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] -[0 0 0 1 0 -1 0 0 ] - -After affineEq_vec m: -[0 0 0 0 1 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 0 -1 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 1 -1 0 0 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 1 -1 0 0 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -forget_vars m: -[|#ret-8=0; y#323#arg-y#328=0|]Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 1 -1 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -After affineEq_vec m: -[0 0 0 0 0 0 1 0 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before Matrix.rref_vec x: -[1 0 0 0 0 0 0 8 ] - b: -[0 0 0 0 0 1 -1 0 ] - -Before rref_vec we have m: -[1 0 0 0 0 0 0 8 ] -v: [0 0 0 0 0 1 -1 0 ] - -Before normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After normalizing we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -forget_vars m: -[|#ret-8=0; z#324#arg-z#329=0|]Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 1 -1 0 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] -[0 0 0 0 0 0 0 0 ] - -Before dim_remove m: -[1 0 0 0 0 0 0 8 ] -Before reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 1 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 3 of m: -[1 0 0 0 0 0 0 8 ] - -Before reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -After reduce_col 5 of m: -[1 0 0 0 0 0 0 8 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -After dim_remove m': -[1 0 0 0 8 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 0 0 8 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0, -Occ_cols is: -(0,1) -After add_empty_columns m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before rref_matrix m1 m2 -m1: [0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -m2: [1 0 0 0 8 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 8 ] -After normalizing we have m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_matrix m, before removing zero rows: - [1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -meet a: [|x#327-z#329=0; y#328-z#329=0|] b: [|#ret-8=0|] -> [|#ret-8=0; x#327-z#329=0; y#328-z#329=0|] -Before dim_remove m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 0 of m: -[1 0 0 0 8 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After dim_remove m': -[1 0 -1 0 ] -[0 1 -1 0 ] -Before del_cols cols_length=1 -m: -[0 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before add_empty_columns m: -[1 0 -1 0 ] -[0 1 -1 0 ] -indices: 0, -Occ_cols is: -(0,1) -After add_empty_columns m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After affineEq_vec m: -[0 0 0 0 0 ] - -Before reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 0 of m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before Matrix.rref_vec x: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - b: -[1 0 0 0 0 ] - -Before rref_vec we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -v: [1 0 0 0 0 ] - -Before normalizing we have m: -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -[1 0 0 0 0 ] -After normalizing we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -After rref_vec, before removing zero rows, we have m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -Before dim_remove m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] -Before reduce_col 1 of m: -[1 0 0 0 0 ] -[0 1 0 -1 0 ] -[0 0 1 -1 0 ] - -After reduce_col 1 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -Before reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 1 -1 0 ] - -After reduce_col 2 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After reduce_col 3 of m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -After dim_remove m': -[1 0 ] -Before del_cols cols_length=3 -m: -[1 0 0 0 0 ] -[0 0 0 0 0 ] -[0 0 0 0 0 ] - -[Info][Deadcode] Logical lines of code (LLoC) summary: - live: 10 - dead: 0 - total lines: 10 -See result/index.xml From c836b6341cf3f988670ef440f14c661e688ecfcb Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Mon, 13 Jan 2025 15:59:35 +0100 Subject: [PATCH 176/240] comments and naming changes --- .../arrayImplementation/arrayMatrix.ml | 2 +- src/cdomains/affineEquality/matrix.ml | 2 +- .../sparseImplementation/listMatrix.ml | 77 +++++++++++++++---- .../apron/affineEqualityDomain.apron.ml | 6 +- .../sparseMatrixImplementationTest.ml | 6 +- 5 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index d2120f7944..c5a65459f5 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -82,7 +82,7 @@ module ArrayMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - let get_col_rref m n = failwith "Never implemented" + let get_col_upper_triangular m n = failwith "Never implemented" let set_col_with m new_col n = for i = 0 to num_rows m - 1 do diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index eef3407dc5..fd2de28588 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -37,7 +37,7 @@ sig val get_col: t -> int -> vec - val get_col_rref: t -> int -> vec + val get_col_upper_triangular: t -> int -> vec val set_col: t -> vec -> int -> t diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index ff3093aaff..8242f16020 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -66,6 +66,10 @@ module ListMatrix: AbstractMatrix = let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v + (** + [add_empty_columns m cols] extends the matrix [m] as specified in [c]. + @param c An apron dimchange array as defined here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html . + *) let add_empty_columns m cols = let cols = Array.to_list cols in (* cols should adhere to apron specification as described here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html*) let sorted_cols = List.sort Stdlib.compare cols in @@ -89,8 +93,10 @@ module ListMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - (** Same as [get_col], but [m] must be in rref *) - let get_col_rref m n = + (** + Same as [get_col], but [m] must be in upper triangular form. + *) + let get_col_upper_triangular m n = let rec helper acc m i = match m with | [] -> acc @@ -101,7 +107,7 @@ module ListMatrix: AbstractMatrix = let value = V.nth row n in if value <>: A.zero then helper ((i, value) :: acc) xs (i + 1) else helper acc xs (i + 1) in V.of_sparse_list (num_rows m) (List.rev @@ helper [] m 0) - let get_col_rref m n = Timing.wrap "get_col" (get_col_rref m) n + let get_col_upper_triangular m n = Timing.wrap "get_col" (get_col_upper_triangular m) n let set_col m new_col n = map2 (fun row value -> V.set_nth row n value) m new_col @@ -113,6 +119,10 @@ module ListMatrix: AbstractMatrix = else List.map (fun row -> V.remove_nth row j) m + (** + [del_cols m cols] removes columns from [m] as specified by [c]. + @param c An apron dimchange array as defined here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html . + *) let del_cols m cols = let cols = Array.to_list cols in let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) @@ -133,8 +143,10 @@ module ListMatrix: AbstractMatrix = let sub_scaled_row row1 row2 factor = V.map2_f_preserves_zero (fun x y -> x -: (factor *: y)) row1 row2 - (** Returns a list of tuples of row index and pivot position (column index) of all rref-pivots of m. - m must be in [rref] *) + (** + [get_pivot_positions m] returns a list of tuples of row index and pivot position (column index) of all rref-pivots of [m]. + @param m A matrix in rref. + *) let get_pivot_positions m = List.rev @@ List.fold_lefti ( fun acc i row -> match V.find_first_non_zero row with @@ -142,7 +154,10 @@ module ListMatrix: AbstractMatrix = | Some (pivot_col, _) -> (i, pivot_col) :: acc ) [] m - (** Reduces the [j]th column with the last row that has a non-zero element in this column. *) + (** + [reduce_col m j] reduces the [j]-th column in [m] with the last row that has a non-zero element in this column. + TODO do we need m to be rref here? + *) let reduce_col m j = if is_empty m then m else @@ -166,7 +181,9 @@ module ListMatrix: AbstractMatrix = sub_scaled_row row pivot_row s) ) m - (** Transforms matrix [m] into reduced row echolon form (rref) *) + (** + [normalize m] transforms matrix [m] into reduced row echolon form (rref). + *) let normalize m = let col_count = num_cols m in let cut_front_matrix m row_idx col_idx = @@ -219,7 +236,8 @@ module ListMatrix: AbstractMatrix = let normalize m = Timing.wrap "normalize" normalize m - (** Sets the [j]th column of [m] to zero by subtracting multiples of [v] from each row *) + (** + [reduce_col_with_vec m j v] sets the [j]-th column of [m] to zero by subtracting multiples of [v] from each row. *) let reduce_col_with_vec m j v = let pivot_element = V.nth v j in if pivot_element = A.zero then m @@ -230,8 +248,14 @@ module ListMatrix: AbstractMatrix = V.map2_f_preserves_zero (fun x y -> x -: (s *: y)) row v) ) m - (** Inserts vector [v] with pivot at [piv_idx] at an rref-preserving position in [m]. - [m] has to be in rref form and [v] is valid to be inserted as an rref-row into [m] + (** + [insert_v_according_to_piv m v piv_idx pivot_position] inserts vector [v] into [m] such that rref is preserved. + @param m A matrix in rref such that [(r, piv_idx)] is not in [pivot_positions] for all [r]. + @param v A vector such that [v(piv_idx) =: A.one] and [v(c) <>: A.zero] iff [(r,c)] is not in [pivot_position] for all [r]. + + TODO is the above the right description of the below + + [m] has to be in rref and [v] is valid to be inserted as an rref-row into [m] ([v] is only <>: A.zero on [piv_idx] or idx not included in [piv_positions] of [m]). *) let insert_v_according_to_piv m v piv_idx pivot_positions = let reduced_m = reduce_col_with_vec m piv_idx v in @@ -241,9 +265,17 @@ module ListMatrix: AbstractMatrix = let (before, after) = List.split_at row_idx reduced_m in before @ (v :: after) - (** This function yields the same result as appending [v] to [m], normalizing and removing zero rows. - However, it is usually faster than performing those ops manually. - [m] must be in rref form and must contain the same number of columns as [v]. *) + (** + [rref_vec m v] yields the same result as appending [v] to [m], then bringing [m] into rref. + + {i Faster than appending [v] to [m] and normalizing!} + @param m A matrix in rref. + @param v A vector with number of entries equal to the number of columns of [v]. + + TODO is the above valid description of below? + + However, it is usually faster than performing those ops manually. + [m] must be in rref form and must contain the same number of columns as [v]. *) let rref_vec m v = if is_empty m then (* In this case, v is normalized and returned *) match V.find_first_non_zero v with @@ -274,7 +306,16 @@ module ListMatrix: AbstractMatrix = let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v - (** This should yield the same result as appending [m2] to [m1], normalizing and removing zero rows. However, it is usually faster. + (** [rref_matrix m m'] yields the same result as appending [m'] to [m], then bringing the resulting matrix into rref. + + {i Faster than appending [m'] to [m] then normalizing!} + @param m A matrix in rref. + @param m' A matrix in rref. + + TODO above correct description for below? + + + This should yield the same result as appending [m2] to [m1], normalizing and removing zero rows. However, it is usually faster. [m1] and [m2] must be in rref *) let rref_matrix m1 m2 = let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in @@ -283,9 +324,11 @@ module ListMatrix: AbstractMatrix = let rref_matrix m1 m2 = Timing.wrap "rref_matrix" (rref_matrix m1) m2 - - (* Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) - (** Both input matrices must be in rref form! *) + (** + [is_coverd_by m m'] returns [true] iff every vector in [m] is a linear combination of vectors in [m']. + @param m A matrix in rref. + @param m' A matrix in rref. + *) let is_covered_by m1 m2 = let rec is_linearly_independent_rref v m = let pivot_opt = V.find_first_non_zero v in diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 9a7e914a92..a3764a3b04 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -310,7 +310,7 @@ struct Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) ) in - let col_a, col_b = Matrix.get_col_rref a s, Matrix.get_col_rref b s in + let col_a, col_b = Matrix.get_col_upper_triangular a s, Matrix.get_col_upper_triangular b s in let nth_zero v i = match Vector.nth v i with | exception Invalid_argument _ -> Mpqf.zero | x -> x @@ -381,7 +381,7 @@ struct let assign_texpr (t: VarManagement(Vc)(Mx).t) var texp = let assign_invertible_rels x var b env = let j0 = Environment.dim_of_var env var in - let a_j0 = Matrix.get_col_rref x j0 in (*Corresponds to Axj0*) + let a_j0 = Matrix.get_col_upper_triangular x j0 in (*Corresponds to Axj0*) let b0 = Vector.nth b j0 in let a_j0 = Vector.apply_with_c_f_preserves_zero (/:) b0 a_j0 in (*Corresponds to Axj0/Bj0*) let recalc_entries m rd_a = Matrix.map2 (fun x y -> Vector.map2i (fun j z d -> @@ -452,7 +452,7 @@ struct | Some m when not @@ is_top_env multi_t -> let replace_col m x y = let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in - let col_x = Matrix.get_col_rref m dim_x in + let col_x = Matrix.get_col_upper_triangular m dim_x in Matrix.set_col m col_x dim_y in let switched_m = List.fold_left2 replace_col m primed_vars assigned_vars in diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index f56cb7ab68..102b0ae879 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -335,13 +335,13 @@ let vectorMap_zero_preserving_normal _ = assert_equal expected result -let get_col_rref _ = +let get_col_upper_triangular _ = let m = make_matrix_of_2d_list @@ [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; [int 0; int 0; int 1; frac (-1) 3; int 0; frac 1 3; int 1]] in - let result = Matrix.get_col_rref m 5 in + let result = Matrix.get_col_upper_triangular m 5 in let expected = Vector.of_list [int 0; int 0; frac 1 3] in @@ -370,7 +370,7 @@ let tests = "map2i two empty vectors" >:: vectorMap2i_empty; "map2i one zero vector" >:: vectorMap2i_one_zero; "map zero preserving normal" >:: vectorMap_zero_preserving_normal; - "get column when matrix in rref" >:: get_col_rref; + "get column when matrix in rref" >:: get_col_upper_triangular; ] let () = run_test_tt_main tests From 470e79184e055e13a7ecb4bc3a7ca2ca965a4b18 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Mon, 13 Jan 2025 16:05:45 +0100 Subject: [PATCH 177/240] small comment changes --- src/cdomains/affineEquality/sparseImplementation/listMatrix.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 8242f16020..7bfb3de3fe 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -94,7 +94,8 @@ module ListMatrix: AbstractMatrix = Timing.wrap "get_col" (get_col m) n (** - Same as [get_col], but [m] must be in upper triangular form. + [get_col_upper_triangular m n] yields the same result as [get_col m n], but [m] must be in upper triangular form. + @param m A matrix in upper triangular form. *) let get_col_upper_triangular m n = let rec helper acc m i = From 9627e382ac88788988a4fc72b53b78750a764176 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Mon, 13 Jan 2025 16:41:10 +0100 Subject: [PATCH 178/240] ArrayMatrix get_col_upper_triangular is normal get_col and rref_vec optimized again --- .../affineEquality/arrayImplementation/arrayMatrix.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index c5a65459f5..e6b4c25db1 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -82,7 +82,7 @@ module ArrayMatrix: AbstractMatrix = let get_col m n = Timing.wrap "get_col" (get_col m) n - let get_col_upper_triangular m n = failwith "Never implemented" + let get_col_upper_triangular m n = get_col m n (* Never implemented optimized version *) let set_col_with m new_col n = for i = 0 to num_rows m - 1 do @@ -253,7 +253,7 @@ module ArrayMatrix: AbstractMatrix = (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) - (*let v = V.to_array v in + let v = V.to_array v in if is_empty m then match Array.findi (fun x -> x <>: A.zero) v with | exception Not_found -> None @@ -262,8 +262,7 @@ module ArrayMatrix: AbstractMatrix = Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) else let pivot_elements = get_pivot_positions m in - rref_vec_helper m pivot_elements v*) - normalize @@ append_row m v + rref_vec_helper m pivot_elements v let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v From 68910d4ddbaf52bd7a2fa825b752198718a098bc Mon Sep 17 00:00:00 2001 From: Franzisco Schmidt <81369817+CopperCableIsolator@users.noreply.github.com> Date: Mon, 13 Jan 2025 21:14:28 +0100 Subject: [PATCH 179/240] Update listMatrix.ml --- .../sparseImplementation/listMatrix.ml | 30 +++++-------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 7bfb3de3fe..1cee1862b5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -156,8 +156,7 @@ module ListMatrix: AbstractMatrix = ) [] m (** - [reduce_col m j] reduces the [j]-th column in [m] with the last row that has a non-zero element in this column. - TODO do we need m to be rref here? + [reduce_col m j] reduces the [j]-th column in [m] with the last row that has a non-zero element in this column. *) let reduce_col m j = if is_empty m then m @@ -252,12 +251,8 @@ module ListMatrix: AbstractMatrix = (** [insert_v_according_to_piv m v piv_idx pivot_position] inserts vector [v] into [m] such that rref is preserved. @param m A matrix in rref such that [(r, piv_idx)] is not in [pivot_positions] for all [r]. - @param v A vector such that [v(piv_idx) =: A.one] and [v(c) <>: A.zero] iff [(r,c)] is not in [pivot_position] for all [r]. - - TODO is the above the right description of the below - - [m] has to be in rref and [v] is valid to be inserted as an rref-row into [m] - ([v] is only <>: A.zero on [piv_idx] or idx not included in [piv_positions] of [m]). *) + @param v A vector such that [v(piv_idx) =: A.one] and [v(c) <>: A.zero] if [(r,c)] is not in [pivot_position] for all [r]. + *) let insert_v_according_to_piv m v piv_idx pivot_positions = let reduced_m = reduce_col_with_vec m piv_idx v in match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with @@ -267,16 +262,12 @@ module ListMatrix: AbstractMatrix = before @ (v :: after) (** - [rref_vec m v] yields the same result as appending [v] to [m], then bringing [m] into rref. + [rref_vec m v] yields the same result as appending [v] to [m], then bringing [m] into rref and removing all zero rows. {i Faster than appending [v] to [m] and normalizing!} @param m A matrix in rref. @param v A vector with number of entries equal to the number of columns of [v]. - - TODO is the above valid description of below? - - However, it is usually faster than performing those ops manually. - [m] must be in rref form and must contain the same number of columns as [v]. *) + *) let rref_vec m v = if is_empty m then (* In this case, v is normalized and returned *) match V.find_first_non_zero v with @@ -307,17 +298,12 @@ module ListMatrix: AbstractMatrix = let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v - (** [rref_matrix m m'] yields the same result as appending [m'] to [m], then bringing the resulting matrix into rref. + (** [rref_matrix m m'] yields the same result as appending [m'] to [m], then bringing the resulting matrix into rref and removing all zero rows. {i Faster than appending [m'] to [m] then normalizing!} @param m A matrix in rref. @param m' A matrix in rref. - - TODO above correct description for below? - - - This should yield the same result as appending [m2] to [m1], normalizing and removing zero rows. However, it is usually faster. - [m1] and [m2] must be in rref *) + *) let rref_matrix m1 m2 = let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in fst @@ List.fold_while (fun acc _ -> Option.is_some acc) @@ -362,4 +348,4 @@ module ListMatrix: AbstractMatrix = let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 - end \ No newline at end of file + end From c8f81553fcc9923328c33440ca04f840cc834651 Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:32:04 +0100 Subject: [PATCH 180/240] Update regtest.sh to old --html --- regtest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regtest.sh b/regtest.sh index f263b2b968..488dd0bab4 100755 --- a/regtest.sh +++ b/regtest.sh @@ -14,7 +14,7 @@ if [[ $OSTYPE == 'darwin'* ]]; then grep="ggrep" fi params="`$grep -oP "PARAM: \K.*" $file`" -cmd="./goblint --enable warn.debug --enable dbg.regression $params ${@:3} $file -v" # -v --html +cmd="./goblint --enable warn.debug --enable dbg.regression --html $params ${@:3} $file" # -v echo "$cmd" eval $cmd echo "See result/index.xml" From a3988d441249736960e8894e547315c3ef9dcf68 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 14 Jan 2025 15:43:33 +0100 Subject: [PATCH 181/240] comments --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 2 +- .../affineEquality/sparseImplementation/listMatrix.ml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index fcb12606da..a5a18e9d92 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -15,7 +15,7 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in - let module AD_A = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in (* TODO: Remove this! Just to suppress warning *) + let module AD_Array = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in (* TODO: Remove this! Just to suppress warning *) let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 1cee1862b5..676949bf49 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -6,7 +6,7 @@ open ConvenienceOps open BatList module List = BatList -(** Sparse matrix implementation. +(** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) module ListMatrix: AbstractMatrix = @@ -15,7 +15,7 @@ module ListMatrix: AbstractMatrix = include ConvenienceOps(A) module V = V(A) - type t = V.t list (*List of rows*) + type t = V.t list (* List of rows *) [@@deriving eq, ord, hash] let show x = @@ -300,7 +300,7 @@ module ListMatrix: AbstractMatrix = (** [rref_matrix m m'] yields the same result as appending [m'] to [m], then bringing the resulting matrix into rref and removing all zero rows. - {i Faster than appending [m'] to [m] then normalizing!} + {i Faster than appending [m'] to [m] and then normalizing!} @param m A matrix in rref. @param m' A matrix in rref. *) From e5a0f8a8df0019ef2bf6da2534eb459f1b16a816 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 21 Jan 2025 15:19:12 +0100 Subject: [PATCH 182/240] Removed unused arrayimplementation --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index a5a18e9d92..ca1ce5683b 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -4,9 +4,6 @@ open Analyses -open ArrayVector -open ArrayMatrix - open SparseVector open ListMatrix @@ -15,7 +12,6 @@ include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in - let module AD_Array = AffineEqualityDomain.D2 (ArrayVector) (ArrayMatrix) in (* TODO: Remove this! Just to suppress warning *) let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct From 9555ab0fde44589bd11ec880866ec092a21e2feb Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Tue, 21 Jan 2025 16:03:58 +0100 Subject: [PATCH 183/240] Update tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml Co-authored-by: Michael Petter --- .../sparseImplementation/sparseMatrixImplementationTest.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 102b0ae879..d24d5b0895 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -30,9 +30,7 @@ let make_matrix_of_2d_list l = (** This function runs the equality assertion with the solution after normalizing the matrix. *) let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in - let do_dimensions_match dim1 dim2 = - match (dim1, dim2) with (r1, c1), (r2, c2) -> r1 == r2 && c1 == c2 - in + let do_dimensions_match (r1, c1), (r2, c2) = r1 = r2 && c1 = c2 in let matrix_dim = get_dimensions matrix in let solution_dim = get_dimensions solution in if not (do_dimensions_match solution_dim matrix_dim) then From 07d9d5c6c000fae092168b9ee0c2061442de4dde Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Tue, 21 Jan 2025 16:10:20 +0100 Subject: [PATCH 184/240] Update comment for add_empy_columns Co-authored-by: Michael Petter --- .../affineEquality/sparseImplementation/listMatrix.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 676949bf49..21d4496fab 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -67,8 +67,8 @@ module ListMatrix: AbstractMatrix = let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v (** - [add_empty_columns m cols] extends the matrix [m] as specified in [c]. - @param c An apron dimchange array as defined here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html . + [add_empty_columns m cols] extends the matrix [m] as specified in [cols]. + @param cols An apron dimchange array as defined here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html . *) let add_empty_columns m cols = let cols = Array.to_list cols in (* cols should adhere to apron specification as described here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html*) From 0aa86a7e90ab2e290991084d07f3c7fc324c5723 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 21 Jan 2025 16:10:42 +0100 Subject: [PATCH 185/240] Change comments about _with suffixes --- src/cdomains/affineEquality/abstractVector.ml | 1 - src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/abstractVector.ml b/src/cdomains/affineEquality/abstractVector.ml index e5d7cd40e6..b4de95f30b 100644 --- a/src/cdomains/affineEquality/abstractVector.ml +++ b/src/cdomains/affineEquality/abstractVector.ml @@ -1,7 +1,6 @@ open RatOps open Vector -(** Some functions inside have the suffix _with, which means that the function has side effects. *) module type AbstractVector = functor (A: RatOps) -> sig diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index e6b4c25db1..a5b70764f4 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -9,6 +9,8 @@ module Array = Batteries.Array (** Array-based matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) +(* The functions that have the suffix _with have side effects and were used in a previous version of the affineEqualityDomain. + These calls were removed to transition to list-based matrices.*) module ArrayMatrix: AbstractMatrix = functor (A: RatOps) (V: AbstractVector) -> struct From 8d80046e5ef62651c24bcfc80e25c8dbf8a4af62 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 21 Jan 2025 17:17:38 +0100 Subject: [PATCH 186/240] Change order of starting_from_nth parameters. Add comments for some functions --- .../arrayImplementation/arrayVector.ml | 2 +- .../sparseImplementation/listMatrix.ml | 2 +- .../sparseImplementation/sparseVector.ml | 22 +++++++++++++++---- src/cdomains/affineEquality/vector.ml | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index de77bcb346..480beac534 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -127,7 +127,7 @@ module ArrayVector: AbstractVector = let findi_val_opt f v = failwith "Never implemented!" - let starting_from_nth n v = + let starting_from_nth v n = failwith "Never implemented!" let find_first_non_zero v = diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 21d4496fab..820eb1b439 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -187,7 +187,7 @@ module ListMatrix: AbstractMatrix = let normalize m = let col_count = num_cols m in let cut_front_matrix m row_idx col_idx = - List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth col_idx row)) m + List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth row col_idx)) m in let cut_front_matrix m row_idx col_idx = Timing.wrap "cut_front_matrix" (cut_front_matrix m row_idx) col_idx in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 8a4006df81..715f04238b 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -32,6 +32,7 @@ module SparseVector: AbstractVector = let of_sparse_list count ls = {entries = ls; len = count} + (** [to_list v] Returns a non-sparse list representing the vector v *) let to_list v = let rec extend_zero_aux i v' acc = match v' with @@ -57,6 +58,8 @@ module SparseVector: AbstractVector = in "["^list_str t^"\n" + let show v = Timing.wrap "V.show" (show) v + let length v = v.len let compare_length_with v n = @@ -167,18 +170,29 @@ module SparseVector: AbstractVector = | (idx, value) :: xs, (y :: ys) -> remove_indices_helper xs cur_idx deleted_count ((idx - deleted_count, value) :: acc) in {entries = remove_indices_helper v.entries indices 0 []; len = v.len - List.length indices} - + + (** [keep_vals v n] returns returns a vector only containing the first [n] elements of [v] *) let keep_vals v n = if n >= v.len then v else {entries = List.take_while (fun (idx, _) -> idx < n) v.entries; len=n} - - let starting_from_nth n v = + + (** [starting_from_nth v n] returns a vector only containing the elements after the [n]th *) + let starting_from_nth v n = let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in {entries = entries'; len = v.len - n} let findi f v = + (* How this works: + Case 1: + A.zero is also to be found. The List.findi is used to have an iteration index i. + If at one point i < idx, it means that a Zero element was skipped because of the sparse vector representation. In that case i is the index of the first Zero, so returning true indicates that it is found. + f value still has to be checked in case other elements than Zero are to be found. + List.findi returns the index at which is was found in the tuple's first element. + Case 2: + A.zero is not to be found. We just iterate over the sparse list then and the index is returned if an element is found. + *) if f A.zero then - fst @@ List.findi (fun i (idx, value) -> if idx > i then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) + fst @@ List.findi (fun i (idx, value) -> if i < idx then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index f937432aba..4315644aa0 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -45,7 +45,7 @@ sig val keep_vals: t -> int -> t (* Returns the part of the vector starting from index n*) - val starting_from_nth : int -> t -> t + val starting_from_nth : t -> int -> t val findi: (num -> bool) -> t -> int From 9ecb30bee0677c9b9251ee8584bf5d0b100fce46 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 21 Jan 2025 17:29:02 +0100 Subject: [PATCH 187/240] Formatting --- .../sparseImplementation/sparseVector.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 715f04238b..1d026ce683 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -170,12 +170,12 @@ module SparseVector: AbstractVector = | (idx, value) :: xs, (y :: ys) -> remove_indices_helper xs cur_idx deleted_count ((idx - deleted_count, value) :: acc) in {entries = remove_indices_helper v.entries indices 0 []; len = v.len - List.length indices} - + (** [keep_vals v n] returns returns a vector only containing the first [n] elements of [v] *) let keep_vals v n = if n >= v.len then v else {entries = List.take_while (fun (idx, _) -> idx < n) v.entries; len=n} - + (** [starting_from_nth v n] returns a vector only containing the elements after the [n]th *) let starting_from_nth v n = let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in @@ -183,13 +183,13 @@ module SparseVector: AbstractVector = let findi f v = (* How this works: - Case 1: - A.zero is also to be found. The List.findi is used to have an iteration index i. - If at one point i < idx, it means that a Zero element was skipped because of the sparse vector representation. In that case i is the index of the first Zero, so returning true indicates that it is found. - f value still has to be checked in case other elements than Zero are to be found. - List.findi returns the index at which is was found in the tuple's first element. - Case 2: - A.zero is not to be found. We just iterate over the sparse list then and the index is returned if an element is found. + Case 1: + A.zero is also to be found. The List.findi is used to have an iteration index i. + If at one point i < idx, it means that a Zero element was skipped because of the sparse vector representation. In that case i is the index of the first Zero, so returning true indicates that it is found. + f value still has to be checked in case other elements than Zero are to be found. + List.findi returns the index at which is was found in the tuple's first element. + Case 2: + A.zero is not to be found. We just iterate over the sparse list then and the index is returned if an element is found. *) if f A.zero then fst @@ List.findi (fun i (idx, value) -> if i < idx then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) From 4890a03082a0a7db1a98f232c8134aebb1461ef6 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 21 Jan 2025 18:04:02 +0100 Subject: [PATCH 188/240] Optimize to_const_opt with find_first_non_zero --- src/cdomains/apron/affineEqualityDomain.apron.ml | 9 ++++++--- .../sparseMatrixImplementationTest.ml | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index a3764a3b04..644dc7730d 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -55,11 +55,14 @@ struct include ConvenienceOps(Mpqf) (** Get the constant from the vector if it is a constant *) - let to_constant_opt v = match Vector.findi ((<>:) Mpqf.zero) v with - | exception Not_found -> Some Mpqf.zero - | i when Vector.compare_length_with v (i + 1) = 0 -> Some (Vector.nth v i) + + let to_constant_opt v = match Vector.find_first_non_zero v with + | None -> Some Mpqf.zero + | Some (i, value) when i = (Vector.length v) - 1 -> Some value | _ -> None + let to_constant_opt v = Timing.wrap "to_constant_opt" (to_constant_opt) v + let get_coeff_vec (t: t) texp = (*Parses a Texpr to obtain a coefficient + const (last entry) vector to repr. an affine relation. Returns None if the expression is not affine*) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index d24d5b0895..2aeedff556 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -30,7 +30,7 @@ let make_matrix_of_2d_list l = (** This function runs the equality assertion with the solution after normalizing the matrix. *) let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in - let do_dimensions_match (r1, c1), (r2, c2) = r1 = r2 && c1 = c2 in + let do_dimensions_match (r1, c1) (r2, c2) = r1 = r2 && c1 = c2 in let matrix_dim = get_dimensions matrix in let solution_dim = get_dimensions solution in if not (do_dimensions_match solution_dim matrix_dim) then From 1ec9fbe21bc642652932dfee610df39251e8159a Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 21 Jan 2025 19:14:24 +0100 Subject: [PATCH 189/240] Update SparseVector.show to be sparse --- .../sparseImplementation/sparseVector.ml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 1d026ce683..a444c4e4b9 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -50,13 +50,15 @@ module SparseVector: AbstractVector = v.entries let show v = - let t = to_list v in - let rec list_str l = - match l with - | [] -> "]" - | x :: xs -> (A.to_string x) ^ " " ^ (list_str xs) + let rec sparse_list_str i l = + if i >= v.len then "]" + else match l with + | [] -> (A.to_string A.zero) ^" "^ (sparse_list_str (i + 1) l) + | (idx, value) :: xs -> + if i = idx then (A.to_string value) ^" "^ sparse_list_str (i + 1) xs + else (A.to_string A.zero) ^" "^ sparse_list_str (i + 1) l in - "["^list_str t^"\n" + "["^(sparse_list_str 0 v.entries)^"\n" let show v = Timing.wrap "V.show" (show) v From 5e169850b6967623961e267913a645640e2798e6 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Wed, 22 Jan 2025 12:02:43 +0100 Subject: [PATCH 190/240] Remove V.nth from map2 - not better? --- .../sparseImplementation/listMatrix.ml | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 820eb1b439..7146726c05 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -58,12 +58,44 @@ module ListMatrix: AbstractMatrix = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m + let map2 f m v = + let vector_length = V.length v in + let vector_entries = V.to_sparse_list v in + let rec map2_helper acc index m v = + match m, v with + | [], _ -> List.rev acc + | row :: rs, [] when index >= vector_length -> map2_helper (row :: acc) (index + 1) rs [] + | row :: rs, [] -> map2_helper ((f row A.zero):: acc) (index + 1) rs [] + | row :: rs, (i, value) :: vs -> + if i = index then + map2_helper ((f row value):: acc) (index + 1) rs vs + else + map2_helper ((f row A.zero) :: acc) (index + 1) rs v + in + map2_helper [] 0 m vector_entries + let map2 f m v = Timing.wrap "Matrix.map2" (map2 f m) v let map2i f m v = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row ) m + let map2i f m v = + let vector_length = V.length v in + let vector_entries = V.to_sparse_list v in + let rec map2_helper acc index m v = + match m, v with + | [], _ -> List.rev acc + | row :: rs, [] when index >= vector_length -> map2_helper (row :: acc) (index + 1) rs [] + | row :: rs, [] -> map2_helper ((f index row A.zero):: acc) (index + 1) rs [] + | row :: rs, (i, value) :: vs -> + if i = index then + map2_helper ((f index row value):: acc) (index + 1) rs vs + else + map2_helper ((f index row A.zero) :: acc) (index + 1) rs v + in + map2_helper [] 0 m vector_entries + let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v (** From af9104e43502300bb877425916bcab4eaff0f55d Mon Sep 17 00:00:00 2001 From: charlotte-brandt Date: Wed, 22 Jan 2025 12:04:43 +0100 Subject: [PATCH 191/240] Update src/cdomains/affineEquality/sparseImplementation/sparseVector.ml Co-authored-by: Michael Petter --- .../affineEquality/sparseImplementation/sparseVector.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a444c4e4b9..f36ec21e9c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -134,8 +134,7 @@ module SparseVector: AbstractVector = match vec, cur_idx with | [], _ -> List.rev acc (* inserting at the end only means changing the dimension *) | (idx, value) :: xs, [] -> add_indices_helper xs [] added_count ((idx + added_count, value) :: acc) - | (idx, value) :: xs, ((i, count) :: ys) when i = idx -> add_indices_helper vec ys (added_count + count) acc - | (idx, value) :: xs, ((i, count) :: ys) when i < idx -> add_indices_helper vec ys (added_count + count) acc + | (idx, _) :: _, ((i, count) :: ys) when i <= idx -> add_indices_helper vec ys (added_count + count) acc | (idx, value) :: xs, ((i, count) :: ys) -> add_indices_helper xs cur_idx added_count ((idx + added_count, value) :: acc) in {entries = add_indices_helper v.entries indices 0 []; len = v.len + num_zeros} From 9e155711f82ffaec7ca2f276d7ea8f12de728423 Mon Sep 17 00:00:00 2001 From: charlotte-brandt Date: Wed, 22 Jan 2025 12:05:40 +0100 Subject: [PATCH 192/240] Update src/cdomains/affineEquality/sparseImplementation/sparseVector.ml Co-authored-by: Michael Petter --- .../affineEquality/sparseImplementation/sparseVector.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index f36ec21e9c..87a0c3f050 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -166,8 +166,8 @@ module SparseVector: AbstractVector = | [], (y :: ys) when deleted_count >= v.len || y >= v.len -> raise (Invalid_argument "Indices out of bounds") | [], (y :: ys) -> remove_indices_helper [] ys (deleted_count + 1) acc | (idx, value) :: xs, [] -> remove_indices_helper xs [] deleted_count ((idx - deleted_count, value) :: acc) - | (idx, value) :: xs, (y :: ys) when y = idx -> remove_indices_helper xs ys (deleted_count + 1) acc - | (idx, value) :: xs, (y :: ys) when y < idx -> remove_indices_helper vec ys (deleted_count + 1) acc + | (idx, _) :: xs, (y :: ys) when y = idx -> remove_indices_helper xs ys (deleted_count + 1) acc + | (idx, _) :: xs, (y :: ys) when y < idx -> remove_indices_helper vec ys (deleted_count + 1) acc | (idx, value) :: xs, (y :: ys) -> remove_indices_helper xs cur_idx deleted_count ((idx - deleted_count, value) :: acc) in {entries = remove_indices_helper v.entries indices 0 []; len = v.len - List.length indices} From 5c45990055a7f91d6a720eb7558d901fb82200d4 Mon Sep 17 00:00:00 2001 From: charlotte-brandt Date: Wed, 22 Jan 2025 12:06:23 +0100 Subject: [PATCH 193/240] Update src/cdomains/affineEquality/sparseImplementation/sparseVector.ml Co-authored-by: Michael Petter --- .../affineEquality/sparseImplementation/sparseVector.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 87a0c3f050..3632eeb943 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -73,8 +73,8 @@ module SparseVector: AbstractVector = let is_zero_vec v = (v.entries = []) (** - [is_const_vec v] returns true if the v represents an affine equality over only one variable, i.e. a constant. - Constant vectors are represented by a two element list, however this is not an iff relationship.*) + [is_const_vec v] returns true if the v can be interpreted as an expression with one variable and possibly a constant, i.e. x_i + c + *) let is_const_vec v = match v.entries with | [] -> false From b0feb2a484c86f484ef324451fd6d34af3153da9 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Wed, 22 Jan 2025 12:27:20 +0100 Subject: [PATCH 194/240] Use Bat functions to improve readability --- .../affineEquality/sparseImplementation/listMatrix.ml | 8 +++----- .../affineEquality/sparseImplementation/sparseVector.ml | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 7146726c05..50c6290c00 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -4,6 +4,8 @@ open RatOps open ConvenienceOps open BatList +open BatOption + module List = BatList (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. @@ -302,11 +304,7 @@ module ListMatrix: AbstractMatrix = *) let rref_vec m v = if is_empty m then (* In this case, v is normalized and returned *) - match V.find_first_non_zero v with - | None -> None - | Some (_, value) -> - let normalized_v = div_row v value in - Some (init_with_vec normalized_v) + BatOption.map (fun (_, value) -> init_with_vec @@ div_row v value) (V.find_first_non_zero v) else (* We try to normalize v and check if a contradiction arises. If not, we insert v at the appropriate place in m (depending on the pivot) *) let pivot_positions = get_pivot_positions m in let v_after_elim = List.fold_left ( diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index a444c4e4b9..885ed9bc24 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -21,7 +21,7 @@ module SparseVector: AbstractVector = let copy v = v let of_list l = - let entries' = List.rev @@ List.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc) [] l + let entries' = List.filteri_map (fun i x -> if x <> A.zero then Some (i, x) else None) l in {entries = entries'; len = List.length l} let of_array a = From bc2cad00d486cd1ea7d7ada2ae0bca77b5f0e519 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Wed, 22 Jan 2025 17:44:56 +0100 Subject: [PATCH 195/240] Remove references in comments to missing not-zero-preserving functions --- .../sparseImplementation/sparseVector.ml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 7c9592f13a..4c597ad719 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -74,7 +74,7 @@ module SparseVector: AbstractVector = (** [is_const_vec v] returns true if the v can be interpreted as an expression with one variable and possibly a constant, i.e. x_i + c - *) + *) let is_const_vec v = match v.entries with | [] -> false @@ -201,8 +201,6 @@ module SparseVector: AbstractVector = [find2i_f_false_at_zero f v v'] returns the {b index} of the first pair of entries [e, e'] from [v, v'] where [f e e' = true ]. Note that [f] {b must} be such that [f 0 0 = false]! - - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} *) let find2i_f_false_at_zero f v v' = (*Very welcome to change the name*) let rec aux v1 v2 = @@ -259,7 +257,6 @@ module SparseVector: AbstractVector = Note that [f] {b must} be such that [f 0 = 0]! - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} *) let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) let entries' = List.filter_map ( @@ -274,7 +271,6 @@ module SparseVector: AbstractVector = Note that [f] {b must} be such that [f i 0 = 0] for any index [i]! - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} *) let mapi_f_preserves_zero f v = let entries' = List.filter_map ( @@ -287,8 +283,6 @@ module SparseVector: AbstractVector = Note that [f] {b must} be such that [f 0 0 = 0]! - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} - @raise Invalid_argument if [v] and [v'] have unequal lengths *) let map2_f_preserves_zero f v v' = @@ -342,8 +336,6 @@ module SparseVector: AbstractVector = [fold_left_f_preserves_zero f acc v] returns the fold of [v] on [acc] specified by [f]. Note that [f] {b must} be such that [f acc 0 = acc]! - - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} *) let fold_left_f_preserves_zero f acc v = List.fold_left (fun acc (_, value) -> f acc value) acc v.entries @@ -353,8 +345,6 @@ module SparseVector: AbstractVector = Note that [f] {b must} be such that [f acc 0 0 = acc]! - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} - @raise Invalid_argument if [v] and [v'] have unequal lengths *) let fold_left2_f_preserves_zero f acc v v' = @@ -376,8 +366,6 @@ module SparseVector: AbstractVector = [apply_with_c_f_preserves_zero f c v] returns the mapping of [v] and [c] specified by [f]. Note that [f] {b must} be such that [f 0 c = 0]! - - {i One should use this function over its general counterpart whenever possible, as it is considerably faster!} *) let apply_with_c_f_preserves_zero f c v = let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in From dc0da87030f82369848e2881a34fad0ac8828686 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Wed, 22 Jan 2025 18:42:07 +0100 Subject: [PATCH 196/240] Add comments to some vector functions and add some field punning for records --- .../sparseImplementation/sparseVector.ml | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 4c597ad719..192e58469a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -20,19 +20,26 @@ module SparseVector: AbstractVector = let copy v = v + (** [of_list l] returns a vector constructed from the non-sparse list [l] *) let of_list l = - let entries' = List.filteri_map (fun i x -> if x <> A.zero then Some (i, x) else None) l - in {entries = entries'; len = List.length l} + let entries = List.filteri_map (fun i x -> if x <> A.zero then Some (i, x) else None) l in + let len = List.length l in + {entries; len} + (** [of_array a] returns a vector constructed from the non-sparse array [a] *) let of_array a = - let len' = Array.length a in - let entries' = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in - {entries = entries'; len = len'} + let entries = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in + let len = Array.length a in + {entries; len} - let of_sparse_list count ls = - {entries = ls; len = count} + (** [of_sparse_list len entries] returns a vector of length [len] constructed from the sorted sparse list [entries]. + A sparse list is a list of tuples of the form [(i, value)] which represent that the vector has an entry [value] at index [i]. + All non-specified entries are assumed to be [Zero]. The sparse list has to be sorted by the index [i]. + *) + let of_sparse_list len entries = + {entries; len} - (** [to_list v] Returns a non-sparse list representing the vector v *) + (** [to_list v] returns a non-sparse list representing the vector v *) let to_list v = let rec extend_zero_aux i v' acc = match v' with @@ -64,11 +71,12 @@ module SparseVector: AbstractVector = let length v = v.len + let compare_length_with v n = Int.compare v.len n - let zero_vec n = - {entries = []; len = n} + let zero_vec len = + {entries = []; len} let is_zero_vec v = (v.entries = []) @@ -110,7 +118,7 @@ module SparseVector: AbstractVector = | (idx, value) :: xs when n < idx -> if num <>: A.zero then List.rev_append ((n, num) :: acc) vec else List.rev_append acc vec | x :: xs -> set_nth_helper xs (x :: acc) in - {entries = set_nth_helper v.entries []; len = v.len} + {v with entries = set_nth_helper v.entries []} (** [insert_val_at v n num] returns [v] where the [num] is inserted into the [n]-th position, i.e. [v] at [n] = [num]. @@ -119,11 +127,11 @@ module SparseVector: AbstractVector = let insert_val_at v n num = if n > v.len then raise (Invalid_argument "Index out of bounds") else - let entries' = List.rev @@ List.fold_left (fun acc (idx, value) -> + let entries = List.rev @@ List.fold_left (fun acc (idx, value) -> if idx < n then (idx, value) :: acc else (if num <>: A.zero then (idx + 1, value) :: (n, num) :: acc else (idx + 1, value) :: acc) ) [] v.entries in - {entries = entries'; len = v.len + 1} + {entries; len = v.len + 1} (** [insert_zero_at_indices v indices num_zeros] inserts [num_zeros] into [v]. @@ -146,13 +154,13 @@ module SparseVector: AbstractVector = let remove_nth v n = if n >= v.len then raise (Invalid_argument "Index out of bounds") else - let new_entries = List.filter_map (fun (idx, value) -> + let entries = List.filter_map (fun (idx, value) -> if idx = n then None else if idx > n then Some (idx - 1, value) else Some (idx, value) ) v.entries in - {entries = new_entries; len = v.len - 1} + {entries; len = v.len - 1} (** [remove_at_indices v indices] returns [v] where all entries at the positions specified by [indices] are removed, decreasing its length by the length of [indices]. @@ -179,8 +187,8 @@ module SparseVector: AbstractVector = (** [starting_from_nth v n] returns a vector only containing the elements after the [n]th *) let starting_from_nth v n = - let entries' = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in - {entries = entries'; len = v.len - n} + let entries = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in + {entries; len = v.len - n} let findi f v = (* How this works: @@ -259,10 +267,10 @@ module SparseVector: AbstractVector = *) let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) - let entries' = List.filter_map ( + let entries = List.filter_map ( fun (idx, value) -> let new_val = f value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in - {entries = entries'; len = v.len} + {entries; len = v.len} let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v @@ -273,10 +281,10 @@ module SparseVector: AbstractVector = *) let mapi_f_preserves_zero f v = - let entries' = List.filter_map ( + let entries = List.filter_map ( fun (idx, value) -> let new_val = f idx value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in - {entries = entries'; len = v.len} + {entries; len = v.len} (** [map2_f_preserves_zero f v v'] returns the mapping of [v] and [v'] specified by [f]. @@ -302,7 +310,7 @@ module SparseVector: AbstractVector = | _ -> aux (f_rem_zero acc xidx xval yval) xs ys in if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else - {entries = List.rev (aux [] v.entries v'.entries); len = v.len} + {v with entries = List.rev (aux [] v.entries v'.entries)} let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 @@ -330,7 +338,7 @@ module SparseVector: AbstractVector = | d when d > 0 -> aux (f_rem_zero i acc A.zero yval) vec1 ys (i + 1) | _ -> aux (f_rem_zero i acc xval yval) xs ys (i + 1) in - {entries = List.rev (aux [] v.entries v'.entries 0); len = v.len} + {v with entries = List.rev (aux [] v.entries v'.entries 0)} (** [fold_left_f_preserves_zero f acc v] returns the fold of [v] on [acc] specified by [f]. @@ -368,14 +376,14 @@ module SparseVector: AbstractVector = Note that [f] {b must} be such that [f 0 c = 0]! *) let apply_with_c_f_preserves_zero f c v = - let entries' = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in - {entries = entries'; len = v.len} + let entries = List.filter_map (fun (idx, value) -> let new_val = f value c in if new_val =: A.zero then None else Some (idx, new_val)) v.entries in + {entries; len = v.len} let rev v = - let entries' = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in - {entries = entries'; len = v.len} + let entries = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in + {entries; len = v.len} let append v v' = - let entries' = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in - {entries = entries'; len = v.len + v'.len} + let entries = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in + {entries; len = v.len + v'.len} end From fd70b72360dfe0a8afa7da2bc279e46c0a3e8219 Mon Sep 17 00:00:00 2001 From: charlotte-brandt Date: Thu, 23 Jan 2025 13:12:28 +0100 Subject: [PATCH 197/240] Update src/cdomains/affineEquality/sparseImplementation/sparseVector.ml Co-authored-by: Michael Schwarz --- .../affineEquality/sparseImplementation/sparseVector.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 192e58469a..9504da21e5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -201,7 +201,7 @@ module SparseVector: AbstractVector = A.zero is not to be found. We just iterate over the sparse list then and the index is returned if an element is found. *) if f A.zero then - fst @@ List.findi (fun i (idx, value) -> if i < idx then true else f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) + fst @@ List.findi (fun i (idx, value) -> i < idx || f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) else fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) From 426d739cf7c9e96cfc74afed8917debfb71bd0e2 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 24 Jan 2025 10:32:14 +0100 Subject: [PATCH 198/240] Optimize get_pivot_positions to also return the row itself --- .../affineEquality/sparseImplementation/listMatrix.ml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 50c6290c00..3369b3e9b5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -186,7 +186,7 @@ module ListMatrix: AbstractMatrix = List.rev @@ List.fold_lefti ( fun acc i row -> match V.find_first_non_zero row with | None -> acc - | Some (pivot_col, _) -> (i, pivot_col) :: acc + | Some (pivot_col, _) -> (i, pivot_col, row) :: acc ) [] m (** @@ -289,9 +289,9 @@ module ListMatrix: AbstractMatrix = *) let insert_v_according_to_piv m v piv_idx pivot_positions = let reduced_m = reduce_col_with_vec m piv_idx v in - match List.find_opt (fun (row_idx, piv_col) -> piv_col > piv_idx) pivot_positions with + match List.find_opt (fun (row_idx, piv_col, _) -> piv_col > piv_idx) pivot_positions with | None -> append_row reduced_m v - | Some (row_idx, _) -> + | Some (row_idx, _, _) -> let (before, after) = List.split_at row_idx reduced_m in before @ (v :: after) @@ -308,12 +308,11 @@ module ListMatrix: AbstractMatrix = else (* We try to normalize v and check if a contradiction arises. If not, we insert v at the appropriate place in m (depending on the pivot) *) let pivot_positions = get_pivot_positions m in let v_after_elim = List.fold_left ( - fun acc (row_idx, pivot_position) -> + fun acc (row_idx, pivot_position, piv_row) -> let v_at_piv = V.nth acc pivot_position in if v_at_piv =: A.zero then acc else - let piv_row = List.nth m row_idx in sub_scaled_row acc piv_row v_at_piv ) v pivot_positions in From 6fef8120f1e89388b19d19c6d61c5f111a6dfe13 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 24 Jan 2025 14:58:35 +0100 Subject: [PATCH 199/240] Punning and List.rev_map --- .../sparseImplementation/sparseVector.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 9504da21e5..e45d26eb5a 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -267,10 +267,10 @@ module SparseVector: AbstractVector = *) let map_f_preserves_zero f v = (* map for functions f such that f 0 = 0 since f won't be applied to zero values. See also map *) - let entries = List.filter_map ( + let entries' = List.filter_map ( fun (idx, value) -> let new_val = f value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in - {entries; len = v.len} + {v with entries = entries'} let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v @@ -281,10 +281,10 @@ module SparseVector: AbstractVector = *) let mapi_f_preserves_zero f v = - let entries = List.filter_map ( + let entries' = List.filter_map ( fun (idx, value) -> let new_val = f idx value in if new_val = A.zero then None else Some (idx, new_val)) v.entries in - {entries; len = v.len} + {v with entries = entries'} (** [map2_f_preserves_zero f v v'] returns the mapping of [v] and [v'] specified by [f]. @@ -380,7 +380,7 @@ module SparseVector: AbstractVector = {entries; len = v.len} let rev v = - let entries = List.rev @@ List.map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in + let entries = List.rev_map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in {entries; len = v.len} let append v v' = From 335832c3f3a936a6f66308bb7188548eee671f7e Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 24 Jan 2025 15:25:06 +0100 Subject: [PATCH 200/240] Change SparseVector.of_array to BatList.fold_righti --- .../affineEquality/sparseImplementation/sparseVector.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index e45d26eb5a..7b75e08177 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -28,7 +28,7 @@ module SparseVector: AbstractVector = (** [of_array a] returns a vector constructed from the non-sparse array [a] *) let of_array a = - let entries = List.rev @@ Array.fold_lefti (fun acc i x -> if x <> A.zero then (i, x) :: acc else acc ) [] a in + let entries = Array.fold_righti (fun i x acc -> if x <> A.zero then (i, x) :: acc else acc ) a [] in let len = Array.length a in {entries; len} From 6819b4a47aeee67f0ed09249cee1959bc4f85db1 Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Fri, 24 Jan 2025 15:46:02 +0100 Subject: [PATCH 201/240] Update sparseVector exists Co-authored-by: Michael Schwarz --- .../sparseImplementation/sparseVector.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 7b75e08177..86cdd7b980 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -254,11 +254,11 @@ module SparseVector: AbstractVector = let exists f v = let c = v.len in - let rec exists_aux at f v = - match v with - | [] -> if at = 0 then false else f A.zero - | (xi, xv) :: xs -> if f xv then true else exists_aux (at - 1) f xs - in (exists_aux c f v.entries) + let rec exists_aux at = function + | [] -> if at = 0 then false (* vector is dense *) else f A.zero + | (_, xv) :: xs -> f xv || exists_aux (at - 1) xs + in + exists_aux c v.entries (** [map_f_preserves_zero f v] returns the mapping of [v] specified by [f]. From 15d2fb737c5695e8dfefc109905b6fc8c85eae89 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Fri, 24 Jan 2025 18:02:59 +0100 Subject: [PATCH 202/240] Split up interface and restore old domain and array implementation --- .../apron/affineEqualityAnalysis.apron.ml | 6 + src/cdomains/affineEquality/abstractMatrix.ml | 16 +- src/cdomains/affineEquality/abstractVector.ml | 14 +- .../arrayImplementation/arrayMatrix.ml | 111 ++-- .../arrayImplementation/arrayVector.ml | 60 +- src/cdomains/affineEquality/matrix.ml | 31 +- .../sparseImplementation/listMatrix.ml | 4 +- .../sparseImplementation/sparseVector.ml | 2 +- src/cdomains/affineEquality/vector.ml | 54 +- .../apron/affineEqualityDomain.apron.ml | 10 +- .../affineEqualityDomainSideEffects.apron.ml | 607 ++++++++++++++++++ ...ffineEqualityDomainSideEffects.no-apron.ml | 5 + src/dune | 4 + src/goblint_lib.ml | 1 + 14 files changed, 764 insertions(+), 161 deletions(-) create mode 100644 src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml create mode 100644 src/cdomains/apron/affineEqualityDomainSideEffects.no-apron.ml diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index ca1ce5683b..6e32e23145 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -7,11 +7,17 @@ open Analyses open SparseVector open ListMatrix +(* To use the original affineEqualityDomain implementation uncomment this and the AD_Array. + Then replace AD with AD_Array in the functor application. + open ArrayVector + open ArrayMatrix *) + include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = lazy ( let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in + (* let module AD_Array = AffineEqualityDomainSideEffects.D2 (ArrayVector) (ArrayMatrix) in *) let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/cdomains/affineEquality/abstractMatrix.ml b/src/cdomains/affineEquality/abstractMatrix.ml index 64181c1a2b..62e7a3a127 100644 --- a/src/cdomains/affineEquality/abstractMatrix.ml +++ b/src/cdomains/affineEquality/abstractMatrix.ml @@ -3,9 +3,19 @@ open AbstractVector open Matrix (** Some functions inside have the suffix _with, which means that the function has side effects. *) -module type AbstractMatrix = - functor (A: RatOps) (V: AbstractVector) -> +module type ArrayMatrixFunctor = + functor (A: RatOps) (V: ArrayVectorFunctor) -> sig - include Matrix with type vec := V(A).t and type num := A.t + include ArrayMatrix with type vec := V(A).t and type num := A.t end +module type SparseMatrixFunctor = + functor (A: RatOps) (V: SparseVectorFunctor) -> + sig + include SparseMatrix with type vec := V(A).t and type num := A.t + end + +(* let timing_wrap = Timing.wrap *) +(* Disable timing of VectorMatrix and AffineEqualityDomain. + This is cleaner than a timing functor because the timed functions also call each other. *) +let timing_wrap _ f x = f x diff --git a/src/cdomains/affineEquality/abstractVector.ml b/src/cdomains/affineEquality/abstractVector.ml index b4de95f30b..e20f92c2f4 100644 --- a/src/cdomains/affineEquality/abstractVector.ml +++ b/src/cdomains/affineEquality/abstractVector.ml @@ -1,9 +1,19 @@ open RatOps open Vector -module type AbstractVector = +module type ArrayVectorFunctor = functor (A: RatOps) -> sig - include Vector with type num:= A.t + include ArrayVector with type num:= A.t end +module type SparseVectorFunctor = + functor (A: RatOps) -> + sig + include SparseVector with type num:= A.t + end + +(* let timing_wrap = Timing.wrap *) +(* Disable timing of VectorMatrix and AffineEqualityDomain. + This is cleaner than a timing functor because the timed functions also call each other. *) +let timing_wrap _ f x = f x diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index a5b70764f4..6883651bee 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -11,8 +11,8 @@ module Array = Batteries.Array Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) (* The functions that have the suffix _with have side effects and were used in a previous version of the affineEqualityDomain. These calls were removed to transition to list-based matrices.*) -module ArrayMatrix: AbstractMatrix = - functor (A: RatOps) (V: AbstractVector) -> +module ArrayMatrix: ArrayMatrixFunctor = + functor (A: RatOps) (V: ArrayVectorFunctor) -> struct include ConvenienceOps(A) module V = V(A) @@ -38,10 +38,9 @@ module ArrayMatrix: AbstractMatrix = let cp = Array.make_matrix (num_rows m) (num_cols m) A.zero in Array.iteri (fun i x -> Array.blit x 0 cp.(i) 0 (num_cols m)) m; cp - let copy m = Timing.wrap "copy" (copy) m + let copy m = timing_wrap "copy" (copy) m let add_empty_columns m cols = - Array.modifyi (+) cols; let nnc = Array.length cols in if is_empty m || nnc = 0 then m else let nr, nc = num_rows m, num_cols m in @@ -55,7 +54,7 @@ module ArrayMatrix: AbstractMatrix = done; m' - let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols + let add_empty_columns m cols = timing_wrap "add_empty_cols" (add_empty_columns m) cols let append_row m row = let size = num_rows m in @@ -82,17 +81,14 @@ module ArrayMatrix: AbstractMatrix = let get_col m n = V.of_array @@ Array.init (Array.length m) (fun i -> m.(i).(n)) - let get_col m n = Timing.wrap "get_col" (get_col m) n - - let get_col_upper_triangular m n = get_col m n (* Never implemented optimized version *) + let get_col m n = timing_wrap "get_col" (get_col m) n let set_col_with m new_col n = for i = 0 to num_rows m - 1 do m.(i).(n) <- V.nth new_col i - done; - m + done; m - let set_col_with m new_col n = Timing.wrap "set_col" (set_col_with m new_col) n + let set_col_with m new_col n = timing_wrap "set_col" (set_col_with m new_col) n let set_col m new_col n = let copy = copy m in @@ -101,7 +97,7 @@ module ArrayMatrix: AbstractMatrix = let append_matrices m1 m2 = Array.append m1 m2 - let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 + let equal m1 m2 = timing_wrap "equal" (equal m1) m2 let reduce_col_with m j = if not @@ is_empty m then @@ -119,7 +115,7 @@ module ArrayMatrix: AbstractMatrix = done; if !r >= 0 then Array.fill m.(!r) 0 (num_cols m) A.zero) - let reduce_col_with m j = Timing.wrap "reduce_col_with" (reduce_col_with m) j + let reduce_col_with m j = timing_wrap "reduce_col_with" (reduce_col_with m) j let reduce_col m j = let copy = copy m in reduce_col_with copy j; @@ -148,7 +144,12 @@ module ArrayMatrix: AbstractMatrix = done; m' - let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols + let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols + + let map2i f m v = + let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in + let range_array = Array.init (V.length v) Fun.id in + Array.map2 f' m (Array.combine range_array (V.to_array v)) let remove_zero_rows m = Array.filter (fun x -> Array.exists (fun y -> y <>: A.zero) x) m @@ -167,19 +168,19 @@ module ArrayMatrix: AbstractMatrix = for i = 0 to num_rows-1 do let exception Found in try ( - for j = i to num_cols -2 do (* Find pivot *) + for j = i to num_cols -2 do for k = i to num_rows -1 do if m.(k).(j) <>: A.zero then ( if k <> i then swap_rows k i; let piv = m.(i).(j) in - Array.iteri(fun j' x -> m.(i).(j') <- x /: piv) m.(i); (* Normalize pivot *) - for l = 0 to num_rows-1 do (* Subtract from each row *) + Array.iteri(fun j' x -> m.(i).(j') <- x /: piv) m.(i); + for l = 0 to num_rows-1 do if l <> i && m.(l).(j) <>: A.zero then ( let is_only_zero = ref true in let m_lj = m.(l).(j) in for k = 0 to num_cols - 2 do - m.(l).(k) <- m.(l).(k) -: m.(i).(k) *: m_lj /: m.(i).(j); (* Subtraction *) + m.(l).(k) <- m.(l).(k) -: m.(i).(k) *: m_lj /: m.(i).(j); if m.(l).(k) <>: A.zero then is_only_zero := false; done; let k_end = num_cols - 1 in @@ -197,7 +198,7 @@ module ArrayMatrix: AbstractMatrix = true) with Unsolvable -> false - let rref_with m = Timing.wrap "rref_with" rref_with m + let rref_with m = timing_wrap "rref_with" rref_with m let init_with_vec v = let new_matrix = Array.make_matrix 1 (V.length v) A.zero in @@ -211,12 +212,11 @@ module ArrayMatrix: AbstractMatrix = Array.iteri (fun j' x -> m.(i).(j') <- x -: beta *: v.(j')) m.(i) done - let get_pivot_positions m = let pivot_elements = Array.make (num_rows m) 0 in Array.iteri (fun i x -> pivot_elements.(i) <- Array.findi (fun z -> z =: A.one) x) m; pivot_elements - let rref_vec_helper m pivot_positions v = + let rref_vec m pivot_positions v = let insert = ref (-1) in for j = 0 to Array.length v -2 do if v.(j) <>: A.zero then @@ -240,40 +240,23 @@ module ArrayMatrix: AbstractMatrix = else (Array.blit m 0 new_m 0 i; new_m.(i) <- v; Array.blit m i new_m (i + 1) (Array.length m - j)); Some new_m - let normalize_with m = - rref_with m - let normalize_with m = Timing.wrap "normalize_with" normalize_with m - - let normalize m = - let copy = copy m in - if normalize_with copy then - Some copy - else - None let rref_vec_with m v = (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) let v = V.to_array v in - if is_empty m then + if is_empty m then match Array.findi (fun x -> x <>: A.zero) v with | exception Not_found -> None | i -> if i = Array.length v - 1 then None else let v_i = v.(i) in Array.iteri (fun j x -> v.(j) <- x /: v_i) v; Some (init_with_vec @@ V.of_array v) - else + else let pivot_elements = get_pivot_positions m in - rref_vec_helper m pivot_elements v - - let rref_vec_with m v = Timing.wrap "rref_vec_with" (rref_vec_with m) v + rref_vec m pivot_elements v - let rref_vec m v = (* !! There was another rref_vec function that has been renamed to rref_vec_helper !!*) - let m' = copy m in - let v' = V.copy v in - match rref_vec_with m' v' with - | Some res -> Some (remove_zero_rows res) - | None -> None + let rref_vec_with m v = timing_wrap "rref_vec_with" (rref_vec_with m) v let rref_matrix_with m1 m2 = (*Similar to rref_vec_with but takes two matrices instead.*) @@ -284,7 +267,7 @@ module ArrayMatrix: AbstractMatrix = try ( for i = 0 to num_rows s_m - 1 do let pivot_elements = get_pivot_positions !b in - let res = rref_vec_helper !b pivot_elements s_m.(i) in + let res = rref_vec !b pivot_elements s_m.(i) in match res with | None -> raise Unsolvable | Some res -> b := res @@ -293,14 +276,19 @@ module ArrayMatrix: AbstractMatrix = ) with Unsolvable -> None - let rref_matrix_with m1 m2 = Timing.wrap "rref_matrix_with" (rref_matrix_with m1) m2 + let rref_matrix_with m1 m2 = timing_wrap "rref_matrix_with" (rref_matrix_with m1) m2 - let rref_matrix m1 m2 = - let m1' = copy m1 in - let m2' = copy m2 in - match rref_matrix_with m1' m2' with - | Some m -> Some m - | None -> None + let normalize_with m = + rref_with m + + let normalize_with m = timing_wrap "normalize_with" normalize_with m + + let normalize m = + let copy = copy m in + if normalize_with copy then + Some copy + else + None let is_covered_by m1 m2 = (*Performs a partial rref reduction to check if concatenating both matrices and afterwards normalizing them would yield a matrix <> m2 *) @@ -309,7 +297,6 @@ module ArrayMatrix: AbstractMatrix = let p2 = lazy (get_pivot_positions m2) in try ( for i = 0 to num_rows m1 - 1 do - (* check if there are rows in m1 and m2 that aren't equal *) if Array.exists2 (<>:) m1.(i) m2.(i) then let m1_i = Array.copy m1.(i) in for j = 0 to Array.length m1_i - 2 do @@ -326,11 +313,13 @@ module ArrayMatrix: AbstractMatrix = ) with Stdlib.Exit -> false;; - let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 + let is_covered_by m1 m2 = timing_wrap "is_covered_by" (is_covered_by m1) m2 let find_opt f m = let f' x = f (V.of_array x) in Option.map V.of_array (Array.find_opt f' m) + let map2 f m v = + let f' x y = V.to_array @@ f (V.of_array x) y in Array.map2 f' m (V.to_array v) let map2_with f m v = if num_rows m = V.length v then @@ -340,12 +329,7 @@ module ArrayMatrix: AbstractMatrix = m.(i) <- V.to_array @@ f (V.of_array m.(i)) (V.nth v i) done - let map2_with f m v = Timing.wrap "map2_with" (map2_with f m) v - - let map2 f m v = - let m' = copy m in - map2_with f m' v; - m' + let map2_with f m v = timing_wrap "map2_with" (map2_with f m) v let map2i_with f m v = if num_rows m = V.length v then @@ -355,14 +339,5 @@ module ArrayMatrix: AbstractMatrix = m.(i) <- V.to_array @@ f i (V.of_array m.(i)) (V.nth v i) done - let map2i_with f m v = Timing.wrap "map2i_with" (map2i_with f m) v - - let map2i f m v = - let m' = copy m in - map2i_with f m' v; - m' - - let swap_rows m j k = - failwith "TODO" - + let map2i_with f m v = timing_wrap "map2i_with" (map2i_with f m) v end \ No newline at end of file diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 480beac534..db84354d51 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -7,7 +7,7 @@ module Array = Batteries.Array (** Array-based vector implementation. *) -module ArrayVector: AbstractVector = +module ArrayVector: ArrayVectorFunctor = functor (A: RatOps) -> struct include ConvenienceOps (A) @@ -30,14 +30,10 @@ module ArrayVector: AbstractVector = let compare_length_with v len = Int.compare (Array.length v) len - let remove_nth v n = + let remove_val v n = if n >= Array.length v then failwith "n outside of Array range" else Array.init (Array.length v - 1) (fun i -> if i < n then Array.get v i else Array.get v (i + 1)) (* TODO: remove_at? *) - let remove_at_indices v idx = failwith "TODO" - - let insert_zero_at_indices v idx count = failwith "TODO" - let set_nth_with v n new_val = if n >= Array.length v then failwith "n outside of Array range" else Array.set v n new_val @@ -46,17 +42,15 @@ module ArrayVector: AbstractVector = let copy = copy v in set_nth_with copy n new_val; copy - let insert_val_at v n num = + let insert_val_at v n new_val = if n > Array.length v then failwith "n too large" else - Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then num else Array.get v (i -1)) (* insert? *) + Array.init (Array.length v + 1) (fun i -> if i < n then Array.get v i else if i = n then new_val else Array.get v (i -1)) (* insert? *) let apply_with_c f c v = Array.map (fun x -> f x c) v let zero_vec n = Array.make n A.zero - let is_zero_vec v = not (Array.exists (fun x -> x <>: A.zero) v) - let is_const_vec v = compare_length_with (filteri (fun i x -> (*Inefficient*) compare_length_with v (i + 1) > 0 && x <>: A.zero) v) 1 = 0 @@ -67,34 +61,27 @@ module ArrayVector: AbstractVector = let f' i = uncurry (f i) in Array.mapi f' (Array.combine v1 v2) (* TODO: iter2i? *) + let map2i_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f i x y) v1 v2 + let find2i f v1 v2 = Array.findi (uncurry f) (Array.combine v1 v2) (* TODO: iter2i? *) - let find2i_f_false_at_zero f v v' = - find2i f v v' - let to_array v = v let of_array v = v - let rev v = Array.rev v + let apply_with_c_with f c v = Array.modify (fun x -> f x c) v - let map f v = Array.map f v + let rev_with v = Array.rev_in_place v - let map2_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f x y) v1 v2 + let map_with f v = Array.modify f v - let map2 f v1 v2 = - let copy_v1 = copy v1 in - map2_with f copy_v1 v2; copy_v1 + let map2_with f v1 v2 = Array.iter2i (fun i x y -> v1.(i) <- f x y) v1 v2 let copy v = Array.copy v let mapi_with f v = Array.iteri (fun i x -> v.(i) <- f i x) v - let mapi f v = - let copy = copy v in - mapi_with f copy; copy - let of_sparse_list col_count ls = let vec = Array.make col_count A.zero in List.iter (fun (idx, value) -> vec.(idx) <- value) ls; @@ -108,31 +95,4 @@ module ArrayVector: AbstractVector = let acc = if value <> A.zero then (idx, value):: acc else acc in aux (idx - 1) acc in aux (length v - 1) [] - - let map_f_preserves_zero f v = - map f v - - let map2_f_preserves_zero f v1 v2 = - map2 f v1 v2 - - let mapi_f_preserves_zero f v = - mapi f v - - let fold_left_f_preserves_zero f acc v = - failwith "Never implemented!" - - let fold_left2_f_preserves_zero f acc v v' = - failwith "Never implemented!" - - let findi_val_opt f v = - failwith "Never implemented!" - - let starting_from_nth v n = - failwith "Never implemented!" - - let find_first_non_zero v = - failwith "Never implemented!" - - let apply_with_c_f_preserves_zero f c v = - apply_with_c f c v end \ No newline at end of file diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index fd2de28588..f356872480 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -27,8 +27,6 @@ sig val remove_zero_rows: t -> t - val swap_rows: t -> int -> int -> t - val map2: (vec -> num -> vec) -> t -> vec -> t val map2i: (int -> vec-> num -> vec) -> t -> vec -> t @@ -37,8 +35,6 @@ sig val get_col: t -> int -> vec - val get_col_upper_triangular: t -> int -> vec - val set_col: t -> vec -> int -> t val del_col: t -> int -> t @@ -51,12 +47,31 @@ sig val reduce_col: t -> int -> t - val normalize: t -> t Option.t (*Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution*) + val normalize: t -> t Option.t (* Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution *) - val rref_vec: t -> vec -> t Option.t + val is_covered_by: t -> t -> bool - val rref_matrix: t -> t -> t Option.t +end - val is_covered_by: t -> t -> bool +module type ArrayMatrix = +sig + include Matrix + val set_col_with: t -> vec -> int -> t + val reduce_col_with: t -> int -> unit + val normalize_with: t -> bool + + val rref_vec_with: t -> vec -> t Option.t + val rref_matrix_with: t -> t -> t Option.t + val map2_with: (vec -> num -> vec) -> t -> vec -> unit + val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit +end + +module type SparseMatrix = +sig + include Matrix + val get_col_upper_triangular: t -> int -> vec + val swap_rows: t -> int -> int -> t + val rref_vec: t -> vec -> t Option.t + val rref_matrix: t -> t -> t Option.t end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 3369b3e9b5..6934912460 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -11,8 +11,8 @@ module List = BatList (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) -module ListMatrix: AbstractMatrix = - functor (A: RatOps) (V: AbstractVector) -> +module ListMatrix: SparseMatrixFunctor = + functor (A: RatOps) (V: SparseVectorFunctor) -> struct include ConvenienceOps(A) module V = V(A) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index e45d26eb5a..65a1c370b5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -8,7 +8,7 @@ open Batteries module List = BatList module Array = BatArray -module SparseVector: AbstractVector = +module SparseVector: SparseVectorFunctor = functor (A: RatOps) -> struct include ConvenienceOps (A) diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index 4315644aa0..c106051a2c 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -26,8 +26,6 @@ sig val zero_vec: int -> t - val is_zero_vec: t -> bool - val is_const_vec: t -> bool val nth: t -> int -> num @@ -36,43 +34,55 @@ sig val insert_val_at: t -> int -> num -> t - val insert_zero_at_indices: t -> (int * int) list -> int -> t - - val remove_nth: t -> int -> t + val keep_vals: t -> int -> t - val remove_at_indices: t -> int list -> t + val findi: (num -> bool) -> t -> int - val keep_vals: t -> int -> t + val exists: (num -> bool) -> t -> bool - (* Returns the part of the vector starting from index n*) - val starting_from_nth : t -> int -> t + val map2i: (int -> num -> num -> num) -> t -> t -> t - val findi: (num -> bool) -> t -> int + val rev: t -> t - val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int + val append: t -> t -> t +end - (* Returns optional tuple of position and value which was found*) - val findi_val_opt: (num -> bool) -> t -> (int * num) Option.t +module type SparseVector = +sig + include Vector + val is_zero_vec: t -> bool - val find_first_non_zero : t -> (int * num) option + val insert_zero_at_indices: t -> (int * int) list -> int -> t - val exists: (num -> bool) -> t -> bool + val remove_nth: t -> int -> t + val remove_at_indices: t -> int list -> t + (* Returns the part of the vector starting from index n*) + val starting_from_nth : t -> int -> t + val find_first_non_zero : t -> (int * num) option val map_f_preserves_zero: (num -> num) -> t -> t val mapi_f_preserves_zero: (int -> num -> num) -> t -> t val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t - - val map2i: (int -> num -> num -> num) -> t -> t -> t - + val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int val fold_left_f_preserves_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc val fold_left2_f_preserves_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t - - val rev: t -> t - - val append: t -> t -> t +end + +module type ArrayVector = +sig + include Vector + val mapi_with: (int -> num -> num) -> t -> unit + val map_with: (num -> num) -> t -> unit + val map2_with: (num -> num -> num) -> t -> t -> unit + val map2i_with: (int -> num -> num -> num) -> t -> t -> unit + val filteri: (int -> num -> bool) -> t -> t + val find2i: (num -> num -> bool) -> t -> t -> int + val set_nth_with: t -> int -> num -> unit + val apply_with_c_with: (num -> num -> num) -> num -> t -> unit + val rev_with: t -> unit end \ No newline at end of file diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 644dc7730d..9f8cbba819 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -22,7 +22,7 @@ module Array = Batteries.Array module Mpqf = SharedFunctions.Mpqf -module AffineEqualityMatrix (Vec: AbstractVector) (Mx: AbstractMatrix) = +module AffineEqualityMatrix (Vec: SparseVectorFunctor) (Mx: SparseMatrixFunctor) = struct include Mx(Mpqf) (Vec) let dim_add (ch: Apron.Dim.change) m = @@ -44,7 +44,7 @@ end (** It defines the type t of the affine equality domain (a struct that contains an optional matrix and an apron environment) and provides the functions needed for handling variables (which are defined by RelationDomain.D2) such as add_vars remove_vars. Furthermore, it provides the function get_coeff_vec that parses an apron expression into a vector of coefficients if the apron expression has an affine form. *) -module VarManagement (Vec: AbstractVector) (Mx: AbstractMatrix)= +module VarManagement (Vec: SparseVectorFunctor) (Mx: SparseMatrixFunctor)= struct module Vector = Vec (Mpqf) module Matrix = AffineEqualityMatrix (Vec) (Mx) @@ -122,7 +122,7 @@ struct end (** As it is specifically used for the new affine equality domain, it can only provide bounds if the expression contains known constants only and in that case, min and max are the same. *) -module ExpressionBounds (Vc: AbstractVector) (Mx: AbstractMatrix): (SharedFunctions.ConvBounds with type t = VarManagement(Vc) (Mx).t) = +module ExpressionBounds (Vc: SparseVectorFunctor) (Mx: SparseMatrixFunctor): (SharedFunctions.ConvBounds with type t = VarManagement(Vc) (Mx).t) = struct include VarManagement (Vc) (Mx) @@ -148,7 +148,7 @@ struct let bound_texpr d texpr1 = Timing.wrap "bounds calculation" (bound_texpr d) texpr1 end -module D(Vc: AbstractVector) (Mx: AbstractMatrix) = +module D(Vc: SparseVectorFunctor) (Mx: SparseMatrixFunctor) = struct include Printable.Std include ConvenienceOps (Mpqf) @@ -591,7 +591,7 @@ struct let unmarshal t = t end -module D2(Vc: AbstractVector) (Mx: AbstractMatrix): RelationDomain.RD with type var = Var.t = +module D2(Vc: SparseVectorFunctor) (Mx: SparseMatrixFunctor): RelationDomain.RD with type var = Var.t = struct module D = D (Vc) (Mx) module ConvArg = struct diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml new file mode 100644 index 0000000000..f5eb840998 --- /dev/null +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -0,0 +1,607 @@ +(** OCaml implementation of the affine equalities domain. + + @see Karr, M. Affine relationships among variables of a program. *) + +(** Abstract states in the newly added domain are represented by structs containing a matrix and an apron environment. + Matrices are modeled as proposed by Karr: Each variable is assigned to a column and each row represents a linear affine relationship that must hold at the corresponding program point. + The apron environment is hereby used to organize the order of columns and variables. *) + +open GoblintCil +open Pretty +module M = Messages +open GobApron + +open ConvenienceOps +open AbstractVector +open AbstractMatrix + +open Batteries +module Array = BatArray + +module Mpqf = SharedFunctions.Mpqf + +module AffineEqualityMatrix (Vec: ArrayVectorFunctor) (Mx: ArrayMatrixFunctor) = +struct + include Mx(Mpqf) (Vec) + let dim_add (ch: Apron.Dim.change) m = + Array.modifyi (+) ch.dim; + add_empty_columns m ch.dim + + let dim_add ch m = timing_wrap "dim add" (dim_add ch) m + + + let dim_remove (ch: Apron.Dim.change) m ~del = + if Array.length ch.dim = 0 || is_empty m then + m + else ( + Array.modifyi (+) ch.dim; + let m' = if not del then let m = copy m in Array.fold_left (fun y x -> reduce_col_with y x; y) m ch.dim else m in + remove_zero_rows @@ del_cols m' ch.dim) + + let dim_remove ch m ~del = timing_wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del +end + +(** It defines the type t of the affine equality domain (a struct that contains an optional matrix and an apron environment) and provides the functions needed for handling variables (which are defined by RelationDomain.D2) such as add_vars remove_vars. + Furthermore, it provides the function get_coeff_vec that parses an apron expression into a vector of coefficients if the apron expression has an affine form. *) +module VarManagement (Vec: ArrayVectorFunctor) (Mx: ArrayMatrixFunctor)= +struct + module Vector = Vec (Mpqf) + module Matrix = AffineEqualityMatrix (Vec) (Mx) + + let dim_add = Matrix.dim_add + + include SharedFunctions.VarManagementOps(AffineEqualityMatrix (Vec) (Mx)) + include ConvenienceOps(Mpqf) + + (** Get the constant from the vector if it is a constant *) + let to_constant_opt v = match Vector.findi ((<>:) Mpqf.zero) v with + | exception Not_found -> Some Mpqf.zero + | i when Vector.compare_length_with v (i + 1) = 0 -> Some (Vector.nth v i) + | _ -> None + + let get_coeff_vec (t: t) texp = + (*Parses a Texpr to obtain a coefficient + const (last entry) vector to repr. an affine relation. + Returns None if the expression is not affine*) + let open Apron.Texpr1 in + let exception NotLinear in + let zero_vec = Vector.zero_vec @@ Environment.size t.env + 1 in + let neg v = Vector.map_with Mpqf.neg v; v in + let is_const_vec v = Vector.compare_length_with (Vector.filteri (fun i x -> (*Inefficient*) + Vector.compare_length_with v (i + 1) > 0 && x <>: Mpqf.zero) v) 1 = 0 + in + let rec convert_texpr = function + (*If x is a constant, replace it with its const. val. immediately*) + | Cst x -> + let of_union = function + | Coeff.Interval _ -> failwith "Not a constant" + | Scalar Float x -> Mpqf.of_float x + | Scalar Mpqf x -> x + | Scalar Mpfrf x -> Mpfr.to_mpq x + in + Vector.set_nth zero_vec ((Vector.length zero_vec) - 1) (of_union x) + | Var x -> + let zero_vec_cp = Vector.copy zero_vec in + let entry_only v = Vector.set_nth_with v (Environment.dim_of_var t.env x) Mpqf.one; v in + begin match t.d with + | Some m -> + let row = Matrix.find_opt (fun r -> Vector.nth r (Environment.dim_of_var t.env x) =: Mpqf.one) m in + begin match row with + | Some v when is_const_vec v -> + Vector.set_nth_with zero_vec_cp ((Vector.length zero_vec) - 1) (Vector.nth v (Vector.length v - 1)); zero_vec_cp + | _ -> entry_only zero_vec_cp + end + | None -> entry_only zero_vec_cp end + | Unop (Neg, e, _, _) -> neg @@ convert_texpr e + | Unop (Cast, e, _, _) -> convert_texpr e (*Ignore since casts in apron are used for floating point nums and rounding in contrast to CIL casts*) + | Unop (Sqrt, e, _, _) -> raise NotLinear + | Binop (Add, e1, e2, _, _) -> + let v1 = convert_texpr e1 in + let v2 = convert_texpr e2 in + Vector.map2_with (+:) v1 v2; v1 + | Binop (Sub, e1, e2, _, _) -> + let v1 = convert_texpr e1 in + let v2 = convert_texpr e2 in + Vector.map2_with (+:) v1 (neg @@ v2); v1 + | Binop (Mul, e1, e2, _, _) -> + let v1 = convert_texpr e1 in + let v2 = convert_texpr e2 in + begin match to_constant_opt v1, to_constant_opt v2 with + | _, Some c -> Vector.apply_with_c_with ( *:) c v1; v1 + | Some c, _ -> Vector.apply_with_c_with ( *:) c v2; v2 + | _, _ -> raise NotLinear + end + | Binop _ -> raise NotLinear + in + try + Some (convert_texpr texp) + with NotLinear -> None + + let get_coeff_vec t texp = timing_wrap "coeff_vec" (get_coeff_vec t) texp +end + +(** As it is specifically used for the new affine equality domain, it can only provide bounds if the expression contains known constants only and in that case, min and max are the same. *) +module ExpressionBounds (Vc: ArrayVectorFunctor) (Mx: ArrayMatrixFunctor): (SharedFunctions.ConvBounds with type t = VarManagement(Vc) (Mx).t) = +struct + include VarManagement (Vc) (Mx) + + let bound_texpr t texpr = + let texpr = Texpr1.to_expr texpr in + match Option.bind (get_coeff_vec t texpr) to_constant_opt with + | Some c when Mpqf.get_den c = Z.one -> + let int_val = Mpqf.get_num c in + Some int_val, Some int_val + | _ -> None, None + + + let bound_texpr d texpr1 = + let res = bound_texpr d texpr1 in + (if M.tracing then + match res with + | Some min, Some max -> M.tracel "bounds" "min: %a max: %a" GobZ.pretty min GobZ.pretty max + | _ -> () + ); + res + + + let bound_texpr d texpr1 = timing_wrap "bounds calculation" (bound_texpr d) texpr1 +end + +module D(Vc: ArrayVectorFunctor) (Mx: ArrayMatrixFunctor) = +struct + include Printable.Std + include ConvenienceOps (Mpqf) + include VarManagement (Vc) (Mx) + + module Bounds = ExpressionBounds (Vc) (Mx) + module V = RelationDomain.V + module Arg = struct + let allow_global = true + end + module Convert = SharedFunctions.Convert (V) (Bounds) (Arg) (SharedFunctions.Tracked) + + + type var = V.t + + let show t = + let conv_to_ints row = + let row = Array.copy @@ Vector.to_array row in + let mpqf_of_z x = Mpqf.of_mpz @@ Z_mlgmpidl.mpzf_of_z x in + let lcm = mpqf_of_z @@ Array.fold_left (fun x y -> Z.lcm x (Mpqf.get_den y)) Z.one row in + Array.modify (( *:) lcm) row; + let int_arr = Array.map Mpqf.get_num row in + let div = Array.fold_left Z.gcd int_arr.(0) int_arr in + Array.modify (fun x -> Z.div x div) int_arr; + int_arr + in + let vec_to_constraint arr env = + let vars, _ = Environment.vars env in + let dim_to_str var = + let coeff = arr.(Environment.dim_of_var env var) in + if Z.equal coeff Z.zero then + "" + else + let coeff_str = + if Z.equal coeff Z.one then "+" + else if Z.equal coeff Z.minus_one then "-" + else if Z.lt coeff Z.minus_one then Z.to_string coeff + else Format.asprintf "+%s" (Z.to_string coeff) + in + coeff_str ^ Var.show var + in + let const_to_str vl = + if Z.equal vl Z.zero then + "" + else + let negated = Z.neg vl in + if Z.gt negated Z.zero then "+" ^ Z.to_string negated + else Z.to_string negated + in + let res = (String.concat "" @@ Array.to_list @@ Array.map dim_to_str vars) + ^ (const_to_str arr.(Array.length arr - 1)) ^ "=0" in + if Stdlib.String.starts_with res ~prefix:"+" then + Str.string_after res 1 + else + res + in + match t.d with + | None -> "Bottom Env" + | Some m when Matrix.is_empty m -> "⊤" + | Some m -> + let constraint_list = List.init (Matrix.num_rows m) (fun i -> vec_to_constraint (conv_to_ints @@ Matrix.get_row m i) t.env) in + "[|"^ (String.concat "; " constraint_list) ^"|]" + + let pretty () (x:t) = text (show x) + let printXml f x = BatPrintf.fprintf f "\n\n\nmatrix\n\n\n%s\n\nenv\n\n\n%a\n\n\n" (XmlUtil.escape (show x)) Environment.printXml x.env + let eval_interval ask = Bounds.bound_texpr + + let name () = "affeq" + + let to_yojson _ = failwith "ToDo Implement in future" + + + let is_bot t = equal t (bot ()) + + let bot_env = {d = None; env = Environment.make [||] [||]} + + let is_bot_env t = t.d = None + + let top () = {d = Some (Matrix.empty ()); env = Environment.make [||] [||]} + + let is_top t = Environment.equal empty_env t.env && GobOption.exists Matrix.is_empty t.d + + let is_top_env t = (not @@ Environment.equal empty_env t.env) && GobOption.exists Matrix.is_empty t.d + + let meet t1 t2 = + let sup_env = Environment.lce t1.env t2.env in + + let t1, t2 = change_d t1 sup_env ~add:true ~del:false, change_d t2 sup_env ~add:true ~del:false in + if is_bot t1 || is_bot t2 then + bot () + else + (* TODO: Why can I be sure that m1 && m2 are all Some here? + Answer: because is_bot checks if t1.d is None and we checked is_bot before. *) + let m1, m2 = Option.get t1.d, Option.get t2.d in + if is_top_env t1 then + {d = Some (dim_add (Environment.dimchange t2.env sup_env) m2); env = sup_env} + else if is_top_env t2 then + {d = Some (dim_add (Environment.dimchange t1.env sup_env) m1); env = sup_env} + else + let rref_matr = Matrix.rref_matrix_with (Matrix.copy m1) (Matrix.copy m2) in + if Option.is_none rref_matr then + bot () + else + {d = rref_matr; env = sup_env} + + + let meet t1 t2 = + let res = meet t1 t2 in + if M.tracing then M.tracel "meet" "meet a: %s b: %s -> %s " (show t1) (show t2) (show res) ; + res + + let meet t1 t2 = timing_wrap "meet" (meet t1) t2 + + let leq t1 t2 = + let env_comp = Environment.cmp t1.env t2.env in (* Apron's Environment.cmp has defined return values. *) + if env_comp = -2 || env_comp > 0 then + (* -2: environments are not compatible (a variable has different types in the 2 environements *) + (* -1: if env1 is a subset of env2, (OK) *) + (* 0: if equality, (OK) *) + (* +1: if env1 is a superset of env2, and +2 otherwise (the lce exists and is a strict superset of both) *) + false + else if is_bot t1 || is_top_env t2 then + true + else if is_bot t2 || is_top_env t1 then + false + else + let m1, m2 = Option.get t1.d, Option.get t2.d in + let m1' = if env_comp = 0 then m1 else dim_add (Environment.dimchange t1.env t2.env) m1 in + Matrix.is_covered_by m2 m1' + + let leq a b = timing_wrap "leq" (leq a) b + + let leq t1 t2 = + let res = leq t1 t2 in + if M.tracing then M.tracel "leq" "leq a: %s b: %s -> %b " (show t1) (show t2) res ; + res + + let join a b = + let rec lin_disjunc r s a b = + if s >= Matrix.num_cols a then a else + let case_two a r col_b = + let a_r = Matrix.get_row a r in + Matrix.map2i_with (fun i x y -> if i < r then + Vector.map2_with (fun u j -> u +: y *: j) x a_r; x) a col_b; + Matrix.remove_row a r + in + let case_three a b col_a col_b max = + let col_a, col_b = Vector.copy col_a, Vector.copy col_b in + let col_a, col_b = Vector.keep_vals col_a max, Vector.keep_vals col_b max in + if Vector.equal col_a col_b then + (a, b, max) + else + ( + Vector.rev_with col_a; + Vector.rev_with col_b; + let i = Vector.find2i (<>:) col_a col_b in + let (x, y) = Vector.nth col_a i, Vector.nth col_b i in + let r, diff = Vector.length col_a - (i + 1), x -: y in + let a_r, b_r = Matrix.get_row a r, Matrix.get_row b r in + Vector.map2_with (-:) col_a col_b; + Vector.rev_with col_a; + let multiply_by_t m t = + Matrix.map2i_with (fun i' x c -> if i' <= max then (let beta = c /: diff in + Vector.map2_with (fun u j -> u -: (beta *: j)) x t); x) m col_a; + m + in + Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) + ) + in + let col_a, col_b = Matrix.get_col a s, Matrix.get_col b s in + let nth_zero v i = match Vector.nth v i with + | exception Invalid_argument _ -> Mpqf.zero + | x -> x + in + let a_rs, b_rs = nth_zero col_a r, nth_zero col_b r in + if not (Z.equal (Mpqf.get_den a_rs) Z.one) || not (Z.equal (Mpqf.get_den b_rs) Z.one) then failwith "Matrix not in rref form" else + begin match Int.of_float @@ Mpqf.to_float @@ a_rs, Int.of_float @@ Mpqf.to_float @@ b_rs with (* TODO: is it safe to go through floats? *) + | 1, 1 -> lin_disjunc (r + 1) (s + 1) a b + | 1, 0 -> lin_disjunc r (s + 1) (case_two a r col_b) b + | 0, 1 -> lin_disjunc r (s + 1) a (case_two b r col_a) + | 0, 0 -> let new_a, new_b, new_r = case_three a b col_a col_b r in + lin_disjunc new_r (s + 1) new_a new_b + | _ -> failwith "Matrix not in rref form" end + in + if is_bot a then + b + else if is_bot b then + a + else + match Option.get a.d, Option.get b.d with + | x, y when is_top_env a || is_top_env b -> {d = Some (Matrix.empty ()); env = Environment.lce a.env b.env} + | x, y when (Environment.cmp a.env b.env <> 0) -> + let sup_env = Environment.lce a.env b.env in + let mod_x = dim_add (Environment.dimchange a.env sup_env) x in + let mod_y = dim_add (Environment.dimchange b.env sup_env) y in + {d = Some (lin_disjunc 0 0 (Matrix.copy mod_x) (Matrix.copy mod_y)); env = sup_env} + | x, y when Matrix.equal x y -> {d = Some x; env = a.env} + | x, y -> {d = Some(lin_disjunc 0 0 (Matrix.copy x) (Matrix.copy y)); env = a.env} + + let join a b = timing_wrap "join" (join a) b + + let join a b = + let res = join a b in + if M.tracing then M.tracel "join" "join a: %s b: %s -> %s " (show a) (show b) (show res) ; + res + + let widen a b = + if Environment.equal a.env b.env then + join a b + else + b + + let narrow a b = a + + let pretty_diff () (x, y) = + dprintf "%s: %a not leq %a" (name ()) pretty x pretty y + + let remove_rels_with_var x var env inplace = + let j0 = Environment.dim_of_var env var in + if inplace then + (Matrix.reduce_col_with x j0; x) + else + Matrix.reduce_col x j0 + + let remove_rels_with_var x var env inplace = timing_wrap "remove_rels_with_var" (remove_rels_with_var x var env) inplace + + let forget_vars t vars = + if is_bot t || is_top_env t || vars = [] then + t + else + let m = Option.get t.d in + let rem_from m = List.fold_left (fun m' x -> remove_rels_with_var m' x t.env true) m vars in + {d = Some (Matrix.remove_zero_rows @@ rem_from (Matrix.copy m)); env = t.env} + + let forget_vars t vars = + let res = forget_vars t vars in + if M.tracing then M.tracel "ops" "forget_vars %s -> %s" (show t) (show res); + res + + let forget_vars t vars = timing_wrap "forget_vars" (forget_vars t) vars + + let assign_texpr (t: VarManagement(Vc)(Mx).t) var texp = + let assign_invertible_rels x var b env = + let j0 = Environment.dim_of_var env var in + let a_j0 = Matrix.get_col x j0 in (*Corresponds to Axj0*) + let b0 = Vector.nth b j0 in + Vector.apply_with_c_with (/:) b0 a_j0; (*Corresponds to Axj0/Bj0*) + let recalc_entries m rd_a = Matrix.map2_with (fun x y -> Vector.map2i_with (fun j z d -> + if j = j0 then y + else if Vector.compare_length_with b (j + 1) > 0 then z -: y *: d + else z +: y *: d) x b; x) m rd_a + in + recalc_entries x a_j0; + if Matrix.normalize_with x then {d = Some x; env = env} else bot () + in + let assign_invertible_rels x var b env = timing_wrap "assign_invertible" (assign_invertible_rels x var b) env in + let assign_uninvertible_rel x var b env = + let b_length = Vector.length b in + Vector.mapi_with (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b; + Vector.set_nth_with b (Environment.dim_of_var env var) Mpqf.one; + let opt_m = Matrix.rref_vec_with x b in + if Option.is_none opt_m then bot () else + {d = opt_m; env = env} + in + (* let assign_uninvertible_rel x var b env = timing_wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) + let is_invertible v = Vector.nth v @@ Environment.dim_of_var t.env var <>: Mpqf.zero + in let affineEq_vec = get_coeff_vec t texp + in if is_bot t then t else let m = Option.get t.d in + match affineEq_vec with + | Some v when is_top_env t -> if is_invertible v then t else assign_uninvertible_rel m var v t.env + | Some v -> if is_invertible v then let t' = assign_invertible_rels (Matrix.copy m) var v t.env in {d = t'.d; env = t'.env} + else let new_m = Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env false + in assign_uninvertible_rel new_m var v t.env + | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env false); env = t.env} + + let assign_texpr t var texp = timing_wrap "assign_texpr" (assign_texpr t var) texp + + let assign_exp ask (t: VarManagement(Vc)(Mx).t) var exp (no_ov: bool Lazy.t) = + let t = if not @@ Environment.mem_var t.env var then add_vars t [var] else t in + (* TODO: Do we need to do a constant folding here? It happens for texpr1_of_cil_exp *) + match Convert.texpr1_expr_of_cil_exp ask t t.env exp no_ov with + | exp -> assign_texpr t var exp + | exception Convert.Unsupported_CilExp _ -> + if is_bot t then t else forget_vars t [var] + + let assign_exp ask t var exp no_ov = + let res = assign_exp ask t var exp no_ov in + if M.tracing then M.tracel "ops" "assign_exp t:\n %s \n var: %a \n exp: %a\n no_ov: %b -> \n %s" + (show t) Var.pretty var d_exp exp (Lazy.force no_ov) (show res); + res + + let assign_var (t: VarManagement(Vc)(Mx).t) v v' = + let t = add_vars t [v; v'] in + let texpr1 = Texpr1.of_expr (t.env) (Var v') in + assign_texpr t v (Apron.Texpr1.to_expr texpr1) + + let assign_var t v v' = + let res = assign_var t v v' in + if M.tracing then M.tracel "ops" "assign_var t:\n %s \n v: %a \n v': %a\n -> %s" (show t) Var.pretty v Var.pretty v' (show res); + res + + let assign_var_parallel t vv's = + let assigned_vars = List.map fst vv's in + let t = add_vars t assigned_vars in + let primed_vars = List.init (List.length assigned_vars) (fun i -> Var.of_string (Int.to_string i ^"'")) in (* TODO: we use primed vars in analysis, conflict? *) + let t_primed = add_vars t primed_vars in + let multi_t = List.fold_left2 (fun t' v_prime (_,v') -> assign_var t' v_prime v') t_primed primed_vars vv's in + match multi_t.d with + | Some m when not @@ is_top_env multi_t -> + let replace_col m x y = + let dim_x, dim_y = Environment.dim_of_var multi_t.env x, Environment.dim_of_var multi_t.env y in + let col_x = Matrix.get_col m dim_x in + Matrix.set_col_with m col_x dim_y + in + let m_cp = Matrix.copy m in + let switched_m = List.fold_left2 replace_col m_cp primed_vars assigned_vars in + let res = drop_vars {d = Some switched_m; env = multi_t.env} primed_vars ~del:true in + let x = Option.get res.d in + if Matrix.normalize_with x then + {d = Some x; env = res.env} + else + bot () + | _ -> t + + let assign_var_parallel t vv's = + let res = assign_var_parallel t vv's in + if M.tracing then M.tracel "ops" "assign_var parallel: %s -> %s " (show t) (show res); + res + + let assign_var_parallel t vv's = timing_wrap "var_parallel" (assign_var_parallel t) vv's + + let assign_var_parallel_with t vv's = + let t' = assign_var_parallel t vv's in + t.d <- t'.d; + t.env <- t'.env + + let assign_var_parallel_with t vv's = + if M.tracing then M.tracel "var_parallel" "assign_var parallel'"; + assign_var_parallel_with t vv's + + let assign_var_parallel' t vs1 vs2 = + let vv's = List.combine vs1 vs2 in + assign_var_parallel t vv's + + let assign_var_parallel' t vv's = + let res = assign_var_parallel' t vv's in + if M.tracing then M.tracel "ops" "assign_var parallel'"; + res + + let substitute_exp ask t var exp no_ov = + let t = if not @@ Environment.mem_var t.env var then add_vars t [var] else t in + let res = assign_exp ask t var exp no_ov in + forget_vars res [var] + + let substitute_exp ask t var exp no_ov = + let res = substitute_exp ask t var exp no_ov in + if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %a \n exp: %a \n -> \n %s" (show t) Var.pretty var d_exp exp (show res); + res + + let substitute_exp ask t var exp no_ov = timing_wrap "substitution" (substitute_exp ask t var exp) no_ov + + (** Assert a constraint expression. + + The overflow is completely handled by the flag "no_ov", + which is set in relationAnalysis.ml via the function no_overflow. + In case of a potential overflow, "no_ov" is set to false + and Convert.tcons1_of_cil_exp will raise the exception Unsupported_CilExp Overflow *) + + let meet_tcons ask t tcons expr = + let check_const cmp c = if cmp c Mpqf.zero then bot_env else t in + let meet_vec e = + (* Flip the sign of the const. val in coeff vec *) + let coeff = Vector.nth e (Vector.length e - 1) in + Vector.set_nth_with e (Vector.length e - 1) (Mpqf.neg coeff); + if is_bot t then + bot () + else + let opt_m = Matrix.rref_vec_with (Matrix.copy @@ Option.get t.d) e in + if Option.is_none opt_m then bot () else {d = opt_m; env = t.env} + + in + match get_coeff_vec t (Texpr1.to_expr @@ Tcons1.get_texpr1 tcons) with + | Some v -> + begin match to_constant_opt v, Tcons1.get_typ tcons with + | Some c, DISEQ -> check_const (=:) c + | Some c, SUP -> check_const (<=:) c + | Some c, EQ -> check_const (<>:) c + | Some c, SUPEQ -> check_const (<:) c + | None, DISEQ + | None, SUP -> + if equal (meet_vec v) t then + bot_env + else + t + | None, EQ -> + let res = meet_vec v in + if is_bot res then + bot_env + else + res + | _ -> t + end + | None -> t + + let meet_tcons t tcons expr = timing_wrap "meet_tcons" (meet_tcons t tcons) expr + + let unify a b = + meet a b + + let unify a b = + let res = unify a b in + if M.tracing then M.tracel "ops" "unify: %s %s -> %s" (show a) (show b) (show res); + res + + let assert_constraint ask d e negate no_ov = + if M.tracing then M.tracel "assert_constraint" "assert_constraint with expr: %a %b" d_exp e (Lazy.force no_ov); + match Convert.tcons1_of_cil_exp ask d d.env e negate no_ov with + | tcons1 -> meet_tcons ask d tcons1 e + | exception Convert.Unsupported_CilExp _ -> d + + let assert_constraint ask d e negate no_ov = timing_wrap "assert_constraint" (assert_constraint ask d e negate) no_ov + + let relift t = t + + let invariant t = + let invariant m = + let one_constraint i = + let row = Matrix.get_row m i in + let coeff_vars = List.map (fun x -> Coeff.s_of_mpqf @@ Vector.nth row (Environment.dim_of_var t.env x), x) (vars t) in + let cst = Coeff.s_of_mpqf @@ Vector.nth row (Vector.length row - 1) in + let e1 = Linexpr1.make t.env in + Linexpr1.set_list e1 coeff_vars (Some cst); + Lincons1.make e1 EQ + in + List.init (Matrix.num_rows m) one_constraint + in + BatOption.map_default invariant [] t.d + + let cil_exp_of_lincons1 = Convert.cil_exp_of_lincons1 + + let env t = t.env + + type marshal = t + + let marshal t = t + + let unmarshal t = t +end + +module D2(Vc: ArrayVectorFunctor) (Mx: ArrayMatrixFunctor): RelationDomain.RD with type var = Var.t = +struct + module D = D (Vc) (Mx) + module ConvArg = struct + let allow_global = false + end + include SharedFunctions.AssertionModule (D.V) (D) (ConvArg) + include D +end \ No newline at end of file diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.no-apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.no-apron.ml new file mode 100644 index 0000000000..5fed2c883c --- /dev/null +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.no-apron.ml @@ -0,0 +1,5 @@ +(* This domain is empty on purpose. It serves only as an alternative dependency + in cases where the actual domain can't be used because of a missing library. + It was added because we don't want to fully depend on Apron. *) + +let reset_lazy () = () diff --git a/src/dune b/src/dune index 10996e7ee8..5d3259347c 100644 --- a/src/dune +++ b/src/dune @@ -35,6 +35,10 @@ (apron -> affineEqualityDomain.apron.ml) (-> affineEqualityDomain.no-apron.ml) ) + (select affineEqualityDomainSideEffects.ml from + (apron -> affineEqualityDomainSideEffects.apron.ml) + (-> affineEqualityDomainSideEffects.no-apron.ml) + ) (select linearTwoVarEqualityAnalysis.ml from (apron -> linearTwoVarEqualityAnalysis.apron.ml) (-> linearTwoVarEqualityAnalysis.no-apron.ml) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index c2935ece35..ab7082c913 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -260,6 +260,7 @@ module ValueDomainQueries = ValueDomainQueries module RelationDomain = RelationDomain module ApronDomain = ApronDomain module AffineEqualityDomain = AffineEqualityDomain +module AffineEqualityDomainSideEffects = AffineEqualityDomainSideEffects module LinearTwoVarEqualityDomain = LinearTwoVarEqualityDomain (** {3 Concurrency} *) From b3fb4bcce749ba7f1794071fcea54a66445705b5 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 24 Jan 2025 19:28:09 +0100 Subject: [PATCH 203/240] Add rref_vec timing wraps and comments --- .../affineEquality/sparseImplementation/listMatrix.ml | 6 ++++++ .../affineEquality/sparseImplementation/sparseVector.ml | 1 + src/cdomains/apron/affineEqualityDomain.apron.ml | 5 ++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 3369b3e9b5..43a2fe1ab8 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -189,6 +189,9 @@ module ListMatrix: AbstractMatrix = | Some (pivot_col, _) -> (i, pivot_col, row) :: acc ) [] m + let get_pivot_positions m = + Timing.wrap "get_pivot_positions" get_pivot_positions m + (** [reduce_col m j] reduces the [j]-th column in [m] with the last row that has a non-zero element in this column. *) @@ -295,6 +298,9 @@ module ListMatrix: AbstractMatrix = let (before, after) = List.split_at row_idx reduced_m in before @ (v :: after) + let insert_v_according_to_piv m v piv_idx pivot_positions = + Timing.wrap "insert_v_according_to_piv" (insert_v_according_to_piv m v piv_idx) pivot_positions + (** [rref_vec m v] yields the same result as appending [v] to [m], then bringing [m] into rref and removing all zero rows. diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 86cdd7b980..8abab736c4 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -122,6 +122,7 @@ module SparseVector: AbstractVector = (** [insert_val_at v n num] returns [v] where the [num] is inserted into the [n]-th position, i.e. [v] at [n] = [num]. + All entries in [v] at position [n] and higher are shifted to the right, so the length of the vector is increased by one. @raise Invalid_argument if [n] is out of bounds. *) let insert_val_at v n num = diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 644dc7730d..e7c037021b 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -307,8 +307,7 @@ struct let col_a = Vector.map2_f_preserves_zero (-:) col_a col_b in let col_a = Vector.rev col_a in let multiply_by_t m t = - Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2_f_preserves_zero (fun u j -> u -: (beta *: j)) x t) else x) m col_a; - + Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2_f_preserves_zero (fun u j -> u -: (beta *: j)) x t) else x) m col_a in Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) ) @@ -320,7 +319,7 @@ struct in let a_rs, b_rs = nth_zero col_a r, nth_zero col_b r in if not (Z.equal (Mpqf.get_den a_rs) Z.one) || not (Z.equal (Mpqf.get_den b_rs) Z.one) then failwith "Matrix not in rref form" else - begin match Int.of_float @@ Mpqf.to_float @@ a_rs, Int.of_float @@ Mpqf.to_float @@ b_rs with (* TODO: is it safe to go through floats? *) + begin match Z.to_int @@ Mpqf.get_num a_rs, Z.to_int @@ Mpqf.get_num b_rs with | 1, 1 -> lin_disjunc (r + 1) (s + 1) a b | 1, 0 -> lin_disjunc r (s + 1) (case_two a r col_b) b | 0, 1 -> lin_disjunc r (s + 1) a (case_two b r col_a) From 6e5332bd43fe0e2a7b2aa043c7c6a65c5259a521 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Sat, 25 Jan 2025 15:59:12 +0100 Subject: [PATCH 204/240] Rename AbstractMatrix and AbstractVector and clean up unused functions in listMatrix --- .../arrayImplementation/arrayMatrix.ml | 5 +- .../arrayImplementation/arrayVector.ml | 4 +- src/cdomains/affineEquality/matrix.ml | 10 ++-- .../{abstractMatrix.ml => matrixFunctor.ml} | 2 +- .../sparseImplementation/listMatrix.ml | 50 +++++++------------ .../sparseImplementation/sparseVector.ml | 19 +------ src/cdomains/affineEquality/vector.ml | 4 +- .../{abstractVector.ml => vectorFunctor.ml} | 0 .../apron/affineEqualityDomain.apron.ml | 4 +- .../affineEqualityDomainSideEffects.apron.ml | 4 +- src/goblint_lib.ml | 4 +- 11 files changed, 36 insertions(+), 70 deletions(-) rename src/cdomains/affineEquality/{abstractMatrix.ml => matrixFunctor.ml} (97%) rename src/cdomains/affineEquality/{abstractVector.ml => vectorFunctor.ml} (100%) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 6883651bee..106d3a3758 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -1,7 +1,8 @@ -open AbstractVector +open VectorFunctor +open MatrixFunctor + open RatOps open ConvenienceOps -open AbstractMatrix open Batteries module Array = Batteries.Array diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index db84354d51..2964f342bc 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -1,4 +1,4 @@ -open AbstractVector +open VectorFunctor open RatOps open ConvenienceOps @@ -30,7 +30,7 @@ module ArrayVector: ArrayVectorFunctor = let compare_length_with v len = Int.compare (Array.length v) len - let remove_val v n = + let remove_nth v n = if n >= Array.length v then failwith "n outside of Array range" else Array.init (Array.length v - 1) (fun i -> if i < n then Array.get v i else Array.get v (i + 1)) (* TODO: remove_at? *) diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index f356872480..ec7c0cdd4c 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -33,18 +33,12 @@ sig val add_empty_columns: t -> int array -> t - val get_col: t -> int -> vec - val set_col: t -> vec -> int -> t - val del_col: t -> int -> t - val del_cols: t -> int array -> t val find_opt: (vec -> bool) -> t -> vec option - val append_matrices: t -> t -> t - val reduce_col: t -> int -> t val normalize: t -> t Option.t (* Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution *) @@ -56,7 +50,9 @@ end module type ArrayMatrix = sig include Matrix + val get_col: t -> int -> vec val set_col_with: t -> vec -> int -> t + val del_col: t -> int -> t val reduce_col_with: t -> int -> unit val normalize_with: t -> bool @@ -65,6 +61,8 @@ sig val rref_matrix_with: t -> t -> t Option.t val map2_with: (vec -> num -> vec) -> t -> vec -> unit val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit + + val append_matrices: t -> t -> t end module type SparseMatrix = diff --git a/src/cdomains/affineEquality/abstractMatrix.ml b/src/cdomains/affineEquality/matrixFunctor.ml similarity index 97% rename from src/cdomains/affineEquality/abstractMatrix.ml rename to src/cdomains/affineEquality/matrixFunctor.ml index 62e7a3a127..ef65a46379 100644 --- a/src/cdomains/affineEquality/abstractMatrix.ml +++ b/src/cdomains/affineEquality/matrixFunctor.ml @@ -1,5 +1,5 @@ open RatOps -open AbstractVector +open VectorFunctor open Matrix (** Some functions inside have the suffix _with, which means that the function has side effects. *) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 6934912460..5d3d2a365f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -1,11 +1,9 @@ -open AbstractMatrix -open AbstractVector +open MatrixFunctor +open VectorFunctor open RatOps open ConvenienceOps open BatList -open BatOption - module List = BatList (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. @@ -25,10 +23,10 @@ module ListMatrix: SparseMatrixFunctor = let copy m = m - let equal m1 m2 = Timing.wrap "equal" (equal m1) m2 + let equal m1 m2 = timing_wrap "equal" (equal m1) m2 let copy m = - Timing.wrap "copy" (copy) m + timing_wrap "copy" (copy) m let empty () = [] @@ -76,7 +74,7 @@ module ListMatrix: SparseMatrixFunctor = in map2_helper [] 0 m vector_entries - let map2 f m v = Timing.wrap "Matrix.map2" (map2 f m) v + let map2 f m v = timing_wrap "Matrix.map2" (map2 f m) v let map2i f m v = let vector_length = V.length v in @@ -98,7 +96,7 @@ module ListMatrix: SparseMatrixFunctor = in map2_helper [] 0 m vector_entries - let map2i f m v = Timing.wrap "Matrix.map2i" (map2i f m) v + let map2i f m v = timing_wrap "Matrix.map2i" (map2i f m) v (** [add_empty_columns m cols] extends the matrix [m] as specified in [cols]. @@ -119,16 +117,10 @@ module ListMatrix: SparseMatrixFunctor = List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m let add_empty_columns m cols = - Timing.wrap "add_empty_cols" (add_empty_columns m) cols - - let get_col m n = - V.of_sparse_list (num_rows m) @@ List.filteri_map (fun i row -> let value = V.nth row n in if value <>: A.zero then Some (i, value) else None) m - - let get_col m n = - Timing.wrap "get_col" (get_col m) n + timing_wrap "add_empty_cols" (add_empty_columns m) cols (** - [get_col_upper_triangular m n] yields the same result as [get_col m n], but [m] must be in upper triangular form. + [get_col_upper_triangular m n] returns the [n]th column of [m]. [m] must be in upper triangular form. @param m A matrix in upper triangular form. *) let get_col_upper_triangular m n = @@ -142,17 +134,12 @@ module ListMatrix: SparseMatrixFunctor = let value = V.nth row n in if value <>: A.zero then helper ((i, value) :: acc) xs (i + 1) else helper acc xs (i + 1) in V.of_sparse_list (num_rows m) (List.rev @@ helper [] m 0) - let get_col_upper_triangular m n = Timing.wrap "get_col" (get_col_upper_triangular m) n + let get_col_upper_triangular m n = timing_wrap "get_col" (get_col_upper_triangular m) n let set_col m new_col n = map2 (fun row value -> V.set_nth row n value) m new_col - let set_col m new_col n = Timing.wrap "set_col" (set_col m) new_col n - - let del_col m j = - if num_cols m = 1 then empty () - else - List.map (fun row -> V.remove_nth row j) m + let set_col m new_col n = timing_wrap "set_col" (set_col m) new_col n (** [del_cols m cols] removes columns from [m] as specified by [c]. @@ -165,13 +152,10 @@ module ListMatrix: SparseMatrixFunctor = else List.map (fun row -> V.remove_at_indices row sorted_cols) m - let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols + let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols let find_opt = List.find_opt - let append_matrices m1 m2 = - m1 @ m2 - let div_row row value = V.map_f_preserves_zero (fun a -> a /: value) row @@ -223,7 +207,7 @@ module ListMatrix: SparseMatrixFunctor = let cut_front_matrix m row_idx col_idx = List.filteri_map (fun i row -> if i < row_idx then None else Some (V.starting_from_nth row col_idx)) m in - let cut_front_matrix m row_idx col_idx = Timing.wrap "cut_front_matrix" (cut_front_matrix m row_idx) col_idx in + let cut_front_matrix m row_idx col_idx = timing_wrap "cut_front_matrix" (cut_front_matrix m row_idx) col_idx in (* Function for finding first pivot in an extracted part of the matrix (row_idx and col_idx indicate which part of the original matrix) *) (* The last column represents the constant in the affeq *) let find_first_pivot m row_idx col_idx = @@ -239,7 +223,7 @@ module ListMatrix: SparseMatrixFunctor = in if piv_col = (max_piv_col_idx + 1) then None else Some (row_idx + piv_row, col_idx + piv_col, piv_val) in - let find_first_pivot m row_idx col_idx = Timing.wrap "find_first_pivot" (find_first_pivot m row_idx) col_idx in + let find_first_pivot m row_idx col_idx = timing_wrap "find_first_pivot" (find_first_pivot m row_idx) col_idx in let affeq_rows_are_valid m = (* Check if the semantics of an rref-affeq matrix are correct *) let col_count = num_cols m in let row_is_valid row = @@ -268,7 +252,7 @@ module ListMatrix: SparseMatrixFunctor = if affeq_rows_are_valid m' then Some m' else None - let normalize m = Timing.wrap "normalize" normalize m + let normalize m = timing_wrap "normalize" normalize m (** [reduce_col_with_vec m j v] sets the [j]-th column of [m] to zero by subtracting multiples of [v] from each row. *) @@ -325,7 +309,7 @@ module ListMatrix: SparseMatrixFunctor = let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v_after_elim in Some (insert_v_according_to_piv m normalized_v idx pivot_positions) - let rref_vec m v = Timing.wrap "rref_vec" (rref_vec m) v + let rref_vec m v = timing_wrap "rref_vec" (rref_vec m) v (** [rref_matrix m m'] yields the same result as appending [m'] to [m], then bringing the resulting matrix into rref and removing all zero rows. @@ -338,7 +322,7 @@ module ListMatrix: SparseMatrixFunctor = fst @@ List.fold_while (fun acc _ -> Option.is_some acc) (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m - let rref_matrix m1 m2 = Timing.wrap "rref_matrix" (rref_matrix m1) m2 + let rref_matrix m1 m2 = timing_wrap "rref_matrix" (rref_matrix m1) m2 (** [is_coverd_by m m'] returns [true] iff every vector in [m] is a linear combination of vectors in [m']. @@ -375,6 +359,6 @@ module ListMatrix: SparseMatrixFunctor = if linearly_indep then false else is_covered_by_helper vs1 m2 in is_covered_by_helper m1 m2 - let is_covered_by m1 m2 = Timing.wrap "is_covered_by" (is_covered_by m1) m2 + let is_covered_by m1 m2 = timing_wrap "is_covered_by" (is_covered_by m1) m2 end diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 65a1c370b5..0be24b85de 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -1,4 +1,4 @@ -open AbstractVector +open VectorFunctor open RatOps open ConvenienceOps @@ -225,23 +225,6 @@ module SparseVector: SparseVectorFunctor = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else aux v.entries v'.entries - (** - [findi_val_opt f v] returns the first entry [e] and its index where [f e = true], if such an entry exists. - @return [(idx, e) option] - *) - let findi_val_opt f v = - let rec find_zero_or_val vec last_idx = - let f0 = f A.zero in - match vec with - | [] -> if f0 && v.len <> last_idx + 1 then Some (last_idx + 1, A.zero) else None - | (idx, value) :: xs -> - if f0 && idx <> last_idx + 1 then Some (last_idx + 1, A.zero) - else if f value then Some (idx, value) - else find_zero_or_val xs idx - in find_zero_or_val v.entries (-1) - - let findi_val_opt f v = Timing.wrap "findi_val_opt" (findi_val_opt f) v - (** [find_first_non_zero v] returns the first entry [e] and its index where [e <>: 0], if such an entry exists. @return [(idx, e) option] diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index c106051a2c..b585b9d85c 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -34,6 +34,8 @@ sig val insert_val_at: t -> int -> num -> t + val remove_nth: t -> int -> t + val keep_vals: t -> int -> t val findi: (num -> bool) -> t -> int @@ -54,8 +56,6 @@ sig val insert_zero_at_indices: t -> (int * int) list -> int -> t - val remove_nth: t -> int -> t - val remove_at_indices: t -> int list -> t (* Returns the part of the vector starting from index n*) val starting_from_nth : t -> int -> t diff --git a/src/cdomains/affineEquality/abstractVector.ml b/src/cdomains/affineEquality/vectorFunctor.ml similarity index 100% rename from src/cdomains/affineEquality/abstractVector.ml rename to src/cdomains/affineEquality/vectorFunctor.ml diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 9f8cbba819..5f1c9fcffc 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -13,8 +13,8 @@ module M = Messages open GobApron open ConvenienceOps -open AbstractVector -open AbstractMatrix +open VectorFunctor +open MatrixFunctor open Batteries module Array = Batteries.Array diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml index f5eb840998..1864631291 100644 --- a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -12,8 +12,8 @@ module M = Messages open GobApron open ConvenienceOps -open AbstractVector -open AbstractMatrix +open VectorFunctor +open MatrixFunctor open Batteries module Array = BatArray diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index ab7082c913..8e7a63a07f 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -437,8 +437,8 @@ module WideningThresholds = WideningThresholds (* There might be a more elegant solution. *) module Vector = Vector module Matrix = Matrix -module AbstractVector = AbstractVector -module AbstractMatrix = AbstractMatrix +module VectorFunctor = VectorFunctor +module MatrixFunctor = MatrixFunctor module ArrayVector = ArrayVector module ArrayMatrix = ArrayMatrix module SparseVector = SparseVector From 5f9ae052273cb18490331ada5f6e739d2a9f2713 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 25 Jan 2025 18:29:14 +0100 Subject: [PATCH 205/240] Remove sorting for add_empty_columns and del_cols; Remove some List.length --- .../sparseImplementation/listMatrix.ml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 43a2fe1ab8..c36da124df 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -105,8 +105,7 @@ module ListMatrix: AbstractMatrix = @param cols An apron dimchange array as defined here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html . *) let add_empty_columns m cols = - let cols = Array.to_list cols in (* cols should adhere to apron specification as described here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html*) - let sorted_cols = List.sort Stdlib.compare cols in + let cols_list = Array.to_list cols in (* cols should adhere to apron specification as described here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html*) (* This function creates a list of tuples, each specifying an index and how many zeros are to be inserted at that index *) let rec count_sorted_occ acc cols last count = match cols with @@ -115,12 +114,15 @@ module ListMatrix: AbstractMatrix = | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in count_sorted_occ acc xs x 1 in - let occ_cols = List.rev @@ count_sorted_occ [] sorted_cols 0 0 in - List.map (fun row -> V.insert_zero_at_indices row occ_cols (List.length cols)) m + let occ_cols = List.rev @@ count_sorted_occ [] cols_list 0 0 in + List.map (fun row -> V.insert_zero_at_indices row occ_cols (Array.length cols)) m let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols + (** + [get_col m n] returns a vector representing the [n]-th column of [m]. + *) let get_col m n = V.of_sparse_list (num_rows m) @@ List.filteri_map (fun i row -> let value = V.nth row n in if value <>: A.zero then Some (i, value) else None) m @@ -159,11 +161,10 @@ module ListMatrix: AbstractMatrix = @param c An apron dimchange array as defined here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html . *) let del_cols m cols = - let cols = Array.to_list cols in - let sorted_cols = List.sort_uniq Stdlib.compare cols in (* Apron Docs: Repetitions are meaningless (and are not correct specification) *) - if (List.length sorted_cols) = num_cols m then empty() + if (Array.length cols) = num_cols m then empty() else - List.map (fun row -> V.remove_at_indices row sorted_cols) m + let cols_list = Array.to_list cols in + List.map (fun row -> V.remove_at_indices row cols_list) m let del_cols m cols = Timing.wrap "del_cols" (del_cols m) cols From 1bca083d972855cf28891fab97b9a24868db282d Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 28 Jan 2025 17:02:57 +0100 Subject: [PATCH 206/240] Change add_empty_columns to use List.group and List.map --- .../sparseImplementation/listMatrix.ml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index c36da124df..ae6f6eb0a5 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -106,22 +106,16 @@ module ListMatrix: AbstractMatrix = *) let add_empty_columns m cols = let cols_list = Array.to_list cols in (* cols should adhere to apron specification as described here: https://antoinemine.github.io/Apron/doc/api/ocaml/Dim.html*) - (* This function creates a list of tuples, each specifying an index and how many zeros are to be inserted at that index *) - let rec count_sorted_occ acc cols last count = - match cols with - | [] -> if count > 0 then (last, count) :: acc else acc - | x :: xs when x = last -> count_sorted_occ acc xs x (count + 1) - | x :: xs -> let acc = if count > 0 then (last, count) :: acc else acc in - count_sorted_occ acc xs x 1 - in - let occ_cols = List.rev @@ count_sorted_occ [] cols_list 0 0 in + (* This creates a list of tuples, each specifying an index and how many zeros are to be inserted at that index. This is then used for each row *) + let grouped_indices = List.group Int.compare cols_list in + let occ_cols = List.map (fun group -> ((List.hd group, List.length group))) grouped_indices in List.map (fun row -> V.insert_zero_at_indices row occ_cols (Array.length cols)) m let add_empty_columns m cols = Timing.wrap "add_empty_cols" (add_empty_columns m) cols (** - [get_col m n] returns a vector representing the [n]-th column of [m]. + [get_col m n] returns a vector representing the [n]-th column of [m]. *) let get_col m n = V.of_sparse_list (num_rows m) @@ List.filteri_map (fun i row -> let value = V.nth row n in if value <>: A.zero then Some (i, value) else None) m From 0a135464bfeb7ad05c9bc3d746c23c3ab5c9c461 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 28 Jan 2025 17:26:52 +0100 Subject: [PATCH 207/240] Clean up unused sparseVector functions --- src/cdomains/affineEquality/matrix.ml | 12 +++- src/cdomains/affineEquality/matrixFunctor.ml | 5 -- .../sparseImplementation/listMatrix.ml | 32 ---------- .../sparseImplementation/sparseVector.ml | 58 +------------------ src/cdomains/affineEquality/vector.ml | 27 ++++++--- 5 files changed, 29 insertions(+), 105 deletions(-) diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index ec7c0cdd4c..ed264b063a 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -9,7 +9,7 @@ sig val copy: t -> t - val empty: unit -> t (* TODO: needs unit? *) + val empty: unit -> t val is_empty: t -> bool @@ -44,22 +44,27 @@ sig val normalize: t -> t Option.t (* Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution *) val is_covered_by: t -> t -> bool - end module type ArrayMatrix = sig include Matrix val get_col: t -> int -> vec + val set_col_with: t -> vec -> int -> t + val del_col: t -> int -> t + val reduce_col_with: t -> int -> unit + val normalize_with: t -> bool val rref_vec_with: t -> vec -> t Option.t val rref_matrix_with: t -> t -> t Option.t + val map2_with: (vec -> num -> vec) -> t -> vec -> unit + val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit val append_matrices: t -> t -> t @@ -69,7 +74,10 @@ module type SparseMatrix = sig include Matrix val get_col_upper_triangular: t -> int -> vec + val swap_rows: t -> int -> int -> t + val rref_vec: t -> vec -> t Option.t + val rref_matrix: t -> t -> t Option.t end \ No newline at end of file diff --git a/src/cdomains/affineEquality/matrixFunctor.ml b/src/cdomains/affineEquality/matrixFunctor.ml index ef65a46379..958dd77282 100644 --- a/src/cdomains/affineEquality/matrixFunctor.ml +++ b/src/cdomains/affineEquality/matrixFunctor.ml @@ -14,8 +14,3 @@ module type SparseMatrixFunctor = sig include SparseMatrix with type vec := V(A).t and type num := A.t end - -(* let timing_wrap = Timing.wrap *) -(* Disable timing of VectorMatrix and AffineEqualityDomain. - This is cleaner than a timing functor because the timed functions also call each other. *) -let timing_wrap _ f x = f x diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 5d3d2a365f..5a43f55436 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -58,44 +58,12 @@ module ListMatrix: SparseMatrixFunctor = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m - let map2 f m v = - let vector_length = V.length v in - let vector_entries = V.to_sparse_list v in - let rec map2_helper acc index m v = - match m, v with - | [], _ -> List.rev acc - | row :: rs, [] when index >= vector_length -> map2_helper (row :: acc) (index + 1) rs [] - | row :: rs, [] -> map2_helper ((f row A.zero):: acc) (index + 1) rs [] - | row :: rs, (i, value) :: vs -> - if i = index then - map2_helper ((f row value):: acc) (index + 1) rs vs - else - map2_helper ((f row A.zero) :: acc) (index + 1) rs v - in - map2_helper [] 0 m vector_entries - let map2 f m v = timing_wrap "Matrix.map2" (map2 f m) v let map2i f m v = let vector_length = V.length v in List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row ) m - let map2i f m v = - let vector_length = V.length v in - let vector_entries = V.to_sparse_list v in - let rec map2_helper acc index m v = - match m, v with - | [], _ -> List.rev acc - | row :: rs, [] when index >= vector_length -> map2_helper (row :: acc) (index + 1) rs [] - | row :: rs, [] -> map2_helper ((f index row A.zero):: acc) (index + 1) rs [] - | row :: rs, (i, value) :: vs -> - if i = index then - map2_helper ((f index row value):: acc) (index + 1) rs vs - else - map2_helper ((f index row A.zero) :: acc) (index + 1) rs v - in - map2_helper [] 0 m vector_entries - let map2i f m v = timing_wrap "Matrix.map2i" (map2i f m) v (** diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 0be24b85de..c38a75c326 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -87,7 +87,7 @@ module SparseVector: SparseVectorFunctor = match v.entries with | [] -> false | (idx, _) :: (const_idx , _) :: [] when const_idx = (v.len - 1) -> true - | (idx, _)::[] when idx <> v.len -1 -> true + | (idx, _)::[] when idx <> v.len -1 -> true | _ -> false (** @@ -190,21 +190,6 @@ module SparseVector: SparseVectorFunctor = let entries = List.filter_map (fun (idx, value) -> if idx < n then None else Some (idx - n, value)) v.entries in {entries; len = v.len - n} - let findi f v = - (* How this works: - Case 1: - A.zero is also to be found. The List.findi is used to have an iteration index i. - If at one point i < idx, it means that a Zero element was skipped because of the sparse vector representation. In that case i is the index of the first Zero, so returning true indicates that it is found. - f value still has to be checked in case other elements than Zero are to be found. - List.findi returns the index at which is was found in the tuple's first element. - Case 2: - A.zero is not to be found. We just iterate over the sparse list then and the index is returned if an element is found. - *) - if f A.zero then - fst @@ List.findi (fun i (idx, value) -> i < idx || f value) v.entries (* Here fst is the iteration variable i, not the tuple idx *) - else - fst @@ List.find (fun (idx, value) -> f value) v.entries (* Here fst is the idx contained in the found tuple *) - (** [find2i_f_false_at_zero f v v'] returns the {b index} of the first pair of entries [e, e'] from [v, v'] where [f e e' = true ]. @@ -235,14 +220,6 @@ module SparseVector: SparseVectorFunctor = let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v - let exists f v = - let c = v.len in - let rec exists_aux at f v = - match v with - | [] -> if at = 0 then false else f A.zero - | (xi, xv) :: xs -> if f xv then true else exists_aux (at - 1) f xs - in (exists_aux c f v.entries) - (** [map_f_preserves_zero f v] returns the mapping of [v] specified by [f]. @@ -323,36 +300,6 @@ module SparseVector: SparseVectorFunctor = in {v with entries = List.rev (aux [] v.entries v'.entries 0)} - (** - [fold_left_f_preserves_zero f acc v] returns the fold of [v] on [acc] specified by [f]. - - Note that [f] {b must} be such that [f acc 0 = acc]! - *) - let fold_left_f_preserves_zero f acc v = - List.fold_left (fun acc (_, value) -> f acc value) acc v.entries - - (** - [fold_left2_f_preserves_zero f acc v v'] returns the fold of [v] and [v'] specified by [f]. - - Note that [f] {b must} be such that [f acc 0 0 = acc]! - - @raise Invalid_argument if [v] and [v'] have unequal lengths - *) - let fold_left2_f_preserves_zero f acc v v' = - let rec aux acc v1 v2 = - match v1, v2 with - | [], [] -> acc - | [], (yidx, yval) :: ys -> aux (f acc A.zero yval) [] ys - | (xidx, xval) :: xs, [] -> aux (f acc xval A.zero) xs [] - | (xidx, xval) :: xs, (yidx, yval) :: ys -> - match xidx - yidx with - | d when d < 0 -> aux (f acc xval A.zero) xs v2 - | d when d > 0 -> aux (f acc A.zero yval) v1 ys - | _ -> aux (f acc xval yval) xs ys - in - if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else - (aux acc v.entries v'.entries) - (** [apply_with_c_f_preserves_zero f c v] returns the mapping of [v] and [c] specified by [f]. @@ -366,7 +313,4 @@ module SparseVector: SparseVectorFunctor = let entries = List.rev_map (fun (idx, value) -> (v.len - 1 - idx, value)) v.entries in {entries; len = v.len} - let append v v' = - let entries = v.entries @ List.map (fun (idx, value) -> (idx + v.len), value) v'.entries in - {entries; len = v.len + v'.len} end diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index b585b9d85c..f37f8ba83d 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -38,15 +38,9 @@ sig val keep_vals: t -> int -> t - val findi: (num -> bool) -> t -> int - - val exists: (num -> bool) -> t -> bool - val map2i: (int -> num -> num -> num) -> t -> t -> t val rev: t -> t - - val append: t -> t -> t end module type SparseVector = @@ -57,18 +51,19 @@ sig val insert_zero_at_indices: t -> (int * int) list -> int -> t val remove_at_indices: t -> int list -> t + (* Returns the part of the vector starting from index n*) val starting_from_nth : t -> int -> t + val find_first_non_zero : t -> (int * num) option + val map_f_preserves_zero: (num -> num) -> t -> t val mapi_f_preserves_zero: (int -> num -> num) -> t -> t val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t - val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int - val fold_left_f_preserves_zero: ('acc -> num -> 'acc) -> 'acc -> t -> 'acc - val fold_left2_f_preserves_zero: ('acc -> num -> num -> 'acc) -> 'acc -> t -> t -> 'acc + val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t end @@ -77,12 +72,26 @@ module type ArrayVector = sig include Vector val mapi_with: (int -> num -> num) -> t -> unit + val map_with: (num -> num) -> t -> unit + val map2_with: (num -> num -> num) -> t -> t -> unit + val map2i_with: (int -> num -> num -> num) -> t -> t -> unit + val filteri: (int -> num -> bool) -> t -> t + + val findi: (num -> bool) -> t -> int + val find2i: (num -> num -> bool) -> t -> t -> int + + val exists: (num -> bool) -> t -> bool + val set_nth_with: t -> int -> num -> unit + val apply_with_c_with: (num -> num -> num) -> num -> t -> unit + val rev_with: t -> unit + + val append: t -> t -> t end \ No newline at end of file From 9c949012e2eb1e099e2d7e93ced6a5bc6a56f81f Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:32:10 +0100 Subject: [PATCH 208/240] Update sparseVector to_list Co-authored-by: Michael Schwarz --- .../affineEquality/sparseImplementation/sparseVector.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 8abab736c4..872b5df6c9 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -41,10 +41,10 @@ module SparseVector: AbstractVector = (** [to_list v] returns a non-sparse list representing the vector v *) let to_list v = - let rec extend_zero_aux i v' acc = - match v' with - | (index, value) :: xs -> if index = i then extend_zero_aux (i + 1) xs (value :: acc) else extend_zero_aux (i + 1) v' (A.zero :: acc) - | [] -> if i < v.len then extend_zero_aux (i + 1) v' (A.zero :: acc) else List.rev acc + let rec extend_zero_aux i acc = function + | (index, value) :: xs when index = i -> extend_zero_aux (i + 1) (value :: acc) xs + | ((_:: _) as v) -> extend_zero_aux (i + 1) (A.zero :: acc) v + | [] -> if i < v.len then extend_zero_aux (i + 1) (A.zero :: acc) [] else List.rev acc in extend_zero_aux 0 v.entries [] From 69a46551d6bd3122f21130befdc6fcbe40c690d2 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 28 Jan 2025 17:44:41 +0100 Subject: [PATCH 209/240] Update sparseVector nth --- .../sparseImplementation/sparseVector.ml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 872b5df6c9..2023c5526f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -42,11 +42,11 @@ module SparseVector: AbstractVector = (** [to_list v] returns a non-sparse list representing the vector v *) let to_list v = let rec extend_zero_aux i acc = function - | (index, value) :: xs when index = i -> extend_zero_aux (i + 1) (value :: acc) xs - | ((_:: _) as v) -> extend_zero_aux (i + 1) (A.zero :: acc) v - | [] -> if i < v.len then extend_zero_aux (i + 1) (A.zero :: acc) [] else List.rev acc + | (index, value) :: xs when index = i -> extend_zero_aux (i + 1) (value :: acc) xs + | ((_:: _) as v) -> extend_zero_aux (i + 1) (A.zero :: acc) v + | [] -> if i < v.len then extend_zero_aux (i + 1) (A.zero :: acc) [] else List.rev acc in - extend_zero_aux 0 v.entries [] + extend_zero_aux 0 [] v.entries let to_array v = let vec = Array.make v.len A.zero in @@ -97,12 +97,9 @@ module SparseVector: AbstractVector = let nth v n = (* Note: This exception HAS TO BE THROWN! It is expected by the domain *) if n >= v.len then raise (Invalid_argument "Index out of bounds") else - let rec nth v = match v with - | [] -> A.zero - | (idx, value) :: xs when idx > n -> A.zero - | (idx, value) :: xs when idx = n -> value - | (idx, value) :: xs -> nth xs - in nth v.entries + match List.find_opt (fun (idx, _) -> idx >= n) v.entries with + | Some (idx, value) when idx = n -> value + | _ -> A.zero (** [set_nth v n num] returns [v] where the [n]-th entry has been set to [num]. From c6b10061ff6067fdeaef9bde74bd6fffcc508fd6 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 28 Jan 2025 17:46:36 +0100 Subject: [PATCH 210/240] Remove insert_val_at from ListMatrix since it is uncalled --- .../sparseImplementation/sparseVector.ml | 13 ----- src/cdomains/affineEquality/vector.ml | 54 +++++++++---------- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index c38a75c326..1fb1f79733 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -120,19 +120,6 @@ module SparseVector: SparseVectorFunctor = in {v with entries = set_nth_helper v.entries []} - (** - [insert_val_at v n num] returns [v] where the [num] is inserted into the [n]-th position, i.e. [v] at [n] = [num]. - @raise Invalid_argument if [n] is out of bounds. - *) - let insert_val_at v n num = - if n > v.len then raise (Invalid_argument "Index out of bounds") - else - let entries = List.rev @@ List.fold_left (fun acc (idx, value) -> - if idx < n then (idx, value) :: acc - else (if num <>: A.zero then (idx + 1, value) :: (n, num) :: acc else (idx + 1, value) :: acc) - ) [] v.entries in - {entries; len = v.len + 1} - (** [insert_zero_at_indices v indices num_zeros] inserts [num_zeros] into [v]. @param indices A {b sorted} list of tuples where [fst] gives the index of the insert and [snd] the number of zeros that will be inserted. diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index f37f8ba83d..bc08de7b62 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -32,8 +32,6 @@ sig val set_nth: t -> int -> num -> t - val insert_val_at: t -> int -> num -> t - val remove_nth: t -> int -> t val keep_vals: t -> int -> t @@ -43,31 +41,6 @@ sig val rev: t -> t end -module type SparseVector = -sig - include Vector - val is_zero_vec: t -> bool - - val insert_zero_at_indices: t -> (int * int) list -> int -> t - - val remove_at_indices: t -> int list -> t - - (* Returns the part of the vector starting from index n*) - val starting_from_nth : t -> int -> t - - val find_first_non_zero : t -> (int * num) option - - val map_f_preserves_zero: (num -> num) -> t -> t - - val mapi_f_preserves_zero: (int -> num -> num) -> t -> t - - val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t - - val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int - - val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t -end - module type ArrayVector = sig include Vector @@ -89,9 +62,36 @@ sig val set_nth_with: t -> int -> num -> unit + val insert_val_at: t -> int -> num -> t + val apply_with_c_with: (num -> num -> num) -> num -> t -> unit val rev_with: t -> unit val append: t -> t -> t +end + +module type SparseVector = +sig + include Vector + val is_zero_vec: t -> bool + + val insert_zero_at_indices: t -> (int * int) list -> int -> t + + val remove_at_indices: t -> int list -> t + + (* Returns the part of the vector starting from index n*) + val starting_from_nth : t -> int -> t + + val find_first_non_zero : t -> (int * num) option + + val map_f_preserves_zero: (num -> num) -> t -> t + + val mapi_f_preserves_zero: (int -> num -> num) -> t -> t + + val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t + + val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int + + val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t end \ No newline at end of file From 6d4c154c84f316185d4e56ccb5f6873a114c44a4 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 28 Jan 2025 17:51:13 +0100 Subject: [PATCH 211/240] Correct comments in ArrayMatrix --- src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 106d3a3758..c5d03e263e 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -147,6 +147,7 @@ module ArrayMatrix: ArrayMatrixFunctor = let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols + (* This does NOT have the same semantics (minus side effects) as map2i_with. While map2i_with can deal with m and v having different lenghts, map2i will raise Invalid_argument in that case*) let map2i f m v = let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in let range_array = Array.init (V.length v) Fun.id in @@ -243,7 +244,7 @@ module ArrayMatrix: ArrayMatrixFunctor = let rref_vec_with m v = - (*This function yields the same result as appending vector v to m and normalizing it afterwards would. However, it is usually faster than performing those ops manually.*) + (*This function yields the same result as appending vector v to m, normalizing it and removing zero rows would. However, it is usually faster than performing those ops manually.*) (*m must be in rref form and contain the same num of cols as v*) (*If m is empty then v is simply normalized and returned*) let v = V.to_array v in From 16071d97adab554e065fd0211d276f54a4004e64 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 28 Jan 2025 18:30:50 +0100 Subject: [PATCH 212/240] Change Timing.wrap to timing_wrap --- .../sparseImplementation/listMatrix.ml | 4 +-- .../sparseImplementation/sparseVector.ml | 8 ++--- .../apron/affineEqualityDomain.apron.ml | 34 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index c62a4ae926..2e3440ac52 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -134,7 +134,7 @@ module ListMatrix: SparseMatrixFunctor = ) [] m let get_pivot_positions m = - Timing.wrap "get_pivot_positions" get_pivot_positions m + timing_wrap "get_pivot_positions" get_pivot_positions m (** [reduce_col m j] reduces the [j]-th column in [m] with the last row that has a non-zero element in this column. @@ -243,7 +243,7 @@ module ListMatrix: SparseMatrixFunctor = before @ (v :: after) let insert_v_according_to_piv m v piv_idx pivot_positions = - Timing.wrap "insert_v_according_to_piv" (insert_v_according_to_piv m v piv_idx) pivot_positions + timing_wrap "insert_v_according_to_piv" (insert_v_according_to_piv m v piv_idx) pivot_positions (** [rref_vec m v] yields the same result as appending [v] to [m], then bringing [m] into rref and removing all zero rows. diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index f423afa91a..b9ed69161c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -67,8 +67,6 @@ module SparseVector: SparseVectorFunctor = in "["^(sparse_list_str 0 v.entries)^"\n" - let show v = Timing.wrap "V.show" (show) v - let length v = v.len @@ -202,7 +200,7 @@ module SparseVector: SparseVectorFunctor = if v.entries = [] then None else Some (List.hd v.entries) - let find_first_non_zero v = Timing.wrap "find_first_non_zero" (find_first_non_zero) v + let find_first_non_zero v = timing_wrap "find_first_non_zero" (find_first_non_zero) v (** [map_f_preserves_zero f v] returns the mapping of [v] specified by [f]. @@ -216,7 +214,7 @@ module SparseVector: SparseVectorFunctor = if new_val = A.zero then None else Some (idx, new_val)) v.entries in {v with entries = entries'} - let map_f_preserves_zero f v = Timing.wrap "map_f_preserves_zero" (map_f_preserves_zero f) v + let map_f_preserves_zero f v = timing_wrap "map_f_preserves_zero" (map_f_preserves_zero f) v (** [mapi_f_preserves_zero f v] returns the mapping of [v] specified by [f]. @@ -256,7 +254,7 @@ module SparseVector: SparseVectorFunctor = if v.len <> v'.len then raise (Invalid_argument "Unequal lengths") else {v with entries = List.rev (aux [] v.entries v'.entries)} - let map2_f_preserves_zero f v1 v2 = Timing.wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 + let map2_f_preserves_zero f v1 v2 = timing_wrap "map2_f_preserves_zero" (map2_f_preserves_zero f v1) v2 (** @raise Invalid_argument if [v] and [v'] have unequal lengths diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 4b4ce61181..2cfcbfbfeb 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -28,7 +28,7 @@ struct let dim_add (ch: Apron.Dim.change) m = add_empty_columns m ch.dim - let dim_add ch m = Timing.wrap "dim add" (dim_add ch) m + let dim_add ch m = timing_wrap "dim add" (dim_add ch) m let dim_remove (ch: Apron.Dim.change) m ~del = @@ -39,7 +39,7 @@ struct let m' = if not del then Array.fold_left (fun y x -> reduce_col y x) m ch.dim else m in remove_zero_rows @@ del_cols m' ch.dim) - let dim_remove ch m ~del = Timing.wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del + let dim_remove ch m ~del = timing_wrap "dim remove" (fun del -> dim_remove ch m ~del:del) del end (** It defines the type t of the affine equality domain (a struct that contains an optional matrix and an apron environment) and provides the functions needed for handling variables (which are defined by RelationDomain.D2) such as add_vars remove_vars. @@ -61,7 +61,7 @@ struct | Some (i, value) when i = (Vector.length v) - 1 -> Some value | _ -> None - let to_constant_opt v = Timing.wrap "to_constant_opt" (to_constant_opt) v + let to_constant_opt v = timing_wrap "to_constant_opt" (to_constant_opt) v let get_coeff_vec (t: t) texp = (*Parses a Texpr to obtain a coefficient + const (last entry) vector to repr. an affine relation. @@ -118,7 +118,7 @@ struct Some (convert_texpr texp) with NotLinear -> None - let get_coeff_vec t texp = Timing.wrap "coeff_vec" (get_coeff_vec t) texp + let get_coeff_vec t texp = timing_wrap "coeff_vec" (get_coeff_vec t) texp end (** As it is specifically used for the new affine equality domain, it can only provide bounds if the expression contains known constants only and in that case, min and max are the same. *) @@ -145,7 +145,7 @@ struct res - let bound_texpr d texpr1 = Timing.wrap "bounds calculation" (bound_texpr d) texpr1 + let bound_texpr d texpr1 = timing_wrap "bounds calculation" (bound_texpr d) texpr1 end module D(Vc: SparseVectorFunctor) (Mx: SparseMatrixFunctor) = @@ -258,7 +258,7 @@ struct if M.tracing then M.tracel "meet" "meet a: %s b: %s -> %s " (show t1) (show t2) (show res) ; res - let meet t1 t2 = Timing.wrap "meet" (meet t1) t2 + let meet t1 t2 = timing_wrap "meet" (meet t1) t2 let leq t1 t2 = let env_comp = Environment.cmp t1.env t2.env in (* Apron's Environment.cmp has defined return values. *) @@ -277,7 +277,7 @@ struct let m1' = if env_comp = 0 then m1 else dim_add (Environment.dimchange t1.env t2.env) m1 in Matrix.is_covered_by m2 m1' - let leq a b = Timing.wrap "leq" (leq a) b + let leq a b = timing_wrap "leq" (leq a) b let leq t1 t2 = let res = leq t1 t2 in @@ -342,7 +342,7 @@ struct | x, y when Matrix.equal x y -> {d = Some x; env = a.env} | x, y -> {d = Some(lin_disjunc 0 0 x y); env = a.env} - let join a b = Timing.wrap "join" (join a) b + let join a b = timing_wrap "join" (join a) b let join a b = let res = join a b in @@ -363,7 +363,7 @@ struct let remove_rels_with_var x var env = let j0 = Environment.dim_of_var env var in Matrix.reduce_col x j0 - let remove_rels_with_var x var env = Timing.wrap "remove_rels_with_var" remove_rels_with_var x var env + let remove_rels_with_var x var env = timing_wrap "remove_rels_with_var" remove_rels_with_var x var env let forget_vars t vars = if is_bot t || is_top_env t || vars = [] then @@ -378,7 +378,7 @@ struct if M.tracing then M.tracel "ops" "forget_vars %s -> %s" (show t) (show res); res - let forget_vars t vars = Timing.wrap "forget_vars" (forget_vars t) vars + let forget_vars t vars = timing_wrap "forget_vars" (forget_vars t) vars let assign_texpr (t: VarManagement(Vc)(Mx).t) var texp = let assign_invertible_rels x var b env = @@ -396,7 +396,7 @@ struct | None -> bot () | some_normalized_matrix -> {d = some_normalized_matrix; env = env} in - let assign_invertible_rels x var b env = Timing.wrap "assign_invertible" (assign_invertible_rels x var b) env in + let assign_invertible_rels x var b env = timing_wrap "assign_invertible" (assign_invertible_rels x var b) env in let assign_uninvertible_rel x var b env = let b_length = Vector.length b in let b = Vector.mapi_f_preserves_zero (fun i z -> if i < b_length - 1 then Mpqf.neg z else z) b in @@ -405,7 +405,7 @@ struct | None -> bot () | some_matrix -> {d = some_matrix; env = env} in - (* let assign_uninvertible_rel x var b env = Timing.wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) + (* let assign_uninvertible_rel x var b env = timing_wrap "assign_uninvertible" (assign_uninvertible_rel x var b) env in *) let is_invertible v = Vector.nth v @@ Environment.dim_of_var t.env var <>: Mpqf.zero in let affineEq_vec = get_coeff_vec t texp in if is_bot t then t else let m = Option.get t.d in @@ -418,7 +418,7 @@ struct in assign_uninvertible_rel new_m var v t.env | None -> {d = Some (Matrix.remove_zero_rows @@ remove_rels_with_var m var t.env); env = t.env} - let assign_texpr t var texp = Timing.wrap "assign_texpr" (assign_texpr t var) texp + let assign_texpr t var texp = timing_wrap "assign_texpr" (assign_texpr t var) texp let assign_exp ask (t: VarManagement(Vc)(Mx).t) var exp (no_ov: bool Lazy.t) = let t = if not @@ Environment.mem_var t.env var then add_vars t [var] else t in @@ -470,7 +470,7 @@ struct if M.tracing then M.tracel "ops" "assign_var parallel: %s -> %s " (show t) (show res); res - let assign_var_parallel t vv's = Timing.wrap "var_parallel" (assign_var_parallel t) vv's + let assign_var_parallel t vv's = timing_wrap "var_parallel" (assign_var_parallel t) vv's let assign_var_parallel_with t vv's = let t' = assign_var_parallel t vv's in @@ -500,7 +500,7 @@ struct if M.tracing then M.tracel "ops" "Substitute_expr t: \n %s \n var: %a \n exp: %a \n -> \n %s" (show t) Var.pretty var d_exp exp (show res); res - let substitute_exp ask t var exp no_ov = Timing.wrap "substitution" (substitute_exp ask t var exp) no_ov + let substitute_exp ask t var exp no_ov = timing_wrap "substitution" (substitute_exp ask t var exp) no_ov (** Assert a constraint expression. @@ -545,7 +545,7 @@ struct end | None -> t - let meet_tcons t tcons expr = Timing.wrap "meet_tcons" (meet_tcons t tcons) expr + let meet_tcons t tcons expr = timing_wrap "meet_tcons" (meet_tcons t tcons) expr let unify a b = meet a b @@ -561,7 +561,7 @@ struct | tcons1 -> meet_tcons ask d tcons1 e | exception Convert.Unsupported_CilExp _ -> d - let assert_constraint ask d e negate no_ov = Timing.wrap "assert_constraint" (assert_constraint ask d e negate) no_ov + let assert_constraint ask d e negate no_ov = timing_wrap "assert_constraint" (assert_constraint ask d e negate) no_ov let relift t = t From 5e3f21a1aa37c0bc283eace5624130fa73b374d9 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 28 Jan 2025 18:54:55 +0100 Subject: [PATCH 213/240] Update rref_vec to filter non-relevant pivots --- .../sparseImplementation/listMatrix.ml | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 2e3440ac52..f00eb65cb8 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -8,7 +8,7 @@ module List = BatList (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. It provides a normalization function to reduce a matrix into reduced row echelon form. - Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) + Operations exploit that the input matrix/mtimatrices are in reduced row echelon form already. *) module ListMatrix: SparseMatrixFunctor = functor (A: RatOps) (V: SparseVectorFunctor) -> struct @@ -257,19 +257,21 @@ module ListMatrix: SparseMatrixFunctor = BatOption.map (fun (_, value) -> init_with_vec @@ div_row v value) (V.find_first_non_zero v) else (* We try to normalize v and check if a contradiction arises. If not, we insert v at the appropriate place in m (depending on the pivot) *) let pivot_positions = get_pivot_positions m in - let v_after_elim = List.fold_left ( - fun acc (row_idx, pivot_position, piv_row) -> - let v_at_piv = V.nth acc pivot_position in - if v_at_piv =: A.zero then - acc - else - sub_scaled_row acc piv_row v_at_piv - ) v pivot_positions - in + (* filtered_pivots are only the pivots which have a non-zero entry in the corresponding column of v. Only those are relevant to subtract from v *) + let filtered_pivots = List.rev @@ fst @@ List.fold_left (fun (res, pivs_tail) (col_idx, value) -> + let pivs_tail = List.drop_while (fun (_, piv_col, _) -> piv_col < col_idx) pivs_tail in (* Skipping until possible match of both cols *) + match pivs_tail with + | [] -> (res, []) + | (row_idx, piv_col, row) :: ps when piv_col = col_idx -> ((row_idx, piv_col, row, value) :: res, ps) + | _ -> (res, pivs_tail) + ) ([], pivot_positions) (V.to_sparse_list v) in + let v_after_elim = List.fold_left (fun acc (row_idx, pivot_position, piv_row, v_at_piv) -> + sub_scaled_row acc piv_row v_at_piv + ) v filtered_pivots in match V.find_first_non_zero v_after_elim with (* now we check for contradictions and finally insert v *) | None -> Some m (* v is zero vector and was therefore already covered by m *) - | Some (idx, value) -> - if idx = (num_cols m - 1) then + | Some (idx, value) -> + if idx = (num_cols m - 1) then None else let normalized_v = V.map_f_preserves_zero (fun x -> x /: value) v_after_elim in From 9f5b2d2b73c7c43d3fc69af5ec80f194b9223967 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 28 Jan 2025 19:01:15 +0100 Subject: [PATCH 214/240] Remove duplicate SparseMatrixTests from unit tests --- tests/unit/mainTest.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/mainTest.ml b/tests/unit/mainTest.ml index eab292623f..6dea9bec8d 100644 --- a/tests/unit/mainTest.ml +++ b/tests/unit/mainTest.ml @@ -14,7 +14,6 @@ let all_tests = (* etc *) "domaintest" >::: QCheck_ounit.to_ounit2_test_list Maindomaintest.all_testsuite; IntOpsTest.tests; - SparseMatrixImplementationTest.tests; ] let () = From 96e6e6d7e8374ac0f0eb85f02463f0ce239f6826 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 30 Jan 2025 15:34:14 +0100 Subject: [PATCH 215/240] Remove unnecessary rev in affeq domain --- src/cdomains/apron/affineEqualityDomain.apron.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 2cfcbfbfeb..c856a5ad90 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -294,7 +294,8 @@ struct in let case_three a b col_a col_b max = let col_a, col_b = Vector.keep_vals col_a max, Vector.keep_vals col_b max in - if Vector.equal col_a col_b then + let col_diff = Vector.map2_f_preserves_zero (-:) col_a col_b in + if Vector.is_zero_vec col_diff then (a, b, max) else ( @@ -304,10 +305,8 @@ struct let (x, y) = Vector.nth col_a i, Vector.nth col_b i in let r, diff = Vector.length col_a - (i + 1), x -: y in let a_r, b_r = Matrix.get_row a r, Matrix.get_row b r in - let col_a = Vector.map2_f_preserves_zero (-:) col_a col_b in - let col_a = Vector.rev col_a in let multiply_by_t m t = - Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2_f_preserves_zero (fun u j -> u -: (beta *: j)) x t) else x) m col_a + Matrix.map2i (fun i' x c -> if i' <= max then (let beta = c /: diff in Vector.map2_f_preserves_zero (fun u j -> u -: (beta *: j)) x t) else x) m col_diff in Matrix.remove_row (multiply_by_t a a_r) r, Matrix.remove_row (multiply_by_t b b_r) r, (max - 1) ) From edbf0ec0062ad14857406d3eb5cd66db7860cef3 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 30 Jan 2025 17:06:02 +0100 Subject: [PATCH 216/240] Changed map2 back to version without V.nth --- .../sparseImplementation/listMatrix.ml | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index f00eb65cb8..d7942e704f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -56,13 +56,37 @@ module ListMatrix: SparseMatrixFunctor = let map2 f m v = let vector_length = V.length v in - List.mapi (fun index row -> if index < vector_length then f row (V.nth v index) else row ) m + let vector_entries = V.to_sparse_list v in + let rec map2_helper acc index m v = + match m, v with + | [], _ -> List.rev acc + | row :: rs, [] when index >= vector_length -> List.rev_append acc m + | row :: rs, [] -> map2_helper ((f row A.zero):: acc) (index + 1) rs [] + | row :: rs, (i, value) :: vs -> + if i = index then + map2_helper ((f row value):: acc) (index + 1) rs vs + else + map2_helper ((f row A.zero) :: acc) (index + 1) rs v + in + map2_helper [] 0 m vector_entries let map2 f m v = timing_wrap "Matrix.map2" (map2 f m) v let map2i f m v = let vector_length = V.length v in - List.mapi (fun index row -> if index < vector_length then f index row (V.nth v index) else row ) m + let vector_entries = V.to_sparse_list v in + let rec map2i_helper acc index m v = + match m, v with + | [], _ -> List.rev acc + | row :: rs, [] when index >= vector_length -> List.rev_append acc m + | row :: rs, [] -> map2i_helper ((f index row A.zero):: acc) (index + 1) rs [] + | row :: rs, (i, value) :: vs -> + if i = index then + map2i_helper ((f index row value):: acc) (index + 1) rs vs + else + map2i_helper ((f index row A.zero) :: acc) (index + 1) rs v + in + map2i_helper [] 0 m vector_entries let map2i f m v = timing_wrap "Matrix.map2i" (map2i f m) v From 35b564425e82870e1058cc50c0bfe6c1b4c006d3 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 30 Jan 2025 17:49:41 +0100 Subject: [PATCH 217/240] Add comment explaining type t of sparseVector --- src/cdomains/affineEquality/sparseImplementation/listMatrix.ml | 2 +- .../affineEquality/sparseImplementation/sparseVector.ml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index d7942e704f..cc7e1d9e5c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -8,7 +8,7 @@ module List = BatList (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. It provides a normalization function to reduce a matrix into reduced row echelon form. - Operations exploit that the input matrix/mtimatrices are in reduced row echelon form already. *) + Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) module ListMatrix: SparseMatrixFunctor = functor (A: RatOps) (V: SparseVectorFunctor) -> struct diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index b9ed69161c..81484b18e3 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -13,6 +13,7 @@ module SparseVector: SparseVectorFunctor = struct include ConvenienceOps (A) + (** Only non-zero [entries] are stored in a list of tuples of (index, value). All values not contained in [entries] are implicitly [A.Zero]. *) type t = { entries: (int * A.t) list ; len: int From 52f29ed30e3703efb55ce8b38fabfd8b49111b08 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 30 Jan 2025 19:39:50 +0100 Subject: [PATCH 218/240] Add and Implement compare_num_rows to Matrix, SparseMatrix, ArrayMatrix --- .../affineEquality/arrayImplementation/arrayMatrix.ml | 3 +++ src/cdomains/affineEquality/matrix.ml | 2 ++ .../affineEquality/sparseImplementation/listMatrix.ml | 6 ++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index c5d03e263e..d554bb3428 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -29,6 +29,9 @@ module ArrayMatrix: ArrayMatrixFunctor = let num_rows m = Array.length m + let compare_num_rows m1 m2 = + Int.compare (Array.length m1) (Array.length m2) + let is_empty m = (num_rows m = 0) diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index ed264b063a..2fea011bb3 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -15,6 +15,8 @@ sig val num_rows: t -> int + val compare_num_rows: t -> t -> int + val num_cols: t -> int val init_with_vec: vec -> t diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index cc7e1d9e5c..408df0db5c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -34,6 +34,8 @@ module ListMatrix: SparseMatrixFunctor = let num_rows = List.length + let compare_num_rows = List.compare_lengths + let num_cols m = if m = [] then 0 else V.length (hd m) @@ -310,7 +312,7 @@ module ListMatrix: SparseMatrixFunctor = @param m' A matrix in rref. *) let rref_matrix m1 m2 = - let big_m, small_m = if num_rows m1 > num_rows m2 then m1, m2 else m2, m1 in + let big_m, small_m = if compare_num_rows m1 m2 > 0 then m1, m2 else m2, m1 in fst @@ List.fold_while (fun acc _ -> Option.is_some acc) (fun acc_big_m small -> rref_vec (Option.get acc_big_m) small ) (Some big_m) small_m @@ -338,7 +340,7 @@ module ListMatrix: SparseMatrixFunctor = let new_v = V.map2_f_preserves_zero (fun v1 v2 -> v1 -: (pivot *: v2)) v x in is_linearly_independent_rref new_v m' in - if num_rows m1 > num_rows m2 then false else + if compare_num_rows m1 m2 > 0 then false else let rec is_covered_by_helper m1 m2 = match m1 with | [] -> true From 165fc7aa6771b45ce3d835922da5744846ec821f Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 4 Feb 2025 19:07:04 +0100 Subject: [PATCH 219/240] Update find_first_non_zero --- .../affineEquality/sparseImplementation/sparseVector.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 81484b18e3..75b4b5fcae 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -198,8 +198,9 @@ module SparseVector: SparseVectorFunctor = @return [(idx, e) option] *) let find_first_non_zero v = - if v.entries = [] then None - else Some (List.hd v.entries) + match v.entries with + | [] -> None + | x :: _ -> Some x let find_first_non_zero v = timing_wrap "find_first_non_zero" (find_first_non_zero) v From 0a4e299b616269e2677bfd9a87624247907cb973 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Wed, 5 Feb 2025 17:00:40 +0100 Subject: [PATCH 220/240] Replace more Timing.wrap --- src/cdomains/affineEquality/vectorFunctor.ml | 4 ++-- src/cdomains/apron/affineEqualityDomain.apron.ml | 1 - src/cdomains/apron/sharedFunctions.apron.ml | 15 +++++++-------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/cdomains/affineEquality/vectorFunctor.ml b/src/cdomains/affineEquality/vectorFunctor.ml index e20f92c2f4..299063eef7 100644 --- a/src/cdomains/affineEquality/vectorFunctor.ml +++ b/src/cdomains/affineEquality/vectorFunctor.ml @@ -13,7 +13,7 @@ module type SparseVectorFunctor = include SparseVector with type num:= A.t end -(* let timing_wrap = Timing.wrap *) -(* Disable timing of VectorMatrix and AffineEqualityDomain. +(*let timing_wrap = Timing.wrap*) +(* Disable timing of the vector and matrix implementations and AffineEqualityDomain as well as SharedFunctions. This is cleaner than a timing functor because the timed functions also call each other. *) let timing_wrap _ f x = f x diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index c856a5ad90..c4dce90752 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -21,7 +21,6 @@ module Array = Batteries.Array module Mpqf = SharedFunctions.Mpqf - module AffineEqualityMatrix (Vec: SparseVectorFunctor) (Mx: SparseMatrixFunctor) = struct include Mx(Mpqf) (Vec) diff --git a/src/cdomains/apron/sharedFunctions.apron.ml b/src/cdomains/apron/sharedFunctions.apron.ml index a3821e9de3..6ce473aad6 100644 --- a/src/cdomains/apron/sharedFunctions.apron.ml +++ b/src/cdomains/apron/sharedFunctions.apron.ml @@ -7,7 +7,6 @@ open GobApron module M = Messages - let int_of_scalar ?(scalewith=Z.one) ?round (scalar: Scalar.t) = if Scalar.is_infty scalar <> 0 then (* infinity means unbounded *) None @@ -405,7 +404,7 @@ struct in {d = Some (if add then RelDomain.dim_add dim_change m else RelDomain.dim_remove dim_change m ~del:del); env = new_env} - let change_d t new_env ~add ~del = Timing.wrap "dimension change" (fun del -> change_d t new_env ~add:add ~del:del) del + let change_d t new_env ~add ~del = VectorFunctor.timing_wrap "dimension change" (fun del -> change_d t new_env ~add:add ~del:del) del let vars x = Environment.ivars_only x.env @@ -414,18 +413,18 @@ struct let env' = Environment.add_vars t.env vars in change_d t env' ~add:true ~del:false - let add_vars t vars = Timing.wrap "add_vars" (add_vars t) vars + let add_vars t vars = VectorFunctor.timing_wrap "add_vars" (add_vars t) vars let drop_vars t vars ~del = let t = copy t in let env' = Environment.remove_vars t.env vars in change_d t env' ~add:false ~del:del - let drop_vars t vars = Timing.wrap "drop_vars" (drop_vars t) vars + let drop_vars t vars = VectorFunctor.timing_wrap "drop_vars" (drop_vars t) vars let remove_vars t vars = drop_vars t vars ~del:false - let remove_vars t vars = Timing.wrap "remove_vars" (remove_vars t) vars + let remove_vars t vars = VectorFunctor.timing_wrap "remove_vars" (remove_vars t) vars let remove_vars_with t vars = let t' = remove_vars t vars in @@ -436,7 +435,7 @@ struct let env' = Environment.remove_filter t.env f in change_d t env' ~add:false ~del:false - let remove_filter t f = Timing.wrap "remove_filter" (remove_filter t) f + let remove_filter t f = VectorFunctor.timing_wrap "remove_filter" (remove_filter t) f let remove_filter_with t f = let t' = remove_filter t f in @@ -448,14 +447,14 @@ struct let env' = Environment.keep_filter t.env f in change_d t env' ~add:false ~del:false - let keep_filter t f = Timing.wrap "keep_filter" (keep_filter t) f + let keep_filter t f = VectorFunctor.timing_wrap "keep_filter" (keep_filter t) f let keep_vars t vs = let t = copy t in let env' = Environment.keep_vars t.env vs in change_d t env' ~add:false ~del:false - let keep_vars t vs = Timing.wrap "keep_vars" (keep_vars t) vs + let keep_vars t vs = VectorFunctor.timing_wrap "keep_vars" (keep_vars t) vs let mem_var t var = Environment.mem_var t.env var From 2e4b11546e84d5a70455cbd2cd279f7e1c57a2a0 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 13 Feb 2025 16:59:30 +0100 Subject: [PATCH 221/240] Remove execution of affeq unit tests in test file --- .../sparseImplementation/sparseMatrixImplementationTest.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 2aeedff556..5c8673a169 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -369,6 +369,4 @@ let tests = "map2i one zero vector" >:: vectorMap2i_one_zero; "map zero preserving normal" >:: vectorMap_zero_preserving_normal; "get column when matrix in rref" >:: get_col_upper_triangular; - ] - -let () = run_test_tt_main tests + ] \ No newline at end of file From 3d422cd51ded6379adcdfcb3a47b0636afe234f7 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Thu, 13 Feb 2025 17:03:10 +0100 Subject: [PATCH 222/240] Add comment to domains explaining NoSideEffect domain --- src/cdomains/apron/affineEqualityDomain.apron.ml | 4 +++- src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index c4dce90752..207e2af405 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -2,7 +2,9 @@ @see Karr, M. Affine relationships among variables of a program. *) -(** Abstract states in the newly added domain are represented by structs containing a matrix and an apron environment. +(** There are two versions of the AffineEqualityDomain. + Unlike the other version, this version here is NOT based on side effects. + Abstract states in the newly added domain are represented by structs containing a matrix and an apron environment. Matrices are modeled as proposed by Karr: Each variable is assigned to a column and each row represents a linear affine relationship that must hold at the corresponding program point. The apron environment is hereby used to organize the order of columns and variables. *) diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml index 1864631291..350020347c 100644 --- a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -2,7 +2,9 @@ @see Karr, M. Affine relationships among variables of a program. *) -(** Abstract states in the newly added domain are represented by structs containing a matrix and an apron environment. +(** There are two versions of the AffineEqualityDomain. + This version here is based on side effects, thus it uses Matrix and Vector functions marked with "_with" which use side effects. + Abstract states in the newly added domain are represented by structs containing a matrix and an apron environment. Matrices are modeled as proposed by Karr: Each variable is assigned to a column and each row represents a linear affine relationship that must hold at the corresponding program point. The apron environment is hereby used to organize the order of columns and variables. *) From 431c69a5b855b324c1af1aab853f0f0626c9fd1c Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 18 Feb 2025 17:46:07 +0100 Subject: [PATCH 223/240] Change matrix tests such that they don't run themselves --- .../sparseMatrixImplementationTest.ml | 8 +++----- tests/unit/mainTest.ml | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 2aeedff556..3d27ba582b 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -1,5 +1,5 @@ (* - To run this, type `dune runtest tests/unit/`. + To run this (and all other unit tests), type `dune runtest tests/unit/`. *) open Goblint_lib @@ -345,7 +345,7 @@ let get_col_upper_triangular _ = assert_equal expected result -let tests = +let test () = "SparseMatrixImplementationTest" >::: [ "can solve a standard normalization" >:: standard_normalize; @@ -369,6 +369,4 @@ let tests = "map2i one zero vector" >:: vectorMap2i_one_zero; "map zero preserving normal" >:: vectorMap_zero_preserving_normal; "get column when matrix in rref" >:: get_col_upper_triangular; - ] - -let () = run_test_tt_main tests + ] \ No newline at end of file diff --git a/tests/unit/mainTest.ml b/tests/unit/mainTest.ml index 37cafef544..3ab350d0fe 100644 --- a/tests/unit/mainTest.ml +++ b/tests/unit/mainTest.ml @@ -7,7 +7,7 @@ let all_tests = MapDomainTest.test (); SolverTest.test (); LvalTest.test (); - SparseMatrixImplementationTest.tests ; + SparseMatrixImplementationTest.test () ; CompilationDatabaseTest.tests; LibraryDslTest.tests; CilfacadeTest.tests; From 8daa4de44df93038e37a487754593cf598c31685 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 18 Feb 2025 19:39:05 +0100 Subject: [PATCH 224/240] Move interfaces to their respective files --- .../arrayImplementation/arrayMatrix.ml | 38 +++++++++++- .../arrayImplementation/arrayVector.ml | 37 +++++++++++- src/cdomains/affineEquality/matrix.ml | 36 ------------ src/cdomains/affineEquality/matrixFunctor.ml | 16 ----- .../sparseImplementation/listMatrix.ml | 24 +++++++- .../sparseImplementation/sparseVector.ml | 33 ++++++++++- src/cdomains/affineEquality/vector.ml | 58 ++----------------- src/cdomains/affineEquality/vectorFunctor.ml | 19 ------ .../apron/affineEqualityDomain.apron.ml | 4 +- .../affineEqualityDomainSideEffects.apron.ml | 4 +- src/cdomains/apron/sharedFunctions.apron.ml | 14 ++--- src/goblint_lib.ml | 2 - 12 files changed, 140 insertions(+), 145 deletions(-) delete mode 100644 src/cdomains/affineEquality/matrixFunctor.ml delete mode 100644 src/cdomains/affineEquality/vectorFunctor.ml diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index d554bb3428..b3abd3fede 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -1,12 +1,44 @@ -open VectorFunctor -open MatrixFunctor - +open Matrix +open ArrayVector open RatOps open ConvenienceOps open Batteries module Array = Batteries.Array +let timing_wrap = Vector.timing_wrap + +module type ArrayMatrix = +sig + include Matrix + val get_col: t -> int -> vec + + val set_col_with: t -> vec -> int -> t + + val del_col: t -> int -> t + + val reduce_col_with: t -> int -> unit + + val normalize_with: t -> bool + + val rref_vec_with: t -> vec -> t Option.t + + val rref_matrix_with: t -> t -> t Option.t + + val map2_with: (vec -> num -> vec) -> t -> vec -> unit + + val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit + + val append_matrices: t -> t -> t +end + +(** Some functions inside have the suffix _with, which means that the function has side effects. *) +module type ArrayMatrixFunctor = + functor (A: RatOps) (V: ArrayVectorFunctor) -> + sig + include ArrayMatrix with type vec := V(A).t and type num := A.t + end + (** Array-based matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 7203d85af0..baea3f71db 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -1,10 +1,45 @@ -open VectorFunctor +open Vector open RatOps open ConvenienceOps open Batteries module Array = Batteries.Array +module type ArrayVector = +sig + include Vector + val mapi_with: (int -> num -> num) -> t -> unit + + val map_with: (num -> num) -> t -> unit + + val map2_with: (num -> num -> num) -> t -> t -> unit + + val map2i_with: (int -> num -> num -> num) -> t -> t -> unit + + val filteri: (int -> num -> bool) -> t -> t + + val findi: (num -> bool) -> t -> int + + val find2i: (num -> num -> bool) -> t -> t -> int + + val exists: (num -> bool) -> t -> bool + + val set_nth_with: t -> int -> num -> unit + + val insert_val_at: t -> int -> num -> t + + val apply_with_c_with: (num -> num -> num) -> num -> t -> unit + + val rev_with: t -> unit + + val append: t -> t -> t +end + +module type ArrayVectorFunctor = + functor (A: RatOps) -> + sig + include ArrayVector with type num:= A.t + end (** Array-based vector implementation. *) module ArrayVector: ArrayVectorFunctor = diff --git a/src/cdomains/affineEquality/matrix.ml b/src/cdomains/affineEquality/matrix.ml index 2fea011bb3..5460c2a230 100644 --- a/src/cdomains/affineEquality/matrix.ml +++ b/src/cdomains/affineEquality/matrix.ml @@ -46,40 +46,4 @@ sig val normalize: t -> t Option.t (* Gauss-Jordan Elimination to get matrix in reduced row echelon form (rref) + deletion of zero rows. None matrix has no solution *) val is_covered_by: t -> t -> bool -end - -module type ArrayMatrix = -sig - include Matrix - val get_col: t -> int -> vec - - val set_col_with: t -> vec -> int -> t - - val del_col: t -> int -> t - - val reduce_col_with: t -> int -> unit - - val normalize_with: t -> bool - - val rref_vec_with: t -> vec -> t Option.t - - val rref_matrix_with: t -> t -> t Option.t - - val map2_with: (vec -> num -> vec) -> t -> vec -> unit - - val map2i_with: (int -> vec -> num -> vec) -> t -> vec -> unit - - val append_matrices: t -> t -> t -end - -module type SparseMatrix = -sig - include Matrix - val get_col_upper_triangular: t -> int -> vec - - val swap_rows: t -> int -> int -> t - - val rref_vec: t -> vec -> t Option.t - - val rref_matrix: t -> t -> t Option.t end \ No newline at end of file diff --git a/src/cdomains/affineEquality/matrixFunctor.ml b/src/cdomains/affineEquality/matrixFunctor.ml deleted file mode 100644 index 958dd77282..0000000000 --- a/src/cdomains/affineEquality/matrixFunctor.ml +++ /dev/null @@ -1,16 +0,0 @@ -open RatOps -open VectorFunctor -open Matrix - -(** Some functions inside have the suffix _with, which means that the function has side effects. *) -module type ArrayMatrixFunctor = - functor (A: RatOps) (V: ArrayVectorFunctor) -> - sig - include ArrayMatrix with type vec := V(A).t and type num := A.t - end - -module type SparseMatrixFunctor = - functor (A: RatOps) (V: SparseVectorFunctor) -> - sig - include SparseMatrix with type vec := V(A).t and type num := A.t - end diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 408df0db5c..635b34dc4c 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -1,11 +1,31 @@ -open MatrixFunctor -open VectorFunctor +open Matrix +open SparseVector open RatOps open ConvenienceOps open BatList module List = BatList +let timing_wrap = Vector.timing_wrap + +module type SparseMatrix = +sig + include Matrix + val get_col_upper_triangular: t -> int -> vec + + val swap_rows: t -> int -> int -> t + + val rref_vec: t -> vec -> t Option.t + + val rref_matrix: t -> t -> t Option.t +end + +module type SparseMatrixFunctor = + functor (A: RatOps) (V: SparseVectorFunctor) -> + sig + include SparseMatrix with type vec := V(A).t and type num := A.t + end + (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 75b4b5fcae..f62f70995f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -1,4 +1,4 @@ -open VectorFunctor +open Vector open RatOps open ConvenienceOps @@ -8,6 +8,37 @@ open Batteries module List = BatList module Array = BatArray +module type SparseVector = +sig + include Vector + val is_zero_vec: t -> bool + + val insert_zero_at_indices: t -> (int * int) list -> int -> t + + val remove_at_indices: t -> int list -> t + + (* Returns the part of the vector starting from index n*) + val starting_from_nth : t -> int -> t + + val find_first_non_zero : t -> (int * num) option + + val map_f_preserves_zero: (num -> num) -> t -> t + + val mapi_f_preserves_zero: (int -> num -> num) -> t -> t + + val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t + + val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int + + val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t +end + +module type SparseVectorFunctor = + functor (A: RatOps) -> + sig + include SparseVector with type num:= A.t + end + module SparseVector: SparseVectorFunctor = functor (A: RatOps) -> struct diff --git a/src/cdomains/affineEquality/vector.ml b/src/cdomains/affineEquality/vector.ml index bc08de7b62..32e78f8b5b 100644 --- a/src/cdomains/affineEquality/vector.ml +++ b/src/cdomains/affineEquality/vector.ml @@ -41,57 +41,7 @@ sig val rev: t -> t end -module type ArrayVector = -sig - include Vector - val mapi_with: (int -> num -> num) -> t -> unit - - val map_with: (num -> num) -> t -> unit - - val map2_with: (num -> num -> num) -> t -> t -> unit - - val map2i_with: (int -> num -> num -> num) -> t -> t -> unit - - val filteri: (int -> num -> bool) -> t -> t - - val findi: (num -> bool) -> t -> int - - val find2i: (num -> num -> bool) -> t -> t -> int - - val exists: (num -> bool) -> t -> bool - - val set_nth_with: t -> int -> num -> unit - - val insert_val_at: t -> int -> num -> t - - val apply_with_c_with: (num -> num -> num) -> num -> t -> unit - - val rev_with: t -> unit - - val append: t -> t -> t -end - -module type SparseVector = -sig - include Vector - val is_zero_vec: t -> bool - - val insert_zero_at_indices: t -> (int * int) list -> int -> t - - val remove_at_indices: t -> int list -> t - - (* Returns the part of the vector starting from index n*) - val starting_from_nth : t -> int -> t - - val find_first_non_zero : t -> (int * num) option - - val map_f_preserves_zero: (num -> num) -> t -> t - - val mapi_f_preserves_zero: (int -> num -> num) -> t -> t - - val map2_f_preserves_zero: (num -> num -> num) -> t -> t -> t - - val find2i_f_false_at_zero: (num -> num -> bool) -> t -> t -> int - - val apply_with_c_f_preserves_zero: (num -> num -> num) -> num -> t -> t -end \ No newline at end of file +(*let timing_wrap = Timing.wrap*) +(* Disable timing of the vector and matrix implementations and AffineEqualityDomain as well as SharedFunctions. + This is cleaner than a timing functor because the timed functions also call each other. *) +let timing_wrap _ f x = f x \ No newline at end of file diff --git a/src/cdomains/affineEquality/vectorFunctor.ml b/src/cdomains/affineEquality/vectorFunctor.ml deleted file mode 100644 index 299063eef7..0000000000 --- a/src/cdomains/affineEquality/vectorFunctor.ml +++ /dev/null @@ -1,19 +0,0 @@ -open RatOps -open Vector - -module type ArrayVectorFunctor = - functor (A: RatOps) -> - sig - include ArrayVector with type num:= A.t - end - -module type SparseVectorFunctor = - functor (A: RatOps) -> - sig - include SparseVector with type num:= A.t - end - -(*let timing_wrap = Timing.wrap*) -(* Disable timing of the vector and matrix implementations and AffineEqualityDomain as well as SharedFunctions. - This is cleaner than a timing functor because the timed functions also call each other. *) -let timing_wrap _ f x = f x diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 207e2af405..766374f659 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -15,8 +15,8 @@ module M = Messages open GobApron open ConvenienceOps -open VectorFunctor -open MatrixFunctor +open SparseVector +open ListMatrix open Batteries module Array = Batteries.Array diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml index 350020347c..d6e631752f 100644 --- a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -14,8 +14,8 @@ module M = Messages open GobApron open ConvenienceOps -open VectorFunctor -open MatrixFunctor +open ArrayVector +open ArrayMatrix open Batteries module Array = BatArray diff --git a/src/cdomains/apron/sharedFunctions.apron.ml b/src/cdomains/apron/sharedFunctions.apron.ml index 6ce473aad6..464c10ec74 100644 --- a/src/cdomains/apron/sharedFunctions.apron.ml +++ b/src/cdomains/apron/sharedFunctions.apron.ml @@ -404,7 +404,7 @@ struct in {d = Some (if add then RelDomain.dim_add dim_change m else RelDomain.dim_remove dim_change m ~del:del); env = new_env} - let change_d t new_env ~add ~del = VectorFunctor.timing_wrap "dimension change" (fun del -> change_d t new_env ~add:add ~del:del) del + let change_d t new_env ~add ~del = Vector.timing_wrap "dimension change" (fun del -> change_d t new_env ~add:add ~del:del) del let vars x = Environment.ivars_only x.env @@ -413,18 +413,18 @@ struct let env' = Environment.add_vars t.env vars in change_d t env' ~add:true ~del:false - let add_vars t vars = VectorFunctor.timing_wrap "add_vars" (add_vars t) vars + let add_vars t vars = Vector.timing_wrap "add_vars" (add_vars t) vars let drop_vars t vars ~del = let t = copy t in let env' = Environment.remove_vars t.env vars in change_d t env' ~add:false ~del:del - let drop_vars t vars = VectorFunctor.timing_wrap "drop_vars" (drop_vars t) vars + let drop_vars t vars = Vector.timing_wrap "drop_vars" (drop_vars t) vars let remove_vars t vars = drop_vars t vars ~del:false - let remove_vars t vars = VectorFunctor.timing_wrap "remove_vars" (remove_vars t) vars + let remove_vars t vars = Vector.timing_wrap "remove_vars" (remove_vars t) vars let remove_vars_with t vars = let t' = remove_vars t vars in @@ -435,7 +435,7 @@ struct let env' = Environment.remove_filter t.env f in change_d t env' ~add:false ~del:false - let remove_filter t f = VectorFunctor.timing_wrap "remove_filter" (remove_filter t) f + let remove_filter t f = Vector.timing_wrap "remove_filter" (remove_filter t) f let remove_filter_with t f = let t' = remove_filter t f in @@ -447,14 +447,14 @@ struct let env' = Environment.keep_filter t.env f in change_d t env' ~add:false ~del:false - let keep_filter t f = VectorFunctor.timing_wrap "keep_filter" (keep_filter t) f + let keep_filter t f = Vector.timing_wrap "keep_filter" (keep_filter t) f let keep_vars t vs = let t = copy t in let env' = Environment.keep_vars t.env vs in change_d t env' ~add:false ~del:false - let keep_vars t vs = VectorFunctor.timing_wrap "keep_vars" (keep_vars t) vs + let keep_vars t vs = Vector.timing_wrap "keep_vars" (keep_vars t) vs let mem_var t var = Environment.mem_var t.env var diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 8e7a63a07f..7a67c2c3a4 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -437,8 +437,6 @@ module WideningThresholds = WideningThresholds (* There might be a more elegant solution. *) module Vector = Vector module Matrix = Matrix -module VectorFunctor = VectorFunctor -module MatrixFunctor = MatrixFunctor module ArrayVector = ArrayVector module ArrayMatrix = ArrayMatrix module SparseVector = SparseVector From 282cc24124935f5a75fc5ac9f92d318770ab27b2 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 18 Feb 2025 19:56:24 +0100 Subject: [PATCH 225/240] Moved ConvenienceOps into RatOps file --- .../arrayImplementation/arrayMatrix.ml | 1 - .../arrayImplementation/arrayVector.ml | 1 - src/cdomains/affineEquality/convenienceOps.ml | 18 ------------------ src/cdomains/affineEquality/ratOps.ml | 17 +++++++++++++++++ .../sparseImplementation/listMatrix.ml | 1 - .../sparseImplementation/sparseVector.ml | 1 - .../apron/affineEqualityDomain.apron.ml | 5 ++--- .../affineEqualityDomainSideEffects.apron.ml | 5 ++--- .../apron/linearTwoVarEqualityDomain.apron.ml | 4 +--- src/goblint_lib.ml | 1 - .../sparseMatrixImplementationTest.ml | 3 +-- 11 files changed, 23 insertions(+), 34 deletions(-) delete mode 100644 src/cdomains/affineEquality/convenienceOps.ml diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index d554bb3428..07495025d6 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -2,7 +2,6 @@ open VectorFunctor open MatrixFunctor open RatOps -open ConvenienceOps open Batteries module Array = Batteries.Array diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 7203d85af0..b0422567fd 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -1,6 +1,5 @@ open VectorFunctor open RatOps -open ConvenienceOps open Batteries module Array = Batteries.Array diff --git a/src/cdomains/affineEquality/convenienceOps.ml b/src/cdomains/affineEquality/convenienceOps.ml deleted file mode 100644 index 39aeeeb5e8..0000000000 --- a/src/cdomains/affineEquality/convenienceOps.ml +++ /dev/null @@ -1,18 +0,0 @@ -open RatOps - -(** It provides more readable infix operators for the functions of RatOps. - It is designed to be included by modules that make use of RatOps's functions. *) -module ConvenienceOps (A: RatOps) = -struct - let ( *: ) = A.mul - let (+:) = A.add - let (-:) = A.sub - let (/:) = A.div - let (=:) x y = A.equal x y - let (<>:) x y = not (A.equal x y) - let (<:) x y = A.compare x y < 0 - let (>:) x y = A.compare x y > 0 - let (<=:) x y = A.compare x y <= 0 - let (>=:) x y = A.compare x y >= 0 - let of_int x = A.of_int x -end diff --git a/src/cdomains/affineEquality/ratOps.ml b/src/cdomains/affineEquality/ratOps.ml index c8d8017693..35ec136ba6 100644 --- a/src/cdomains/affineEquality/ratOps.ml +++ b/src/cdomains/affineEquality/ratOps.ml @@ -15,4 +15,21 @@ sig val one: t val get_den: t -> Z.t val get_num: t -> Z.t +end + +(** It provides more readable infix operators for the functions of RatOps. + It is designed to be included by modules that make use of RatOps's functions. *) +module ConvenienceOps (A: RatOps) = +struct + let ( *: ) = A.mul + let (+:) = A.add + let (-:) = A.sub + let (/:) = A.div + let (=:) x y = A.equal x y + let (<>:) x y = not (A.equal x y) + let (<:) x y = A.compare x y < 0 + let (>:) x y = A.compare x y > 0 + let (<=:) x y = A.compare x y <= 0 + let (>=:) x y = A.compare x y >= 0 + let of_int x = A.of_int x end \ No newline at end of file diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 408df0db5c..61828de384 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -1,7 +1,6 @@ open MatrixFunctor open VectorFunctor open RatOps -open ConvenienceOps open BatList module List = BatList diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 75b4b5fcae..736c968e2f 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -1,6 +1,5 @@ open VectorFunctor open RatOps -open ConvenienceOps open BatList open Batteries diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index 207e2af405..b02ee9e6cd 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -14,7 +14,6 @@ open Pretty module M = Messages open GobApron -open ConvenienceOps open VectorFunctor open MatrixFunctor @@ -53,7 +52,7 @@ struct let dim_add = Matrix.dim_add include SharedFunctions.VarManagementOps(AffineEqualityMatrix (Vec) (Mx)) - include ConvenienceOps(Mpqf) + include RatOps.ConvenienceOps(Mpqf) (** Get the constant from the vector if it is a constant *) @@ -152,7 +151,7 @@ end module D(Vc: SparseVectorFunctor) (Mx: SparseMatrixFunctor) = struct include Printable.Std - include ConvenienceOps (Mpqf) + include RatOps.ConvenienceOps (Mpqf) include VarManagement (Vc) (Mx) module Bounds = ExpressionBounds (Vc) (Mx) diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml index 350020347c..5e1a687e08 100644 --- a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -13,7 +13,6 @@ open Pretty module M = Messages open GobApron -open ConvenienceOps open VectorFunctor open MatrixFunctor @@ -53,7 +52,7 @@ struct let dim_add = Matrix.dim_add include SharedFunctions.VarManagementOps(AffineEqualityMatrix (Vec) (Mx)) - include ConvenienceOps(Mpqf) + include RatOps.ConvenienceOps(Mpqf) (** Get the constant from the vector if it is a constant *) let to_constant_opt v = match Vector.findi ((<>:) Mpqf.zero) v with @@ -151,7 +150,7 @@ end module D(Vc: ArrayVectorFunctor) (Mx: ArrayMatrixFunctor) = struct include Printable.Std - include ConvenienceOps (Mpqf) + include RatOps.ConvenienceOps (Mpqf) include VarManagement (Vc) (Mx) module Bounds = ExpressionBounds (Vc) (Mx) diff --git a/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml b/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml index a712dda732..4684d6d02b 100644 --- a/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml +++ b/src/cdomains/apron/linearTwoVarEqualityDomain.apron.ml @@ -13,8 +13,6 @@ open Pretty module M = Messages open GobApron -open ConvenienceOps - module Mpqf = SharedFunctions.Mpqf module Rhs = struct @@ -372,7 +370,7 @@ end module D = struct include Printable.Std - include ConvenienceOps (Mpqf) + include RatOps.ConvenienceOps (Mpqf) include VarManagement module Bounds = ExpressionBounds diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 8e7a63a07f..23f2949fcb 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -444,7 +444,6 @@ module ArrayMatrix = ArrayMatrix module SparseVector = SparseVector module ListMatrix = ListMatrix module RatOps = RatOps -module ConvenienceOps = ConvenienceOps module SharedFunctions = SharedFunctions module GobApron = GobApron diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml index 3d27ba582b..d1532c2e59 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml @@ -6,12 +6,11 @@ open Goblint_lib open OUnit2 open SparseVector open ListMatrix -open ConvenienceOps module D = SharedFunctions.Mpqf module Vector = SparseVector (D) module Matrix = ListMatrix (D) (SparseVector) -include ConvenienceOps(D) +include RatOps.ConvenienceOps(D) (** Shorthands for common functions. *) let int x = D.of_int x From f86845af38837ac3d71680a7b3682c922cd76aa8 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Tue, 18 Feb 2025 20:05:23 +0100 Subject: [PATCH 226/240] Removed unnecessary Batteries assignments --- .../affineEquality/arrayImplementation/arrayMatrix.ml | 1 - .../affineEquality/arrayImplementation/arrayVector.ml | 2 -- .../affineEquality/sparseImplementation/listMatrix.ml | 5 ++--- .../affineEquality/sparseImplementation/sparseVector.ml | 4 ---- src/cdomains/apron/affineEqualityDomain.apron.ml | 1 - src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml | 1 - 6 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 07495025d6..e349592eab 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -4,7 +4,6 @@ open MatrixFunctor open RatOps open Batteries -module Array = Batteries.Array (** Array-based matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index b0422567fd..a57df338f6 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -2,8 +2,6 @@ open VectorFunctor open RatOps open Batteries -module Array = Batteries.Array - (** Array-based vector implementation. *) module ArrayVector: ArrayVectorFunctor = diff --git a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml index 61828de384..39c833d9b3 100644 --- a/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml +++ b/src/cdomains/affineEquality/sparseImplementation/listMatrix.ml @@ -2,8 +2,7 @@ open MatrixFunctor open VectorFunctor open RatOps -open BatList -module List = BatList +open Batteries (** Matrix implementation that uses a list of (ideally sparse) vectors representing its rows. It provides a normalization function to reduce a matrix into reduced row echelon form. @@ -36,7 +35,7 @@ module ListMatrix: SparseMatrixFunctor = let compare_num_rows = List.compare_lengths let num_cols m = - if m = [] then 0 else V.length (hd m) + if m = [] then 0 else V.length (List.hd m) let init_with_vec v = [v] diff --git a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml index 736c968e2f..cf56b8469d 100644 --- a/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml +++ b/src/cdomains/affineEquality/sparseImplementation/sparseVector.ml @@ -1,12 +1,8 @@ open VectorFunctor open RatOps -open BatList open Batteries -module List = BatList -module Array = BatArray - module SparseVector: SparseVectorFunctor = functor (A: RatOps) -> struct diff --git a/src/cdomains/apron/affineEqualityDomain.apron.ml b/src/cdomains/apron/affineEqualityDomain.apron.ml index b02ee9e6cd..03b504b7a1 100644 --- a/src/cdomains/apron/affineEqualityDomain.apron.ml +++ b/src/cdomains/apron/affineEqualityDomain.apron.ml @@ -18,7 +18,6 @@ open VectorFunctor open MatrixFunctor open Batteries -module Array = Batteries.Array module Mpqf = SharedFunctions.Mpqf diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml index 5e1a687e08..f0efcb6caf 100644 --- a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -17,7 +17,6 @@ open VectorFunctor open MatrixFunctor open Batteries -module Array = BatArray module Mpqf = SharedFunctions.Mpqf From 0bbba47d602317505bcffa583ba3b57964a105f2 Mon Sep 17 00:00:00 2001 From: Charlotte Brandt Date: Thu, 20 Feb 2025 09:46:17 +0100 Subject: [PATCH 227/240] Remove unnecessary rename of Array --- src/cdomains/affineEquality/arrayImplementation/arrayVector.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml index 1dffc6b3ec..59d75a0bfe 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayVector.ml @@ -2,7 +2,6 @@ open Vector open RatOps open Batteries -module Array = Batteries.Array module type ArrayVector = sig From b6fc2d09457359f256c75f8cfac49af5e04113b9 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 21 Feb 2025 15:39:10 +0100 Subject: [PATCH 228/240] Add Apron and No-Apron test for sparseMatrix --- tests/unit/dune | 9 +++++++-- ...est.ml => sparseMatrixImplementationTest.apron.ml} | 2 +- tests/unit/sparseMatrixImplementationTest.no-apron.ml | 11 +++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) rename tests/unit/{cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml => sparseMatrixImplementationTest.apron.ml} (99%) create mode 100644 tests/unit/sparseMatrixImplementationTest.no-apron.ml diff --git a/tests/unit/dune b/tests/unit/dune index 07c87e7822..6349239c6e 100644 --- a/tests/unit/dune +++ b/tests/unit/dune @@ -2,7 +2,12 @@ (test (name mainTest) - (libraries ounit2 qcheck-ounit goblint.std goblint.common goblint.lib goblint.constraint goblint.solver goblint.cdomain.value) + (libraries ounit2 qcheck-ounit goblint.std goblint.common goblint.lib goblint.constraint goblint.solver goblint.cdomain.value + (select sparseMatrixImplementationTest.ml from + (apron -> sparseMatrixImplementationTest.apron.ml) + (-> sparseMatrixImplementationTest.no-apron.ml) + ) + ) (preprocess (pps ppx_deriving.std ppx_deriving_hash ppx_deriving_yojson)) (flags :standard -linkall)) @@ -10,4 +15,4 @@ (dev (flags (:standard -warn-error -A -w -unused-var-strict)) ; https://dune.readthedocs.io/en/stable/faq.html#how-to-make-warnings-non-fatal ) -) +) \ No newline at end of file diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml b/tests/unit/sparseMatrixImplementationTest.apron.ml similarity index 99% rename from tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml rename to tests/unit/sparseMatrixImplementationTest.apron.ml index d1532c2e59..6c66655971 100644 --- a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.ml +++ b/tests/unit/sparseMatrixImplementationTest.apron.ml @@ -345,7 +345,7 @@ let get_col_upper_triangular _ = assert_equal expected result let test () = - "SparseMatrixImplementationTest" + "SparseMatrixImplementationTest-Apron" >::: [ "can solve a standard normalization" >:: standard_normalize; "does sort already reduzed" >:: does_just_sort; diff --git a/tests/unit/sparseMatrixImplementationTest.no-apron.ml b/tests/unit/sparseMatrixImplementationTest.no-apron.ml new file mode 100644 index 0000000000..99f80c8931 --- /dev/null +++ b/tests/unit/sparseMatrixImplementationTest.no-apron.ml @@ -0,0 +1,11 @@ +open OUnit2 + +(* Note: + There are currently no tests independent of apron. + The .apron tests use apron's Mpqf module as an implementation of RatOps. + There are currently no other RatOps implementations, so this file is empty. +*) +let test () = + "SparseMatrixImplementationTest-No-Apron" + >::: [ + ] \ No newline at end of file From a8e1987bcf5f1558adc6231059e4afbae75bb9d1 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Fri, 21 Feb 2025 15:45:45 +0100 Subject: [PATCH 229/240] Update dead link to dune alternative dependencies --- src/dune | 2 +- tests/unit/dune | 2 ++ tests/unit/sparseMatrixImplementationTest.no-apron.ml | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dune b/src/dune index 5d3259347c..2c3a2f9cf5 100644 --- a/src/dune +++ b/src/dune @@ -10,7 +10,7 @@ (libraries goblint.sites goblint.build-info goblint-cil goblint-cil.pta goblint-cil.syntacticsearch batteries.unthreaded qcheck-core.runner sha json-data-encoding jsonrpc cpu arg-complete fpath yaml yaml.unix uuidm goblint_timing catapult goblint_backtrace fileutils goblint_std goblint_config goblint_common goblint_domain goblint_constraint goblint_solver goblint_library goblint_cdomain_value goblint_incremental goblint_tracing goblint_logs ; Conditionally compile based on whether apron optional dependency is installed or not. ; Alternative dependencies seem like the only way to optionally depend on optional dependencies. - ; See: https://dune.readthedocs.io/en/stable/concepts.html#alternative-dependencies. + ; See: https://dune.readthedocs.io/en/stable/reference/library-dependencies.html#alternative-dependencies (select gobApron.ml from (apron -> gobApron.apron.ml) (-> gobApron.no-apron.ml) diff --git a/tests/unit/dune b/tests/unit/dune index 6349239c6e..98a4d8a38a 100644 --- a/tests/unit/dune +++ b/tests/unit/dune @@ -3,6 +3,8 @@ (test (name mainTest) (libraries ounit2 qcheck-ounit goblint.std goblint.common goblint.lib goblint.constraint goblint.solver goblint.cdomain.value + ; Conditionally compile based on whether apron optional dependency is installed or not. + ; See: https://dune.readthedocs.io/en/stable/reference/library-dependencies.html#alternative-dependencies (select sparseMatrixImplementationTest.ml from (apron -> sparseMatrixImplementationTest.apron.ml) (-> sparseMatrixImplementationTest.no-apron.ml) diff --git a/tests/unit/sparseMatrixImplementationTest.no-apron.ml b/tests/unit/sparseMatrixImplementationTest.no-apron.ml index 99f80c8931..b50ad787bc 100644 --- a/tests/unit/sparseMatrixImplementationTest.no-apron.ml +++ b/tests/unit/sparseMatrixImplementationTest.no-apron.ml @@ -1,9 +1,9 @@ open OUnit2 (* Note: - There are currently no tests independent of apron. - The .apron tests use apron's Mpqf module as an implementation of RatOps. - There are currently no other RatOps implementations, so this file is empty. + There are currently no tests independent of apron. + The .apron tests use apron's Mpqf module as an implementation of RatOps. + There are currently no other RatOps implementations, so this file is empty. *) let test () = "SparseMatrixImplementationTest-No-Apron" From 3efe923f087f9977c0102f97b770e0abcc53666e Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Sat, 22 Feb 2025 09:47:59 +0100 Subject: [PATCH 230/240] Add option for affeq side effect analysis --- .../apron/affineEqualityAnalysis.apron.ml | 22 ++++++++++++++----- src/config/options.schema.json | 13 +++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index 6e32e23145..867bc407c9 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -7,17 +7,27 @@ open Analyses open SparseVector open ListMatrix -(* To use the original affineEqualityDomain implementation uncomment this and the AD_Array. - Then replace AD with AD_Array in the functor application. - open ArrayVector - open ArrayMatrix *) +open ArrayVector +open ArrayMatrix include RelationAnalysis +(* There are two versions of the affeq domain. + 1. Sparse without side effects + 2. Array with side effects + Default: sparse implementation + The array implementation with side effects of the affeq domain is used when the --enable ana.affeq.side_effects option is set *) +let get_domain: (module RelationDomain.RD) Lazy.t = + lazy ( + if GobConfig.get_bool "ana.affeq.side_effects" then + (module AffineEqualityDomainSideEffects.D2 (ArrayVector) (ArrayMatrix)) + else + (module AffineEqualityDomain.D2 (SparseVector) (ListMatrix)) + ) + let spec_module: (module MCPSpec) Lazy.t = lazy ( - let module AD = AffineEqualityDomain.D2 (SparseVector) (ListMatrix) in - (* let module AD_Array = AffineEqualityDomainSideEffects.D2 (ArrayVector) (ArrayMatrix) in *) + let module AD = (val Lazy.force get_domain) in let module Priv = (val RelationPriv.get_priv ()) in let module Spec = struct diff --git a/src/config/options.schema.json b/src/config/options.schema.json index 39c863ad49..a0aacb6b50 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -1198,6 +1198,19 @@ } }, "additionalProperties": false + }, + "affeq": { + "title": "ana.affeq", + "type": "object", + "properties": { + "side_effects": { + "title": "ana.affeq.side_effects", + "description": "Use side effect Affine Equality analysis (array implementation). Default is false (sparse implementation)", + "type": "boolean", + "default": false + } + }, + "additionalProperties": false } }, "additionalProperties": false From 3d1b1520370f134af96b1a5ec31713863f261017 Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Mon, 24 Feb 2025 19:40:05 +0200 Subject: [PATCH 231/240] Bump minimum dune version to 3.13 Fixes dune issue: https://github.com/ocaml/dune/issues/9365. --- dune-project | 2 +- goblint.opam | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dune-project b/dune-project index 9a1d958484..7209a18f9b 100644 --- a/dune-project +++ b/dune-project @@ -1,4 +1,4 @@ -(lang dune 3.7) +(lang dune 3.13) (using dune_site 0.1) (cram enable) (name goblint) diff --git a/goblint.opam b/goblint.opam index b0d2575efc..4322e1f740 100644 --- a/goblint.opam +++ b/goblint.opam @@ -35,7 +35,7 @@ homepage: "https://goblint.in.tum.de" doc: "https://goblint.readthedocs.io/en/latest/" bug-reports: "https://github.com/goblint/analyzer/issues" depends: [ - "dune" {>= "3.7"} + "dune" {>= "3.13"} "ocaml" {>= "4.14"} "goblint-cil" {>= "2.0.5"} "batteries" {>= "3.5.1"} From bceccd4b8e68607d6478254459c78247ca76e76b Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Mon, 24 Feb 2025 21:40:41 +0100 Subject: [PATCH 232/240] Move affeq tests back to subdir and avoid cyclic dependencies with dune file --- tests/unit/cdomains/affineEqualityDomain/dune | 3 + .../sparseMatrixImplementationTest.apron.ml | 371 ++++++++++++++++++ ...sparseMatrixImplementationTest.no-apron.ml | 11 + 3 files changed, 385 insertions(+) create mode 100644 tests/unit/cdomains/affineEqualityDomain/dune create mode 100644 tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.apron.ml create mode 100644 tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.no-apron.ml diff --git a/tests/unit/cdomains/affineEqualityDomain/dune b/tests/unit/cdomains/affineEqualityDomain/dune new file mode 100644 index 0000000000..acf9e69fbf --- /dev/null +++ b/tests/unit/cdomains/affineEqualityDomain/dune @@ -0,0 +1,3 @@ +; Workaround for workaround for alternative dependencies with unqualified subdirs. +; copy_files causes "dependency cycle that does not involve any files" otherwise +(include_subdirs no) \ No newline at end of file diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.apron.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.apron.ml new file mode 100644 index 0000000000..6c66655971 --- /dev/null +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.apron.ml @@ -0,0 +1,371 @@ +(* + To run this (and all other unit tests), type `dune runtest tests/unit/`. +*) + +open Goblint_lib +open OUnit2 +open SparseVector +open ListMatrix + +module D = SharedFunctions.Mpqf +module Vector = SparseVector (D) +module Matrix = ListMatrix (D) (SparseVector) +include RatOps.ConvenienceOps(D) + +(** Shorthands for common functions. *) +let int x = D.of_int x + +let frac numerator denominator = D.of_frac numerator denominator + +(** Shorthands for common functions. *) +let float x = D.of_float x + +let make_matrix_of_2d_list l = + List.fold_left + (fun acc row -> Matrix.append_row acc (Vector.of_list row)) + (Matrix.empty ()) + l + +(** This function runs the equality assertion with the solution after normalizing the matrix. *) +let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = + let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in + let do_dimensions_match (r1, c1) (r2, c2) = r1 = r2 && c1 = c2 in + let matrix_dim = get_dimensions matrix in + let solution_dim = get_dimensions solution in + if not (do_dimensions_match solution_dim matrix_dim) then + failwith + "The matrix to normalize and the solution have different dimensions!" + else + match Matrix.normalize matrix with + | None -> assert_failure "The normalization returned None." + | Some reduced_matrix -> assert_equal reduced_matrix solution + +(** + Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) + but extended by a solution vector b = [0;0;25]^T. +*) +let standard_normalize _ = + let width = 5 in + let any_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width + [ (0, int 2); (2, int 4); (3, int (-1)) ])) + (Vector.of_sparse_list width [ (0, int 2); (1, int 3); (2, int 4) ])) + (Vector.of_sparse_list width + [ (0, int 1); (1, int 1); (2, int 2); (3, int 4); (4, int 25) ]) + in + let normalized_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (2, int 2); (4, int 3) ])) + (Vector.of_sparse_list width [ (1, int 1); (4, int (-2)) ])) + (Vector.of_sparse_list width [ (3, int 1); (4, int 6) ]) + in + normalize_and_assert any_matrix normalized_matrix + +(** + Normalization just sorts the matrix, as the rows are already reduced. +*) +let does_just_sort _ = + let width = 7 in + let chaotic_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (2, int 1) ])) + (Vector.of_sparse_list width [ (5, int 1) ])) + (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) + (Vector.of_sparse_list width [ (1, int 1); (4, int (-3)) ]) + in + + let sorted_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) + (Vector.of_sparse_list width [ (1, int 1); (4, int (-3)) ])) + (Vector.of_sparse_list width [ (2, int 1) ])) + (Vector.of_sparse_list width [ (5, int 1) ]) + in + normalize_and_assert chaotic_matrix sorted_matrix + +(** + Normalization should eliminate both linearly dependent rows. +*) +let does_eliminate_dependent_rows _ = + let width = 3 in + let linearly_dependent_rows = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (2, int 4) ])) + (Vector.of_sparse_list width [ (0, int 2); (2, int 8) ])) + (Vector.of_sparse_list width [ (0, int 3); (2, int 12) ]) + in + + let minimized_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (2, int 4) ])) + (Vector.zero_vec width)) + (Vector.zero_vec width) + in + normalize_and_assert linearly_dependent_rows minimized_matrix + +let does_handle_floats _ = + let width = 3 in + let any_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, float 5.); (2, float (1. /. 2.)) ])) + (Vector.of_sparse_list width + [ (0, float (1. /. 4.)); (1, float 23.); (2, float 2.) ]) + in + + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, float 1.); (2, frac 1 10) ])) + (Vector.of_sparse_list width [ (1, float 1.); (2, frac 79 920) ]) + in + normalize_and_assert any_matrix normalized_matrix + +let does_handle_fractions _ = + let width = 3 in + let any_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, frac 5 1); (2, frac 1 2) ])) + (Vector.of_sparse_list width + [ (0, frac 1 4); (1, frac 23 1); (2, frac 2 1) ]) + in + + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, frac 1 1); (2, frac 1 10) ])) + (Vector.of_sparse_list width [ (1, frac 1 1); (2, frac 79 920) ]) + in + normalize_and_assert any_matrix normalized_matrix + +let does_negate_negative _ = + let width = 5 in + let negative_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int (-1)); (3, int (-3)) ])) + (Vector.of_sparse_list width [ (2, int (-1)); (4, int (-5)) ]) + in + + let negated_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (3, int 3) ])) + (Vector.of_sparse_list width [ (2, int 1); (4, int 5) ]) + in + normalize_and_assert negative_matrix negated_matrix + +(** + Normalization is idempotent. +*) +let does_not_change_normalized_matrix _ = + let width = 5 in + let already_normalized = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) + (Vector.of_sparse_list width [ (1, int 1); (3, int 3) ])) + (Vector.of_sparse_list width [ (2, int 1); (3, int 1) ]) + in + normalize_and_assert already_normalized already_normalized + +let is_covered_by_simple _ = + let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 1; int 2; int 10]) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 1; int 0; int 6])) + (Vector.of_list [int 0; int 0; int 1; int 2]) in + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" result + +let is_covered_by_vector_first_row _ = + let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 2; int 0; int 7]) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 2; int 0; int 7])) + (Vector.of_list [int 0; int 0; int 1; int 2]) in + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" result + +let is_zero_vec_covered _ = + let m1 = Matrix.init_with_vec (Vector.zero_vec 4) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 2; int 0; int 7])) + (Vector.of_list [int 0; int 0; int 1; int 2]) in + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" result + +let is_not_covered _ = + let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 1; int 2; int 10]) in + let m2 = Matrix.append_row + (Matrix.append_row + (Matrix.empty ()) + (Vector.of_list [int 1; int 1; int 0; int 6])) + (Vector.of_list [int 0; int 0; int 1; int 3]) in + let result = Matrix.is_covered_by m2 m1 in + assert_bool "Matrix m1 is not covered by m2, but was true" (not result) + +let is_covered_big _ = + let m1 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int (-1); int 0]; + [int 0; int 1; int 0; int 0; int 0; int (-2); int 0]; + [int 0; int 0; int 1; (frac (-1) 3); frac 1 3; int 0; frac 1 3]] in + + let m2 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 0; int 1; frac (-1) 3; frac 1 3; int 0; frac 1 3]; + [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in + + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" (result) + +let is_covered_big2 _ = + let m1 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 1; int 0] + ] in + + let m2 = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in + + let result = Matrix.is_covered_by m1 m2 in + assert_bool "Matrix m1 is covered by m2, but was false" (result) +(** + Normalization works on an empty matrix. +*) +let normalize_empty _ = + let width = 3 in + let empty_matrix = + Matrix.append_row + (Matrix.append_row + (Matrix.append_row (Matrix.empty ()) (Vector.zero_vec width)) + (Vector.zero_vec width)) + (Vector.zero_vec width) + in + normalize_and_assert empty_matrix empty_matrix + +let normalize_two_columns _ = + let width = 2 in + let two_col_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 3); (1, int 2) ])) + (Vector.of_sparse_list width [ (0, int 9); (1, int 6) ]) + in + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width + [ (0, int 1); (1, D.div (int 2) (int 3)) ])) + (Vector.of_sparse_list width []) + in + normalize_and_assert two_col_matrix normalized_matrix + +let int_domain_to_rational _ = + let width = 3 in + let int_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width [ (0, int 3); (2, int 1) ])) + (Vector.of_sparse_list width [ (0, int 2); (1, int 1); (2, int 1) ]) + in + let normalized_matrix = + Matrix.append_row + (Matrix.append_row (Matrix.empty ()) + (Vector.of_sparse_list width + [ (0, int 1); (2, D.div (int 1) (int 3)) ])) + (Vector.of_sparse_list width [ (1, int 1); (2, D.div (int 1) (int 3)) ]) + in + normalize_and_assert int_matrix normalized_matrix + + +let vectorMap2i _ = + let v1 = Vector.of_list [int 0; int 1; int 0; int 2; int 3; int 0; int 4; int 0; int 1] in + let v2 = Vector.of_list [int 4; int 0; int 0; int 0; int 5; int 6; int 0; int 0; int 2] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [int 0; int 1; int 0; int 6; int 32; int 30; int 24; int 0; int 24] in + assert_equal expected result + + +let vectorMap2i_empty _ = + let v1 = Vector.of_list [] in + let v2 = Vector.of_list [] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [] in + assert_equal expected result + +let vectorMap2i_one_zero _ = + let v1 = Vector.of_list [int 0; int 0; int 0; int 0] in + let v2 = Vector.of_list [int 1; int 2; int 3; int 4] in + let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in + let expected = Vector.of_list [int 0; int 2; int 6; int 12] in + assert_equal expected result + + +let vectorMap_zero_preserving_normal _ = + let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 4; int 5; int 0; int 0;] in + let result = Vector.map_f_preserves_zero (fun x -> x *: x) v1 in + let expected = Vector.of_list [int 0; int 1; int 4; int 0; int 0; int 16; int 25; int 0; int 0;] in + assert_equal expected result + + +let get_col_upper_triangular _ = + let m = make_matrix_of_2d_list @@ + [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; + [int 0; int 0; int 1; frac (-1) 3; int 0; frac 1 3; int 1]] in + + let result = Matrix.get_col_upper_triangular m 5 in + + let expected = Vector.of_list [int 0; int 0; frac 1 3] in + + assert_equal expected result + +let test () = + "SparseMatrixImplementationTest-Apron" + >::: [ + "can solve a standard normalization" >:: standard_normalize; + "does sort already reduzed" >:: does_just_sort; + "does eliminate dependent rows" >:: does_eliminate_dependent_rows; + "can handle float domain" >:: does_handle_floats; + "can handle fraction domain" >:: does_handle_fractions; + "does negate negative matrix" >:: does_negate_negative; + "does not change already normalized matrix" >:: does_not_change_normalized_matrix; + "m1 is covered by m2" >:: is_covered_by_simple; + "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; + "zero vector is covered by m2" >:: is_zero_vec_covered; + "m1 is not covered by m2" >:: is_not_covered; + "m1 is covered by m2 with big matrix" >:: is_covered_big; + "does not change an empty matrix" >:: normalize_empty; + "can correctly normalize a two column matrix" >:: normalize_two_columns; + "can handle a rational solution" >:: int_domain_to_rational; + "m1 is covered by m2 with big matrix2" >:: is_covered_big2; + "map2i two vectors" >:: vectorMap2i; + "map2i two empty vectors" >:: vectorMap2i_empty; + "map2i one zero vector" >:: vectorMap2i_one_zero; + "map zero preserving normal" >:: vectorMap_zero_preserving_normal; + "get column when matrix in rref" >:: get_col_upper_triangular; + ] \ No newline at end of file diff --git a/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.no-apron.ml b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.no-apron.ml new file mode 100644 index 0000000000..b50ad787bc --- /dev/null +++ b/tests/unit/cdomains/affineEqualityDomain/sparseImplementation/sparseMatrixImplementationTest.no-apron.ml @@ -0,0 +1,11 @@ +open OUnit2 + +(* Note: + There are currently no tests independent of apron. + The .apron tests use apron's Mpqf module as an implementation of RatOps. + There are currently no other RatOps implementations, so this file is empty. +*) +let test () = + "SparseMatrixImplementationTest-No-Apron" + >::: [ + ] \ No newline at end of file From 6fa6c92715baec5673c5a7a2849f8a2b8f50c490 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 25 Feb 2025 10:25:39 +0100 Subject: [PATCH 233/240] Remove old affeq test files --- .../sparseMatrixImplementationTest.apron.ml | 371 ------------------ ...sparseMatrixImplementationTest.no-apron.ml | 11 - 2 files changed, 382 deletions(-) delete mode 100644 tests/unit/sparseMatrixImplementationTest.apron.ml delete mode 100644 tests/unit/sparseMatrixImplementationTest.no-apron.ml diff --git a/tests/unit/sparseMatrixImplementationTest.apron.ml b/tests/unit/sparseMatrixImplementationTest.apron.ml deleted file mode 100644 index 6c66655971..0000000000 --- a/tests/unit/sparseMatrixImplementationTest.apron.ml +++ /dev/null @@ -1,371 +0,0 @@ -(* - To run this (and all other unit tests), type `dune runtest tests/unit/`. -*) - -open Goblint_lib -open OUnit2 -open SparseVector -open ListMatrix - -module D = SharedFunctions.Mpqf -module Vector = SparseVector (D) -module Matrix = ListMatrix (D) (SparseVector) -include RatOps.ConvenienceOps(D) - -(** Shorthands for common functions. *) -let int x = D.of_int x - -let frac numerator denominator = D.of_frac numerator denominator - -(** Shorthands for common functions. *) -let float x = D.of_float x - -let make_matrix_of_2d_list l = - List.fold_left - (fun acc row -> Matrix.append_row acc (Vector.of_list row)) - (Matrix.empty ()) - l - -(** This function runs the equality assertion with the solution after normalizing the matrix. *) -let normalize_and_assert (matrix : Matrix.t) (solution : Matrix.t) = - let get_dimensions m = (Matrix.num_rows m, Matrix.num_cols m) in - let do_dimensions_match (r1, c1) (r2, c2) = r1 = r2 && c1 = c2 in - let matrix_dim = get_dimensions matrix in - let solution_dim = get_dimensions solution in - if not (do_dimensions_match solution_dim matrix_dim) then - failwith - "The matrix to normalize and the solution have different dimensions!" - else - match Matrix.normalize matrix with - | None -> assert_failure "The normalization returned None." - | Some reduced_matrix -> assert_equal reduced_matrix solution - -(** - Example from a [Youtube video](https://www.youtube.com/watch?v=TYs4h-AoqyQ) - but extended by a solution vector b = [0;0;25]^T. -*) -let standard_normalize _ = - let width = 5 in - let any_matrix = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width - [ (0, int 2); (2, int 4); (3, int (-1)) ])) - (Vector.of_sparse_list width [ (0, int 2); (1, int 3); (2, int 4) ])) - (Vector.of_sparse_list width - [ (0, int 1); (1, int 1); (2, int 2); (3, int 4); (4, int 25) ]) - in - let normalized_matrix = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 1); (2, int 2); (4, int 3) ])) - (Vector.of_sparse_list width [ (1, int 1); (4, int (-2)) ])) - (Vector.of_sparse_list width [ (3, int 1); (4, int 6) ]) - in - normalize_and_assert any_matrix normalized_matrix - -(** - Normalization just sorts the matrix, as the rows are already reduced. -*) -let does_just_sort _ = - let width = 7 in - let chaotic_matrix = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (2, int 1) ])) - (Vector.of_sparse_list width [ (5, int 1) ])) - (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) - (Vector.of_sparse_list width [ (1, int 1); (4, int (-3)) ]) - in - - let sorted_matrix = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) - (Vector.of_sparse_list width [ (1, int 1); (4, int (-3)) ])) - (Vector.of_sparse_list width [ (2, int 1) ])) - (Vector.of_sparse_list width [ (5, int 1) ]) - in - normalize_and_assert chaotic_matrix sorted_matrix - -(** - Normalization should eliminate both linearly dependent rows. -*) -let does_eliminate_dependent_rows _ = - let width = 3 in - let linearly_dependent_rows = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 1); (2, int 4) ])) - (Vector.of_sparse_list width [ (0, int 2); (2, int 8) ])) - (Vector.of_sparse_list width [ (0, int 3); (2, int 12) ]) - in - - let minimized_matrix = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 1); (2, int 4) ])) - (Vector.zero_vec width)) - (Vector.zero_vec width) - in - normalize_and_assert linearly_dependent_rows minimized_matrix - -let does_handle_floats _ = - let width = 3 in - let any_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, float 5.); (2, float (1. /. 2.)) ])) - (Vector.of_sparse_list width - [ (0, float (1. /. 4.)); (1, float 23.); (2, float 2.) ]) - in - - let normalized_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, float 1.); (2, frac 1 10) ])) - (Vector.of_sparse_list width [ (1, float 1.); (2, frac 79 920) ]) - in - normalize_and_assert any_matrix normalized_matrix - -let does_handle_fractions _ = - let width = 3 in - let any_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, frac 5 1); (2, frac 1 2) ])) - (Vector.of_sparse_list width - [ (0, frac 1 4); (1, frac 23 1); (2, frac 2 1) ]) - in - - let normalized_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, frac 1 1); (2, frac 1 10) ])) - (Vector.of_sparse_list width [ (1, frac 1 1); (2, frac 79 920) ]) - in - normalize_and_assert any_matrix normalized_matrix - -let does_negate_negative _ = - let width = 5 in - let negative_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int (-1)); (3, int (-3)) ])) - (Vector.of_sparse_list width [ (2, int (-1)); (4, int (-5)) ]) - in - - let negated_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 1); (3, int 3) ])) - (Vector.of_sparse_list width [ (2, int 1); (4, int 5) ]) - in - normalize_and_assert negative_matrix negated_matrix - -(** - Normalization is idempotent. -*) -let does_not_change_normalized_matrix _ = - let width = 5 in - let already_normalized = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 1); (3, int 1) ])) - (Vector.of_sparse_list width [ (1, int 1); (3, int 3) ])) - (Vector.of_sparse_list width [ (2, int 1); (3, int 1) ]) - in - normalize_and_assert already_normalized already_normalized - -let is_covered_by_simple _ = - let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 1; int 2; int 10]) in - let m2 = Matrix.append_row - (Matrix.append_row - (Matrix.empty ()) - (Vector.of_list [int 1; int 1; int 0; int 6])) - (Vector.of_list [int 0; int 0; int 1; int 2]) in - let result = Matrix.is_covered_by m1 m2 in - assert_bool "Matrix m1 is covered by m2, but was false" result - -let is_covered_by_vector_first_row _ = - let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 2; int 0; int 7]) in - let m2 = Matrix.append_row - (Matrix.append_row - (Matrix.empty ()) - (Vector.of_list [int 1; int 2; int 0; int 7])) - (Vector.of_list [int 0; int 0; int 1; int 2]) in - let result = Matrix.is_covered_by m1 m2 in - assert_bool "Matrix m1 is covered by m2, but was false" result - -let is_zero_vec_covered _ = - let m1 = Matrix.init_with_vec (Vector.zero_vec 4) in - let m2 = Matrix.append_row - (Matrix.append_row - (Matrix.empty ()) - (Vector.of_list [int 1; int 2; int 0; int 7])) - (Vector.of_list [int 0; int 0; int 1; int 2]) in - let result = Matrix.is_covered_by m1 m2 in - assert_bool "Matrix m1 is covered by m2, but was false" result - -let is_not_covered _ = - let m1 = Matrix.init_with_vec (Vector.of_list [int 1; int 1; int 2; int 10]) in - let m2 = Matrix.append_row - (Matrix.append_row - (Matrix.empty ()) - (Vector.of_list [int 1; int 1; int 0; int 6])) - (Vector.of_list [int 0; int 0; int 1; int 3]) in - let result = Matrix.is_covered_by m2 m1 in - assert_bool "Matrix m1 is not covered by m2, but was true" (not result) - -let is_covered_big _ = - let m1 = make_matrix_of_2d_list @@ - [[int 1; int 0; int 0; int 0; int 0; int (-1); int 0]; - [int 0; int 1; int 0; int 0; int 0; int (-2); int 0]; - [int 0; int 0; int 1; (frac (-1) 3); frac 1 3; int 0; frac 1 3]] in - - let m2 = make_matrix_of_2d_list @@ - [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; - [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; - [int 0; int 0; int 1; frac (-1) 3; frac 1 3; int 0; frac 1 3]; - [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in - - let result = Matrix.is_covered_by m1 m2 in - assert_bool "Matrix m1 is covered by m2, but was false" (result) - -let is_covered_big2 _ = - let m1 = make_matrix_of_2d_list @@ - [[int 1; int 0; int 0; int 0; int 0; int 1; int 0] - ] in - - let m2 = make_matrix_of_2d_list @@ - [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; - [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; - [int 0; int 0; int 0; int 0; int 0; int 1; int 0]] in - - let result = Matrix.is_covered_by m1 m2 in - assert_bool "Matrix m1 is covered by m2, but was false" (result) -(** - Normalization works on an empty matrix. -*) -let normalize_empty _ = - let width = 3 in - let empty_matrix = - Matrix.append_row - (Matrix.append_row - (Matrix.append_row (Matrix.empty ()) (Vector.zero_vec width)) - (Vector.zero_vec width)) - (Vector.zero_vec width) - in - normalize_and_assert empty_matrix empty_matrix - -let normalize_two_columns _ = - let width = 2 in - let two_col_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 3); (1, int 2) ])) - (Vector.of_sparse_list width [ (0, int 9); (1, int 6) ]) - in - let normalized_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width - [ (0, int 1); (1, D.div (int 2) (int 3)) ])) - (Vector.of_sparse_list width []) - in - normalize_and_assert two_col_matrix normalized_matrix - -let int_domain_to_rational _ = - let width = 3 in - let int_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width [ (0, int 3); (2, int 1) ])) - (Vector.of_sparse_list width [ (0, int 2); (1, int 1); (2, int 1) ]) - in - let normalized_matrix = - Matrix.append_row - (Matrix.append_row (Matrix.empty ()) - (Vector.of_sparse_list width - [ (0, int 1); (2, D.div (int 1) (int 3)) ])) - (Vector.of_sparse_list width [ (1, int 1); (2, D.div (int 1) (int 3)) ]) - in - normalize_and_assert int_matrix normalized_matrix - - -let vectorMap2i _ = - let v1 = Vector.of_list [int 0; int 1; int 0; int 2; int 3; int 0; int 4; int 0; int 1] in - let v2 = Vector.of_list [int 4; int 0; int 0; int 0; int 5; int 6; int 0; int 0; int 2] in - let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in - let expected = Vector.of_list [int 0; int 1; int 0; int 6; int 32; int 30; int 24; int 0; int 24] in - assert_equal expected result - - -let vectorMap2i_empty _ = - let v1 = Vector.of_list [] in - let v2 = Vector.of_list [] in - let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in - let expected = Vector.of_list [] in - assert_equal expected result - -let vectorMap2i_one_zero _ = - let v1 = Vector.of_list [int 0; int 0; int 0; int 0] in - let v2 = Vector.of_list [int 1; int 2; int 3; int 4] in - let result = Vector.map2i (fun i x y -> (int i) *: (x +: y)) v1 v2 in - let expected = Vector.of_list [int 0; int 2; int 6; int 12] in - assert_equal expected result - - -let vectorMap_zero_preserving_normal _ = - let v1 = Vector.of_list [int 0; int 1; int 2; int 0; int 0; int 4; int 5; int 0; int 0;] in - let result = Vector.map_f_preserves_zero (fun x -> x *: x) v1 in - let expected = Vector.of_list [int 0; int 1; int 4; int 0; int 0; int 16; int 25; int 0; int 0;] in - assert_equal expected result - - -let get_col_upper_triangular _ = - let m = make_matrix_of_2d_list @@ - [[int 1; int 0; int 0; int 0; int 0; int 0; int 0]; - [int 0; int 1; int 0; int 0; int 0; int 0; int 0]; - [int 0; int 0; int 1; frac (-1) 3; int 0; frac 1 3; int 1]] in - - let result = Matrix.get_col_upper_triangular m 5 in - - let expected = Vector.of_list [int 0; int 0; frac 1 3] in - - assert_equal expected result - -let test () = - "SparseMatrixImplementationTest-Apron" - >::: [ - "can solve a standard normalization" >:: standard_normalize; - "does sort already reduzed" >:: does_just_sort; - "does eliminate dependent rows" >:: does_eliminate_dependent_rows; - "can handle float domain" >:: does_handle_floats; - "can handle fraction domain" >:: does_handle_fractions; - "does negate negative matrix" >:: does_negate_negative; - "does not change already normalized matrix" >:: does_not_change_normalized_matrix; - "m1 is covered by m2" >:: is_covered_by_simple; - "m1 is covered by m2 with vector in first row" >:: is_covered_by_vector_first_row; - "zero vector is covered by m2" >:: is_zero_vec_covered; - "m1 is not covered by m2" >:: is_not_covered; - "m1 is covered by m2 with big matrix" >:: is_covered_big; - "does not change an empty matrix" >:: normalize_empty; - "can correctly normalize a two column matrix" >:: normalize_two_columns; - "can handle a rational solution" >:: int_domain_to_rational; - "m1 is covered by m2 with big matrix2" >:: is_covered_big2; - "map2i two vectors" >:: vectorMap2i; - "map2i two empty vectors" >:: vectorMap2i_empty; - "map2i one zero vector" >:: vectorMap2i_one_zero; - "map zero preserving normal" >:: vectorMap_zero_preserving_normal; - "get column when matrix in rref" >:: get_col_upper_triangular; - ] \ No newline at end of file diff --git a/tests/unit/sparseMatrixImplementationTest.no-apron.ml b/tests/unit/sparseMatrixImplementationTest.no-apron.ml deleted file mode 100644 index b50ad787bc..0000000000 --- a/tests/unit/sparseMatrixImplementationTest.no-apron.ml +++ /dev/null @@ -1,11 +0,0 @@ -open OUnit2 - -(* Note: - There are currently no tests independent of apron. - The .apron tests use apron's Mpqf module as an implementation of RatOps. - There are currently no other RatOps implementations, so this file is empty. -*) -let test () = - "SparseMatrixImplementationTest-No-Apron" - >::: [ - ] \ No newline at end of file From 514ffcbbe162c48e08c1d8ceb247bbcc06b99c25 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 25 Feb 2025 10:28:24 +0100 Subject: [PATCH 234/240] Add copy_files stanzas to affeq-test dune --- tests/unit/dune | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/unit/dune b/tests/unit/dune index 98a4d8a38a..85038e1da6 100644 --- a/tests/unit/dune +++ b/tests/unit/dune @@ -17,4 +17,10 @@ (dev (flags (:standard -warn-error -A -w -unused-var-strict)) ; https://dune.readthedocs.io/en/stable/faq.html#how-to-make-warnings-non-fatal ) -) \ No newline at end of file +) + +; Workaround for alternative dependencies with unqualified subdirs. +; See: https://github.com/ocaml/dune/issues/4383#issuecomment-805107435. +; TODO: Remove workaround with dune 3.0, where this should get fixed. +; A dune file with "include_subdirs no" is located in cdomains/affineEqualityDomain to avoid a dependency cycle +(copy_files# cdomains/affineEqualityDomain/sparseImplementation/*.ml) \ No newline at end of file From 65d0c12e4a9595b9062a7e91a3e7a68c6a7da657 Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 25 Feb 2025 19:06:11 +0100 Subject: [PATCH 235/240] replaced term "side effects" with alternative description of function behaviour --- conf.json | 146 +++++++++++ rref_vec_new_no_filter_baliktad.txt | 1 + .../arrayImplementation/arrayMatrix.ml | 7 +- .../affineEqualityDomainSideEffects.apron.ml | 2 +- test6new.txt | 237 ++++++++++++++++++ 5 files changed, 389 insertions(+), 4 deletions(-) create mode 100644 conf.json create mode 100644 rref_vec_new_no_filter_baliktad.txt create mode 100644 test6new.txt diff --git a/conf.json b/conf.json new file mode 100644 index 0000000000..8c7335417e --- /dev/null +++ b/conf.json @@ -0,0 +1,146 @@ +{ + "ana": { + "sv-comp": { + "enabled": true, + "functions": true + }, + "int": { + "def_exc": true, + "enums": false, + "interval": true + }, + "float": { + "interval": true + }, + "activated": [ + "base", + "threadid", + "threadflag", + "threadreturn", + "mallocWrapper", + "mutexEvents", + "mutex", + "access", + "race", + "escape", + "expRelation", + "mhp", + "assert", + "var_eq", + "symb_locks", + "region", + "thread", + "threadJoins", + "affeq" + ], + "path_sens": [ + "mutex", + "malloc_null", + "uninit", + "expsplit", + "activeSetjmp", + "memLeak", + "threadflag" + ], + "context": { + "widen": false + }, + "malloc": { + "wrappers": [ + "kmalloc", + "__kmalloc", + "usb_alloc_urb", + "__builtin_alloca", + "kzalloc", + + "ldv_malloc", + + "kzalloc_node", + "ldv_zalloc", + "kmalloc_array", + "kcalloc", + + "ldv_xmalloc", + "ldv_xzalloc", + "ldv_calloc", + "ldv_kzalloc" + ] + }, + "base": { + "arrays": { + "domain": "partitioned" + } + }, + "race": { + "free": false, + "call": false + }, + "autotune": { + "enabled": true, + "activated": [ + "singleThreaded", + "mallocWrappers", + "noRecursiveIntervals", + "enums", + "congruence", + "wideningThresholds", + "loopUnrollHeuristic", + "memsafetySpecification", + "termination", + "tmpSpecialAnalysis" + ] + } + }, + "exp": { + "region-offsets": true + }, + "solver": "td3", + "sem": { + "unknown_function": { + "spawn": false + }, + "int": { + "signed_overflow": "assume_none" + }, + "null-pointer": { + "dereference": "assume_none" + } + }, + "witness": { + "graphml": { + "enabled": true, + "id": "enumerate", + "unknown": false + }, + "yaml": { + "enabled": true, + "format-version": "2.0", + "entry-types": [ + "invariant_set" + ], + "invariant-types": [ + "loop_invariant" + ] + }, + "invariant": { + "loop-head": true, + "after-lock": false, + "other": false, + "accessed": false, + "exact": true, + "exclude-vars": [ + "tmp\\(___[0-9]+\\)?", + "cond", + "RETURN", + "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", + ".*____CPAchecker_TMP_[0-9]+", + "__VERIFIER_assert__cond", + "__ksymtab_.*", + "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" + ] + } + }, + "pre": { + "enabled": false + } +} \ No newline at end of file diff --git a/rref_vec_new_no_filter_baliktad.txt b/rref_vec_new_no_filter_baliktad.txt new file mode 100644 index 0000000000..43eb20ee91 --- /dev/null +++ b/rref_vec_new_no_filter_baliktad.txt @@ -0,0 +1 @@ +Fatal error: exception Sys_error("conf.json: No such file or diretory") diff --git a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml index 3e6a2a4e03..84771a0a15 100644 --- a/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml +++ b/src/cdomains/affineEquality/arrayImplementation/arrayMatrix.ml @@ -30,7 +30,7 @@ sig val append_matrices: t -> t -> t end -(** Some functions inside have the suffix _with, which means that the function has side effects. *) +(** Some functions inside have the suffix _with, which means that the function is not purely functional. *) module type ArrayMatrixFunctor = functor (A: RatOps) (V: ArrayVectorFunctor) -> sig @@ -40,7 +40,8 @@ module type ArrayMatrixFunctor = (** Array-based matrix implementation. It provides a normalization function to reduce a matrix into reduced row echelon form. Operations exploit that the input matrix/matrices are in reduced row echelon form already. *) -(* The functions that have the suffix _with have side effects and were used in a previous version of the affineEqualityDomain. +(* The functions that have the suffix _with are not purely functional and affect the program state beyond their return value. + They were used in a previous version of the affineEqualityDomain. These calls were removed to transition to list-based matrices.*) module ArrayMatrix: ArrayMatrixFunctor = functor (A: RatOps) (V: ArrayVectorFunctor) -> @@ -180,7 +181,7 @@ module ArrayMatrix: ArrayMatrixFunctor = let del_cols m cols = timing_wrap "del_cols" (del_cols m) cols - (* This does NOT have the same semantics (minus side effects) as map2i_with. While map2i_with can deal with m and v having different lenghts, map2i will raise Invalid_argument in that case*) + (* This does NOT have the same semantics as map2i_with. While map2i_with can deal with m and v having different lenghts, map2i will raise Invalid_argument in that case*) let map2i f m v = let f' x (i,y) = V.to_array @@ f i (V.of_array x) y in let range_array = Array.init (V.length v) Fun.id in diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml index 8b884125b6..dc48e805ad 100644 --- a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml +++ b/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml @@ -3,7 +3,7 @@ @see Karr, M. Affine relationships among variables of a program. *) (** There are two versions of the AffineEqualityDomain. - This version here is based on side effects, thus it uses Matrix and Vector functions marked with "_with" which use side effects. + This version here is based on a dense implementation that is not purely functional, thus it uses Matrix and Vector functions marked with "_with". Abstract states in the newly added domain are represented by structs containing a matrix and an apron environment. Matrices are modeled as proposed by Karr: Each variable is assigned to a column and each row represents a linear affine relationship that must hold at the corresponding program point. The apron environment is hereby used to organize the order of columns and variables. *) diff --git a/test6new.txt b/test6new.txt new file mode 100644 index 0000000000..8484db1f35 --- /dev/null +++ b/test6new.txt @@ -0,0 +1,237 @@ +[Warning] --sets is deprecated, use --set instead. +[Warning] --sets is deprecated, use --set instead. +[Info] unrolling loop at /home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9483:5-9493:5 with factor 4 +[Info] no thread creation -> disabling thread analyses "race, deadlock, maylocks, symb_locks, thread, threadid, threadJoins, threadreturn, mhp, region, pthreadMutexType" +[Info] SV-COMP specification: CHECK( init(main()), LTL(G ! call(reach_error())) ) +[Warning][Deadcode] Function 'reach_error' is uncalled: 1 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:16:1-16:83) +[Warning][Deadcode] Function 'calculate_output' is uncalled: 2123 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:73:2-2247:2) +[Warning][Deadcode] Function 'calculate_output2' is uncalled: 2130 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:2249:2-4428:2) +[Warning][Deadcode] Function 'calculate_output3' is uncalled: 2129 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:4430:2-6614:2) +[Warning][Deadcode] Function 'calculate_output4' is uncalled: 2181 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:6616:2-8864:2) +[Warning][Deadcode] Function 'calculate_output5' is uncalled: 534 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:8866:2-9475:2) +[Warning][Deadcode] Function 'main' has dead code: + on line 9491 (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9491-9491) + on line 9494 (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9494-9494) +[Warning][Deadcode] Logical lines of code (LLoC) summary: + live: 6 + dead: 9100 (9098 in uncalled functions) + total lines: 9106 +[Warning][Deadcode][CWE-571] condition '1' (possibly inserted by CIL) is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9483:11-9483:12) +[Warning][Deadcode][CWE-571] condition 'input != 1' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) +[Warning][Deadcode][CWE-571] condition 'input != 2' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) +[Warning][Deadcode][CWE-571] condition 'input != 3' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) +[Warning][Deadcode][CWE-571] condition 'input != 4' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) +[Warning][Deadcode][CWE-571] condition 'input != 5' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) +[Warning][Deadcode][CWE-571] condition 'input != 6' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) +SV-COMP result: true +[Info][Witness] witness generation summary: + location invariants: 0 + loop invariants: 44 + flow-insensitive invariants: 0 + total generation entries: 1 + +[Info] vars = 65 evals = 94 narrow_reuses = 21 + +[Info] Timings: + cputime walltime allocated count +Default 2.789s 2.800s 577.77MB 1× + preprocess 0.060s 0.056s 0.01MB 1× + FrontC 0.113s 0.114s 74.78MB 4× + Cabs2cil 0.254s 0.254s 93.80MB 4× + mergeCIL 0.018s 0.018s 18.06MB 1× + analysis 1.759s 1.765s 199.94MB 1× + createCFG 1.510s 1.515s 111.35MB 1× + handle 0.182s 0.183s 48.91MB 37× + iter_connect 1.314s 1.318s 57.18MB 37× + computeSCCs 0.105s 0.105s 47.10MB 38× + global_inits 0.017s 0.017s 8.03MB 1× + add_vars 0.003s 0.003s 0.84MB 169× + copy 0.001s 0.001s 0.06MB 169× + dimension change 0.002s 0.002s 0.53MB 169× + dim add 0.001s 0.001s 0.45MB 84× + add_empty_cols 0.001s 0.001s 0.40MB 84× + var_parallel 0.001s 0.001s 0.01MB 1× + add_vars 0.001s 0.001s 0.01MB 2× + copy 0.001s 0.001s 0.01MB 2× + dimension change 0.001s 0.001s 0.01MB 2× + drop_vars 0.001s 0.001s 0.01MB 1× + copy 0.001s 0.001s 0.01MB 1× + dimension change 0.001s 0.001s 0.01MB 1× + normalize 0.001s 0.001s 0.01MB 1× + equal 0.001s 0.001s 0.06MB 43× + assign_texpr 0.007s 0.008s 2.15MB 84× + coeff_vec 0.001s 0.001s 0.10MB 84× + equal 0.001s 0.001s 0.03MB 84× + rref_vec 0.006s 0.006s 1.58MB 84× + find_first_non_zero 0.001s 0.001s 0.03MB 84× + map_f_preserves_zero 0.001s 0.001s 0.06MB 84× + get_pivot_positions 0.005s 0.005s 1.10MB 83× + find_first_non_zero 0.002s 0.004s 0.63MB 1764× + insert_v_according_to_piv 0.001s 0.001s 0.28MB 83× + remove_rels_with_var 0.001s 0.001s 0.04MB 83× + remove_vars 0.003s 0.003s 0.69MB 84× + drop_vars 0.001s 0.001s 0.04MB 84× + copy 0.001s 0.001s 0.03MB 84× + dimension change 0.001s 0.001s 0.48MB 84× + dim remove 0.001s 0.001s 0.44MB 42× + del_cols 0.001s 0.001s 0.23MB 42× + equal 0.001s 0.001s 0.01MB 4× + reachability 0.001s 0.001s 0.01MB 1× + add_vars 0.001s 0.001s 0.01MB 1× + copy 0.001s 0.001s 0.01MB 1× + dimension change 0.001s 0.001s 0.01MB 1× + remove_filter 0.001s 0.001s 0.01MB 1× + dimension change 0.001s 0.001s 0.01MB 1× + solving 0.081s 0.082s 26.54MB 1× + equal 0.001s 0.001s 0.06MB 26× + add_vars 0.001s 0.001s 0.18MB 61× + copy 0.001s 0.001s 0.03MB 61× + dimension change 0.001s 0.001s 0.07MB 61× + dim add 0.001s 0.001s 0.05MB 5× + add_empty_cols 0.001s 0.001s 0.05MB 5× + assert_constraint 0.002s 0.002s 0.54MB 58× + meet_tcons 0.001s 0.001s 0.03MB 56× + coeff_vec 0.001s 0.001s 0.34MB 56× + map_f_preserves_zero 0.001s 0.001s 0.04MB 56× + map2_f_preserves_zero 0.001s 0.001s 0.04MB 56× + to_constant_opt 0.001s 0.001s 0.05MB 56× + find_first_non_zero 0.001s 0.001s 0.02MB 56× + var_parallel 0.030s 0.030s 6.41MB 2× + add_vars 0.001s 0.001s 0.01MB 4× + copy 0.001s 0.001s 0.01MB 4× + dimension change 0.001s 0.001s 0.01MB 4× + drop_vars 0.001s 0.001s 0.01MB 2× + copy 0.001s 0.001s 0.01MB 2× + dimension change 0.001s 0.001s 0.01MB 2× + normalize 0.029s 0.029s 6.39MB 2× + find_first_pivot 0.007s 0.007s 1.04MB 84× + find_first_non_zero 0.002s 0.005s 0.64MB 1806× + map_f_preserves_zero 0.001s 0.001s 0.06MB 84× + map2_f_preserves_zero 0.011s 0.015s 3.23MB 3444× + cut_front_matrix 0.001s 0.001s 0.58MB 84× + find_first_non_zero 0.001s 0.001s 0.03MB 84× + S.Dom.equal 0.001s 0.001s 0.04MB 115× + assign_texpr 0.001s 0.001s 0.18MB 4× + coeff_vec 0.001s 0.001s 0.01MB 4× + equal 0.001s 0.001s 0.01MB 4× + remove_rels_with_var 0.001s 0.001s 0.01MB 4× + rref_vec 0.001s 0.001s 0.14MB 4× + get_pivot_positions 0.001s 0.001s 0.11MB 4× + find_first_non_zero 0.001s 0.001s 0.06MB 170× + find_first_non_zero 0.001s 0.001s 0.01MB 4× + map_f_preserves_zero 0.001s 0.001s 0.01MB 4× + insert_v_according_to_piv 0.001s 0.001s 0.03MB 4× + remove_vars 0.001s 0.001s 0.12MB 21× + drop_vars 0.001s 0.001s 0.01MB 21× + copy 0.001s 0.001s 0.01MB 15× + dimension change 0.001s 0.001s 0.08MB 21× + dim remove 0.001s 0.001s 0.07MB 3× + del_cols 0.001s 0.001s 0.03MB 3× + reachability 0.001s 0.001s 0.01MB 1× + remove_filter 0.001s 0.001s 0.04MB 1× + dimension change 0.001s 0.001s 0.03MB 1× + dim remove 0.001s 0.001s 0.03MB 1× + del_cols 0.001s 0.001s 0.01MB 1× + bounds calculation 0.001s 0.001s 0.08MB 13× + coeff_vec 0.001s 0.001s 0.06MB 13× + to_constant_opt 0.001s 0.001s 0.02MB 13× + find_first_non_zero 0.001s 0.001s 0.01MB 13× + keep_filter 0.001s 0.001s 0.33MB 1× + copy 0.001s 0.001s 0.01MB 1× + dimension change 0.001s 0.001s 0.31MB 1× + dim remove 0.001s 0.001s 0.31MB 1× + del_cols 0.001s 0.001s 0.01MB 1× + meet 0.001s 0.001s 0.06MB 1× + dimension change 0.001s 0.001s 0.02MB 2× + dim add 0.001s 0.001s 0.02MB 1× + add_empty_cols 0.001s 0.001s 0.02MB 1× + equal 0.001s 0.001s 0.01MB 2× + rref_matrix 0.001s 0.001s 0.04MB 1× + rref_vec 0.001s 0.001s 0.04MB 1× + get_pivot_positions 0.001s 0.001s 0.03MB 1× + find_first_non_zero 0.001s 0.001s 0.02MB 42× + find_first_non_zero 0.001s 0.001s 0.01MB 1× + map_f_preserves_zero 0.001s 0.001s 0.01MB 1× + insert_v_according_to_piv 0.001s 0.001s 0.01MB 1× + cheap_full_reach 0.001s 0.001s 0.02MB 1× + postsolver 0.026s 0.026s 11.93MB 1× + postsolver_iter 0.026s 0.026s 11.89MB 1× + equal 0.001s 0.001s 0.09MB 40× + add_vars 0.001s 0.001s 0.18MB 61× + copy 0.001s 0.001s 0.03MB 61× + dimension change 0.001s 0.001s 0.07MB 61× + dim add 0.001s 0.001s 0.05MB 5× + add_empty_cols 0.001s 0.001s 0.05MB 5× + assert_constraint 0.002s 0.002s 0.54MB 58× + meet_tcons 0.001s 0.001s 0.03MB 56× + coeff_vec 0.001s 0.001s 0.34MB 56× + map_f_preserves_zero 0.001s 0.001s 0.04MB 56× + map2_f_preserves_zero 0.001s 0.001s 0.04MB 56× + to_constant_opt 0.001s 0.001s 0.05MB 56× + find_first_non_zero 0.001s 0.001s 0.02MB 56× + var_parallel 0.018s 0.018s 6.41MB 2× + add_vars 0.001s 0.001s 0.01MB 4× + copy 0.001s 0.001s 0.01MB 4× + dimension change 0.001s 0.001s 0.01MB 4× + drop_vars 0.001s 0.001s 0.01MB 2× + copy 0.001s 0.001s 0.01MB 2× + dimension change 0.001s 0.001s 0.01MB 2× + normalize 0.018s 0.018s 6.39MB 2× + find_first_pivot 0.004s 0.005s 1.04MB 84× + find_first_non_zero 0.002s 0.004s 0.64MB 1806× + map_f_preserves_zero 0.001s 0.001s 0.06MB 84× + map2_f_preserves_zero 0.009s 0.012s 3.23MB 3444× + cut_front_matrix 0.001s 0.001s 0.58MB 84× + find_first_non_zero 0.001s 0.001s 0.03MB 84× + assign_texpr 0.001s 0.001s 0.18MB 4× + coeff_vec 0.001s 0.001s 0.01MB 4× + equal 0.001s 0.001s 0.01MB 4× + remove_rels_with_var 0.001s 0.001s 0.01MB 4× + rref_vec 0.001s 0.001s 0.14MB 4× + get_pivot_positions 0.001s 0.001s 0.11MB 4× + find_first_non_zero 0.001s 0.001s 0.06MB 170× + find_first_non_zero 0.001s 0.001s 0.01MB 4× + map_f_preserves_zero 0.001s 0.001s 0.01MB 4× + insert_v_according_to_piv 0.001s 0.001s 0.03MB 4× + remove_vars 0.001s 0.001s 0.12MB 21× + drop_vars 0.001s 0.001s 0.01MB 21× + copy 0.001s 0.001s 0.01MB 15× + dimension change 0.001s 0.001s 0.08MB 21× + dim remove 0.001s 0.001s 0.07MB 3× + del_cols 0.001s 0.001s 0.03MB 3× + reachability 0.001s 0.001s 0.01MB 1× + remove_filter 0.001s 0.001s 0.04MB 1× + dimension change 0.001s 0.001s 0.03MB 1× + dim remove 0.001s 0.001s 0.03MB 1× + del_cols 0.001s 0.001s 0.01MB 1× + bounds calculation 0.001s 0.001s 0.08MB 13× + coeff_vec 0.001s 0.001s 0.06MB 13× + to_constant_opt 0.001s 0.001s 0.02MB 13× + find_first_non_zero 0.001s 0.001s 0.01MB 13× + keep_filter 0.001s 0.001s 0.33MB 1× + copy 0.000s 0.001s 0.01MB 1× + dimension change 0.001s 0.001s 0.31MB 1× + dim remove 0.001s 0.001s 0.31MB 1× + del_cols 0.001s 0.001s 0.01MB 1× + meet 0.001s 0.001s 0.06MB 1× + dimension change 0.001s 0.001s 0.02MB 2× + dim add 0.001s 0.001s 0.02MB 1× + add_empty_cols 0.001s 0.001s 0.02MB 1× + equal 0.001s 0.001s 0.01MB 2× + rref_matrix 0.001s 0.001s 0.04MB 1× + rref_vec 0.001s 0.001s 0.04MB 1× + get_pivot_positions 0.001s 0.001s 0.03MB 1× + find_first_non_zero 0.001s 0.001s 0.02MB 42× + find_first_non_zero 0.001s 0.001s 0.01MB 1× + map_f_preserves_zero 0.001s 0.001s 0.01MB 1× + insert_v_according_to_piv 0.001s 0.001s 0.01MB 1× + warn_global 0.001s 0.001s 0.21MB 1× + equal 0.001s 0.001s 0.01MB 6× + sv-comp result 0.001s 0.001s 0.17MB 1× + arg create 0.001s 0.001s 0.17MB 1× + graphml witness 0.050s 0.051s 20.32MB 1× + yaml witness 0.010s 0.010s 1.62MB 1× + keep_filter 0.001s 0.001s 0.01MB 1× + copy 0.001s 0.001s 0.01MB 1× + dimension change 0.001s 0.001s 0.01MB 1× + result output 0.001s 0.001s 0.01MB 1× From 5326e2b0e7039570638487cd6d0ec80bd8f1c1ce Mon Sep 17 00:00:00 2001 From: CopperCableIsolator Date: Tue, 25 Feb 2025 19:19:44 +0100 Subject: [PATCH 236/240] renamed domain to fit goblint scheme --- ...ainSideEffects.apron.ml => affineEqualityDenseDomain.apron.ml} | 0 ...eEffects.no-apron.ml => affineEqualityDenseDomain.no-apron.ml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/cdomains/apron/{affineEqualityDomainSideEffects.apron.ml => affineEqualityDenseDomain.apron.ml} (100%) rename src/cdomains/apron/{affineEqualityDomainSideEffects.no-apron.ml => affineEqualityDenseDomain.no-apron.ml} (100%) diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml b/src/cdomains/apron/affineEqualityDenseDomain.apron.ml similarity index 100% rename from src/cdomains/apron/affineEqualityDomainSideEffects.apron.ml rename to src/cdomains/apron/affineEqualityDenseDomain.apron.ml diff --git a/src/cdomains/apron/affineEqualityDomainSideEffects.no-apron.ml b/src/cdomains/apron/affineEqualityDenseDomain.no-apron.ml similarity index 100% rename from src/cdomains/apron/affineEqualityDomainSideEffects.no-apron.ml rename to src/cdomains/apron/affineEqualityDenseDomain.no-apron.ml From abbde006b27db6bccb9b013b726597cf85220461 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 25 Feb 2025 20:11:19 +0100 Subject: [PATCH 237/240] Change affeq sparse config from side_effect to sparse with default true --- src/config/options.schema.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config/options.schema.json b/src/config/options.schema.json index a0aacb6b50..be379d3866 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -1204,10 +1204,10 @@ "type": "object", "properties": { "side_effects": { - "title": "ana.affeq.side_effects", - "description": "Use side effect Affine Equality analysis (array implementation). Default is false (sparse implementation)", + "title": "ana.affeq.sparse", + "description": "Use sparse implementation of Affine Equality analysis (using lists). If set to false, the dense version is used (using arrays). Default is true (sparse implementation)", "type": "boolean", - "default": false + "default": true } }, "additionalProperties": false From 4176d528aec844151efc19147baaedab68fe8043 Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 25 Feb 2025 20:14:01 +0100 Subject: [PATCH 238/240] Remove debug files --- conf.json | 146 ----------------- rref_vec_new_no_filter_baliktad.txt | 1 - test6new.txt | 237 ---------------------------- 3 files changed, 384 deletions(-) delete mode 100644 conf.json delete mode 100644 rref_vec_new_no_filter_baliktad.txt delete mode 100644 test6new.txt diff --git a/conf.json b/conf.json deleted file mode 100644 index 8c7335417e..0000000000 --- a/conf.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "ana": { - "sv-comp": { - "enabled": true, - "functions": true - }, - "int": { - "def_exc": true, - "enums": false, - "interval": true - }, - "float": { - "interval": true - }, - "activated": [ - "base", - "threadid", - "threadflag", - "threadreturn", - "mallocWrapper", - "mutexEvents", - "mutex", - "access", - "race", - "escape", - "expRelation", - "mhp", - "assert", - "var_eq", - "symb_locks", - "region", - "thread", - "threadJoins", - "affeq" - ], - "path_sens": [ - "mutex", - "malloc_null", - "uninit", - "expsplit", - "activeSetjmp", - "memLeak", - "threadflag" - ], - "context": { - "widen": false - }, - "malloc": { - "wrappers": [ - "kmalloc", - "__kmalloc", - "usb_alloc_urb", - "__builtin_alloca", - "kzalloc", - - "ldv_malloc", - - "kzalloc_node", - "ldv_zalloc", - "kmalloc_array", - "kcalloc", - - "ldv_xmalloc", - "ldv_xzalloc", - "ldv_calloc", - "ldv_kzalloc" - ] - }, - "base": { - "arrays": { - "domain": "partitioned" - } - }, - "race": { - "free": false, - "call": false - }, - "autotune": { - "enabled": true, - "activated": [ - "singleThreaded", - "mallocWrappers", - "noRecursiveIntervals", - "enums", - "congruence", - "wideningThresholds", - "loopUnrollHeuristic", - "memsafetySpecification", - "termination", - "tmpSpecialAnalysis" - ] - } - }, - "exp": { - "region-offsets": true - }, - "solver": "td3", - "sem": { - "unknown_function": { - "spawn": false - }, - "int": { - "signed_overflow": "assume_none" - }, - "null-pointer": { - "dereference": "assume_none" - } - }, - "witness": { - "graphml": { - "enabled": true, - "id": "enumerate", - "unknown": false - }, - "yaml": { - "enabled": true, - "format-version": "2.0", - "entry-types": [ - "invariant_set" - ], - "invariant-types": [ - "loop_invariant" - ] - }, - "invariant": { - "loop-head": true, - "after-lock": false, - "other": false, - "accessed": false, - "exact": true, - "exclude-vars": [ - "tmp\\(___[0-9]+\\)?", - "cond", - "RETURN", - "__\\(cil_\\)?tmp_?[0-9]*\\(_[0-9]+\\)?", - ".*____CPAchecker_TMP_[0-9]+", - "__VERIFIER_assert__cond", - "__ksymtab_.*", - "\\(ldv_state_variable\\|ldv_timer_state\\|ldv_timer_list\\|ldv_irq_\\(line_\\|data_\\)?[0-9]+\\|ldv_retval\\)_[0-9]+" - ] - } - }, - "pre": { - "enabled": false - } -} \ No newline at end of file diff --git a/rref_vec_new_no_filter_baliktad.txt b/rref_vec_new_no_filter_baliktad.txt deleted file mode 100644 index 43eb20ee91..0000000000 --- a/rref_vec_new_no_filter_baliktad.txt +++ /dev/null @@ -1 +0,0 @@ -Fatal error: exception Sys_error("conf.json: No such file or diretory") diff --git a/test6new.txt b/test6new.txt deleted file mode 100644 index 8484db1f35..0000000000 --- a/test6new.txt +++ /dev/null @@ -1,237 +0,0 @@ -[Warning] --sets is deprecated, use --set instead. -[Warning] --sets is deprecated, use --set instead. -[Info] unrolling loop at /home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9483:5-9493:5 with factor 4 -[Info] no thread creation -> disabling thread analyses "race, deadlock, maylocks, symb_locks, thread, threadid, threadJoins, threadreturn, mhp, region, pthreadMutexType" -[Info] SV-COMP specification: CHECK( init(main()), LTL(G ! call(reach_error())) ) -[Warning][Deadcode] Function 'reach_error' is uncalled: 1 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:16:1-16:83) -[Warning][Deadcode] Function 'calculate_output' is uncalled: 2123 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:73:2-2247:2) -[Warning][Deadcode] Function 'calculate_output2' is uncalled: 2130 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:2249:2-4428:2) -[Warning][Deadcode] Function 'calculate_output3' is uncalled: 2129 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:4430:2-6614:2) -[Warning][Deadcode] Function 'calculate_output4' is uncalled: 2181 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:6616:2-8864:2) -[Warning][Deadcode] Function 'calculate_output5' is uncalled: 534 LLoC (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:8866:2-9475:2) -[Warning][Deadcode] Function 'main' has dead code: - on line 9491 (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9491-9491) - on line 9494 (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9494-9494) -[Warning][Deadcode] Logical lines of code (LLoC) summary: - live: 6 - dead: 9100 (9098 in uncalled functions) - total lines: 9106 -[Warning][Deadcode][CWE-571] condition '1' (possibly inserted by CIL) is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9483:11-9483:12) -[Warning][Deadcode][CWE-571] condition 'input != 1' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) -[Warning][Deadcode][CWE-571] condition 'input != 2' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) -[Warning][Deadcode][CWE-571] condition 'input != 3' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) -[Warning][Deadcode][CWE-571] condition 'input != 4' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) -[Warning][Deadcode][CWE-571] condition 'input != 5' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) -[Warning][Deadcode][CWE-571] condition 'input != 6' is always true (/home/franzisco/Goblint/sv-benchmarks/c/eca-rers2012/Problem06_label06.c:9488:14-9488:105) -SV-COMP result: true -[Info][Witness] witness generation summary: - location invariants: 0 - loop invariants: 44 - flow-insensitive invariants: 0 - total generation entries: 1 - -[Info] vars = 65 evals = 94 narrow_reuses = 21 - -[Info] Timings: - cputime walltime allocated count -Default 2.789s 2.800s 577.77MB 1× - preprocess 0.060s 0.056s 0.01MB 1× - FrontC 0.113s 0.114s 74.78MB 4× - Cabs2cil 0.254s 0.254s 93.80MB 4× - mergeCIL 0.018s 0.018s 18.06MB 1× - analysis 1.759s 1.765s 199.94MB 1× - createCFG 1.510s 1.515s 111.35MB 1× - handle 0.182s 0.183s 48.91MB 37× - iter_connect 1.314s 1.318s 57.18MB 37× - computeSCCs 0.105s 0.105s 47.10MB 38× - global_inits 0.017s 0.017s 8.03MB 1× - add_vars 0.003s 0.003s 0.84MB 169× - copy 0.001s 0.001s 0.06MB 169× - dimension change 0.002s 0.002s 0.53MB 169× - dim add 0.001s 0.001s 0.45MB 84× - add_empty_cols 0.001s 0.001s 0.40MB 84× - var_parallel 0.001s 0.001s 0.01MB 1× - add_vars 0.001s 0.001s 0.01MB 2× - copy 0.001s 0.001s 0.01MB 2× - dimension change 0.001s 0.001s 0.01MB 2× - drop_vars 0.001s 0.001s 0.01MB 1× - copy 0.001s 0.001s 0.01MB 1× - dimension change 0.001s 0.001s 0.01MB 1× - normalize 0.001s 0.001s 0.01MB 1× - equal 0.001s 0.001s 0.06MB 43× - assign_texpr 0.007s 0.008s 2.15MB 84× - coeff_vec 0.001s 0.001s 0.10MB 84× - equal 0.001s 0.001s 0.03MB 84× - rref_vec 0.006s 0.006s 1.58MB 84× - find_first_non_zero 0.001s 0.001s 0.03MB 84× - map_f_preserves_zero 0.001s 0.001s 0.06MB 84× - get_pivot_positions 0.005s 0.005s 1.10MB 83× - find_first_non_zero 0.002s 0.004s 0.63MB 1764× - insert_v_according_to_piv 0.001s 0.001s 0.28MB 83× - remove_rels_with_var 0.001s 0.001s 0.04MB 83× - remove_vars 0.003s 0.003s 0.69MB 84× - drop_vars 0.001s 0.001s 0.04MB 84× - copy 0.001s 0.001s 0.03MB 84× - dimension change 0.001s 0.001s 0.48MB 84× - dim remove 0.001s 0.001s 0.44MB 42× - del_cols 0.001s 0.001s 0.23MB 42× - equal 0.001s 0.001s 0.01MB 4× - reachability 0.001s 0.001s 0.01MB 1× - add_vars 0.001s 0.001s 0.01MB 1× - copy 0.001s 0.001s 0.01MB 1× - dimension change 0.001s 0.001s 0.01MB 1× - remove_filter 0.001s 0.001s 0.01MB 1× - dimension change 0.001s 0.001s 0.01MB 1× - solving 0.081s 0.082s 26.54MB 1× - equal 0.001s 0.001s 0.06MB 26× - add_vars 0.001s 0.001s 0.18MB 61× - copy 0.001s 0.001s 0.03MB 61× - dimension change 0.001s 0.001s 0.07MB 61× - dim add 0.001s 0.001s 0.05MB 5× - add_empty_cols 0.001s 0.001s 0.05MB 5× - assert_constraint 0.002s 0.002s 0.54MB 58× - meet_tcons 0.001s 0.001s 0.03MB 56× - coeff_vec 0.001s 0.001s 0.34MB 56× - map_f_preserves_zero 0.001s 0.001s 0.04MB 56× - map2_f_preserves_zero 0.001s 0.001s 0.04MB 56× - to_constant_opt 0.001s 0.001s 0.05MB 56× - find_first_non_zero 0.001s 0.001s 0.02MB 56× - var_parallel 0.030s 0.030s 6.41MB 2× - add_vars 0.001s 0.001s 0.01MB 4× - copy 0.001s 0.001s 0.01MB 4× - dimension change 0.001s 0.001s 0.01MB 4× - drop_vars 0.001s 0.001s 0.01MB 2× - copy 0.001s 0.001s 0.01MB 2× - dimension change 0.001s 0.001s 0.01MB 2× - normalize 0.029s 0.029s 6.39MB 2× - find_first_pivot 0.007s 0.007s 1.04MB 84× - find_first_non_zero 0.002s 0.005s 0.64MB 1806× - map_f_preserves_zero 0.001s 0.001s 0.06MB 84× - map2_f_preserves_zero 0.011s 0.015s 3.23MB 3444× - cut_front_matrix 0.001s 0.001s 0.58MB 84× - find_first_non_zero 0.001s 0.001s 0.03MB 84× - S.Dom.equal 0.001s 0.001s 0.04MB 115× - assign_texpr 0.001s 0.001s 0.18MB 4× - coeff_vec 0.001s 0.001s 0.01MB 4× - equal 0.001s 0.001s 0.01MB 4× - remove_rels_with_var 0.001s 0.001s 0.01MB 4× - rref_vec 0.001s 0.001s 0.14MB 4× - get_pivot_positions 0.001s 0.001s 0.11MB 4× - find_first_non_zero 0.001s 0.001s 0.06MB 170× - find_first_non_zero 0.001s 0.001s 0.01MB 4× - map_f_preserves_zero 0.001s 0.001s 0.01MB 4× - insert_v_according_to_piv 0.001s 0.001s 0.03MB 4× - remove_vars 0.001s 0.001s 0.12MB 21× - drop_vars 0.001s 0.001s 0.01MB 21× - copy 0.001s 0.001s 0.01MB 15× - dimension change 0.001s 0.001s 0.08MB 21× - dim remove 0.001s 0.001s 0.07MB 3× - del_cols 0.001s 0.001s 0.03MB 3× - reachability 0.001s 0.001s 0.01MB 1× - remove_filter 0.001s 0.001s 0.04MB 1× - dimension change 0.001s 0.001s 0.03MB 1× - dim remove 0.001s 0.001s 0.03MB 1× - del_cols 0.001s 0.001s 0.01MB 1× - bounds calculation 0.001s 0.001s 0.08MB 13× - coeff_vec 0.001s 0.001s 0.06MB 13× - to_constant_opt 0.001s 0.001s 0.02MB 13× - find_first_non_zero 0.001s 0.001s 0.01MB 13× - keep_filter 0.001s 0.001s 0.33MB 1× - copy 0.001s 0.001s 0.01MB 1× - dimension change 0.001s 0.001s 0.31MB 1× - dim remove 0.001s 0.001s 0.31MB 1× - del_cols 0.001s 0.001s 0.01MB 1× - meet 0.001s 0.001s 0.06MB 1× - dimension change 0.001s 0.001s 0.02MB 2× - dim add 0.001s 0.001s 0.02MB 1× - add_empty_cols 0.001s 0.001s 0.02MB 1× - equal 0.001s 0.001s 0.01MB 2× - rref_matrix 0.001s 0.001s 0.04MB 1× - rref_vec 0.001s 0.001s 0.04MB 1× - get_pivot_positions 0.001s 0.001s 0.03MB 1× - find_first_non_zero 0.001s 0.001s 0.02MB 42× - find_first_non_zero 0.001s 0.001s 0.01MB 1× - map_f_preserves_zero 0.001s 0.001s 0.01MB 1× - insert_v_according_to_piv 0.001s 0.001s 0.01MB 1× - cheap_full_reach 0.001s 0.001s 0.02MB 1× - postsolver 0.026s 0.026s 11.93MB 1× - postsolver_iter 0.026s 0.026s 11.89MB 1× - equal 0.001s 0.001s 0.09MB 40× - add_vars 0.001s 0.001s 0.18MB 61× - copy 0.001s 0.001s 0.03MB 61× - dimension change 0.001s 0.001s 0.07MB 61× - dim add 0.001s 0.001s 0.05MB 5× - add_empty_cols 0.001s 0.001s 0.05MB 5× - assert_constraint 0.002s 0.002s 0.54MB 58× - meet_tcons 0.001s 0.001s 0.03MB 56× - coeff_vec 0.001s 0.001s 0.34MB 56× - map_f_preserves_zero 0.001s 0.001s 0.04MB 56× - map2_f_preserves_zero 0.001s 0.001s 0.04MB 56× - to_constant_opt 0.001s 0.001s 0.05MB 56× - find_first_non_zero 0.001s 0.001s 0.02MB 56× - var_parallel 0.018s 0.018s 6.41MB 2× - add_vars 0.001s 0.001s 0.01MB 4× - copy 0.001s 0.001s 0.01MB 4× - dimension change 0.001s 0.001s 0.01MB 4× - drop_vars 0.001s 0.001s 0.01MB 2× - copy 0.001s 0.001s 0.01MB 2× - dimension change 0.001s 0.001s 0.01MB 2× - normalize 0.018s 0.018s 6.39MB 2× - find_first_pivot 0.004s 0.005s 1.04MB 84× - find_first_non_zero 0.002s 0.004s 0.64MB 1806× - map_f_preserves_zero 0.001s 0.001s 0.06MB 84× - map2_f_preserves_zero 0.009s 0.012s 3.23MB 3444× - cut_front_matrix 0.001s 0.001s 0.58MB 84× - find_first_non_zero 0.001s 0.001s 0.03MB 84× - assign_texpr 0.001s 0.001s 0.18MB 4× - coeff_vec 0.001s 0.001s 0.01MB 4× - equal 0.001s 0.001s 0.01MB 4× - remove_rels_with_var 0.001s 0.001s 0.01MB 4× - rref_vec 0.001s 0.001s 0.14MB 4× - get_pivot_positions 0.001s 0.001s 0.11MB 4× - find_first_non_zero 0.001s 0.001s 0.06MB 170× - find_first_non_zero 0.001s 0.001s 0.01MB 4× - map_f_preserves_zero 0.001s 0.001s 0.01MB 4× - insert_v_according_to_piv 0.001s 0.001s 0.03MB 4× - remove_vars 0.001s 0.001s 0.12MB 21× - drop_vars 0.001s 0.001s 0.01MB 21× - copy 0.001s 0.001s 0.01MB 15× - dimension change 0.001s 0.001s 0.08MB 21× - dim remove 0.001s 0.001s 0.07MB 3× - del_cols 0.001s 0.001s 0.03MB 3× - reachability 0.001s 0.001s 0.01MB 1× - remove_filter 0.001s 0.001s 0.04MB 1× - dimension change 0.001s 0.001s 0.03MB 1× - dim remove 0.001s 0.001s 0.03MB 1× - del_cols 0.001s 0.001s 0.01MB 1× - bounds calculation 0.001s 0.001s 0.08MB 13× - coeff_vec 0.001s 0.001s 0.06MB 13× - to_constant_opt 0.001s 0.001s 0.02MB 13× - find_first_non_zero 0.001s 0.001s 0.01MB 13× - keep_filter 0.001s 0.001s 0.33MB 1× - copy 0.000s 0.001s 0.01MB 1× - dimension change 0.001s 0.001s 0.31MB 1× - dim remove 0.001s 0.001s 0.31MB 1× - del_cols 0.001s 0.001s 0.01MB 1× - meet 0.001s 0.001s 0.06MB 1× - dimension change 0.001s 0.001s 0.02MB 2× - dim add 0.001s 0.001s 0.02MB 1× - add_empty_cols 0.001s 0.001s 0.02MB 1× - equal 0.001s 0.001s 0.01MB 2× - rref_matrix 0.001s 0.001s 0.04MB 1× - rref_vec 0.001s 0.001s 0.04MB 1× - get_pivot_positions 0.001s 0.001s 0.03MB 1× - find_first_non_zero 0.001s 0.001s 0.02MB 42× - find_first_non_zero 0.001s 0.001s 0.01MB 1× - map_f_preserves_zero 0.001s 0.001s 0.01MB 1× - insert_v_according_to_piv 0.001s 0.001s 0.01MB 1× - warn_global 0.001s 0.001s 0.21MB 1× - equal 0.001s 0.001s 0.01MB 6× - sv-comp result 0.001s 0.001s 0.17MB 1× - arg create 0.001s 0.001s 0.17MB 1× - graphml witness 0.050s 0.051s 20.32MB 1× - yaml witness 0.010s 0.010s 1.62MB 1× - keep_filter 0.001s 0.001s 0.01MB 1× - copy 0.001s 0.001s 0.01MB 1× - dimension change 0.001s 0.001s 0.01MB 1× - result output 0.001s 0.001s 0.01MB 1× From e3cbcf70a284ff59f50fa029bed9dc76918b281e Mon Sep 17 00:00:00 2001 From: Kevin Adameit Date: Tue, 25 Feb 2025 20:43:03 +0100 Subject: [PATCH 239/240] Fix affeq analysis sparse config param and dune file --- src/analyses/apron/affineEqualityAnalysis.apron.ml | 10 +++++----- src/config/options.schema.json | 2 +- src/dune | 6 +++--- src/goblint_lib.ml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/analyses/apron/affineEqualityAnalysis.apron.ml b/src/analyses/apron/affineEqualityAnalysis.apron.ml index 867bc407c9..c1fc2a51e0 100644 --- a/src/analyses/apron/affineEqualityAnalysis.apron.ml +++ b/src/analyses/apron/affineEqualityAnalysis.apron.ml @@ -14,15 +14,15 @@ include RelationAnalysis (* There are two versions of the affeq domain. 1. Sparse without side effects - 2. Array with side effects + 2. Dense Array with side effects Default: sparse implementation - The array implementation with side effects of the affeq domain is used when the --enable ana.affeq.side_effects option is set *) + The array implementation with side effects of the affeq domain is used when the --disable ana.affeq.sparse option is set *) let get_domain: (module RelationDomain.RD) Lazy.t = lazy ( - if GobConfig.get_bool "ana.affeq.side_effects" then - (module AffineEqualityDomainSideEffects.D2 (ArrayVector) (ArrayMatrix)) - else + if GobConfig.get_bool "ana.affeq.sparse" then (module AffineEqualityDomain.D2 (SparseVector) (ListMatrix)) + else + (module AffineEqualityDenseDomain.D2 (ArrayVector) (ArrayMatrix)) ) let spec_module: (module MCPSpec) Lazy.t = diff --git a/src/config/options.schema.json b/src/config/options.schema.json index be379d3866..06629f2b2d 100644 --- a/src/config/options.schema.json +++ b/src/config/options.schema.json @@ -1203,7 +1203,7 @@ "title": "ana.affeq", "type": "object", "properties": { - "side_effects": { + "sparse": { "title": "ana.affeq.sparse", "description": "Use sparse implementation of Affine Equality analysis (using lists). If set to false, the dense version is used (using arrays). Default is true (sparse implementation)", "type": "boolean", diff --git a/src/dune b/src/dune index 2c3a2f9cf5..f114a14db7 100644 --- a/src/dune +++ b/src/dune @@ -35,9 +35,9 @@ (apron -> affineEqualityDomain.apron.ml) (-> affineEqualityDomain.no-apron.ml) ) - (select affineEqualityDomainSideEffects.ml from - (apron -> affineEqualityDomainSideEffects.apron.ml) - (-> affineEqualityDomainSideEffects.no-apron.ml) + (select affineEqualityDenseDomain.ml from + (apron -> affineEqualityDenseDomain.apron.ml) + (-> affineEqualityDenseDomain.no-apron.ml) ) (select linearTwoVarEqualityAnalysis.ml from (apron -> linearTwoVarEqualityAnalysis.apron.ml) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 18998a4ba9..7f0cffb1dd 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -260,7 +260,7 @@ module ValueDomainQueries = ValueDomainQueries module RelationDomain = RelationDomain module ApronDomain = ApronDomain module AffineEqualityDomain = AffineEqualityDomain -module AffineEqualityDomainSideEffects = AffineEqualityDomainSideEffects +module AffineEqualityDomainDense = AffineEqualityDenseDomain module LinearTwoVarEqualityDomain = LinearTwoVarEqualityDomain (** {3 Concurrency} *) From 463f3600d42c9485f4706e4c41d0d99cabcdfd0e Mon Sep 17 00:00:00 2001 From: Kevin Adameit <82610882+GollokG@users.noreply.github.com> Date: Wed, 26 Feb 2025 11:45:32 +0100 Subject: [PATCH 240/240] Fix docs/api-build CI of AffineEqualityDenseDomain Co-authored-by: Simmo Saan --- src/goblint_lib.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index 7f0cffb1dd..e37fa0cae6 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -260,7 +260,7 @@ module ValueDomainQueries = ValueDomainQueries module RelationDomain = RelationDomain module ApronDomain = ApronDomain module AffineEqualityDomain = AffineEqualityDomain -module AffineEqualityDomainDense = AffineEqualityDenseDomain +module AffineEqualityDenseDomain = AffineEqualityDenseDomain module LinearTwoVarEqualityDomain = LinearTwoVarEqualityDomain (** {3 Concurrency} *)