diff --git a/lib/pqtrees/pqRefinementOrder.ml b/lib/pqtrees/pqRefinementOrder.ml
new file mode 100644
index 0000000000000000000000000000000000000000..3e95d7d79f9b338f862c626e61adcf5bf6e63582
--- /dev/null
+++ b/lib/pqtrees/pqRefinementOrder.ml
@@ -0,0 +1,122 @@
+open PqTree
+
+module Make = functor (S : Set.S) -> 
+struct 
+  type elt = S.elt 
+  type pqtree = elt PqTree.t 
+
+  (* type answer =  *)
+  (* | Yes  *)
+  (* | No of elt list  *)
+
+
+  type intersection =
+  | Empty 
+  | All
+  | Complete 
+  | Compromised
+
+  let rec p_intersect = function
+  | []
+  | [ Empty ] -> Empty
+  | [ Complete ] -> Complete 
+  | [ All ] | [All; All]-> All 
+  | Empty :: Empty :: tail -> p_intersect (Empty :: tail)
+  | All :: All :: All :: tail -> p_intersect (All :: All :: tail)
+  | All :: All :: _  -> Compromised
+  | (All | Complete) :: tail 
+  | Empty :: (All | Complete) :: tail ->
+      if List.for_all (fun elt -> elt = Empty) tail then Complete
+      else Compromised
+  | Compromised :: _ 
+  | _ :: Compromised :: _ -> Compromised
+
+  let rec q_intersect = function 
+  | All :: All :: tail -> q_intersect (All :: tail)
+  | Empty :: Empty :: tail -> q_intersect (Empty :: tail)
+  | Empty :: All :: All :: tail -> q_intersect (Empty :: All :: tail)
+  | All :: Empty :: tail 
+  | Empty :: All :: Empty :: tail
+  | Empty :: Complete :: tail 
+  | Complete :: Empty :: tail -> q_intersect(Complete :: tail)
+  | [ All ] -> All 
+  | [ Empty ] | [] -> Empty 
+  | [ Complete ] | [Empty; All] -> Complete
+  | All :: Complete :: _ 
+  | Compromised :: _
+  | _ :: Compromised :: _
+  | Empty :: All :: (Complete | Compromised) :: _
+  | Complete :: All :: _
+  | Complete :: Complete :: _ -> Compromised
+  (* | _ -> Compromised  *)
+  
+
+
+  let rec intersect_block block = function 
+  | P children -> 
+      children
+      |> List.map (intersect_block block)
+      |> p_intersect 
+  | Q children ->
+      children
+      |> List.map (intersect_block block)
+        |> q_intersect 
+  | Leaf x when S.mem x block -> All
+  | Leaf _ -> Empty  
+
+
+  let is_a_block tree block = 
+    intersect_block block tree <> Compromised
+
+  
+  let is_not_singleton set =
+    S.cardinal set <> 1
+
+  let rec blocks_and_block = 
+    let recurse children = 
+        List.to_seq children
+        |> Seq.map blocks_and_block 
+        |> Seq.split 
+    in 
+    function 
+    | Leaf x -> (Seq.empty, S.singleton x) 
+    | P children ->
+        let (blocks, sets) = recurse children in 
+        (blocks
+         |> Seq.concat
+         |> Seq.append (Seq.filter is_not_singleton sets), 
+         Seq.fold_left S.union S.empty sets
+        )
+    | Q children ->
+        let n = List.length children in 
+        let (blocks, sets) = recurse children in 
+        let set = Seq.fold_left S.union S.empty sets in 
+        let leftist_blocks =
+          Seq.scan S.union S.empty sets |> Seq.drop 2 |> Seq.take (n-2) 
+        in
+        let rightist_blocks = 
+          Seq.scan S.diff set sets |> Seq.drop 1 |> Seq.take (n-2)
+        in   
+        (blocks
+         |> Seq.concat 
+         |> Seq.append (Seq.filter is_not_singleton sets)
+         |> Seq.append leftist_blocks
+         |> Seq.append rightist_blocks, 
+         set)
+
+  let enumerate_non_trivial_blocks tree = 
+    fst (blocks_and_block tree)
+  
+
+  let is_refinement tree1 tree2 = 
+    Seq.for_all 
+      (is_a_block tree1)
+      (enumerate_non_trivial_blocks tree2)
+
+
+  (* let is_refinement tree1 tree2 =  *)
+  (*   match certify_refinement tree1 tree2 with  *)
+  (*   | Yes -> true *)
+  (*   | No _ -> false  *)
+
+end
diff --git a/lib/pqtrees/pqRefinementOrder.mli b/lib/pqtrees/pqRefinementOrder.mli
new file mode 100644
index 0000000000000000000000000000000000000000..fae9bc4dbe46a77352c261fb494479a7ef4d9327
--- /dev/null
+++ b/lib/pqtrees/pqRefinementOrder.mli
@@ -0,0 +1,32 @@
+module Make : functor (S : Set.S) -> 
+sig
+  type elt = S.elt 
+  type pqtree = elt PqTree.t 
+
+
+  val is_a_block : pqtree -> S.t -> bool
+
+  val enumerate_non_trivial_blocks : pqtree -> S.t Seq.t 
+
+  val is_refinement : pqtree -> pqtree -> bool 
+
+
+end 
+
+
+
+(* type 'elt answer =  *)
+(*   | Yes  *)
+(*   | No of 'elt list (\** a certifying permutation *\) *)
+
+
+(* (\** [is_refinement tree1 tree2] checks whether all permutations *)
+(*     represented by [tree1] are represented in [tree2]. *\) *)
+(* val is_refinement : 'elt PqTree.t -> 'elt PqTree.t -> bool  *)
+
+
+(* (\** [certify_refinement tree1 tree2] returns [Yes] if [tree1] is a *)
+(*     refinement of [tree2], or [No permut] where [permut] is *)
+(*     represented in [tree1] but not in [tree2]. *\) *)
+(* val certify_refinement : 'elt PqTree.t -> 'elt PqTree.t -> 'elt answer  *)
+
diff --git a/test/propertytest/chainInsertion.ml b/test/propertytest/chainInsertion.ml
index 90034d80fe296ccfaad9c59bc8354386f5cdbcc4..573d7a485338b4eed03839942aec7bd8ddd2229d 100644
--- a/test/propertytest/chainInsertion.ml
+++ b/test/propertytest/chainInsertion.ml
@@ -7,6 +7,7 @@ open QCheck2
 
 
 module IntSet = Set.Make(Int) 
+module Ref = PqRefinementOrder.Make(IntSet)
 
 let insert_interval interval pqtree = 
   let f i = if IntSet.mem i interval then 0 else 1 in 
@@ -38,7 +39,56 @@ let test_interval_insertion_does_not_fail =
     
 
 
+let rec zip list1 list2 = match list1, list2 with 
+| hd1::tl1, hd2::tl2 -> (hd1,hd2)::zip tl1 tl2
+| _,_ -> [] 
+
+  
+
+let print_tree_and_chain = 
+  Print.(pair to_string (pair int (list (pair int int))))
+
+let gen_tree_and_chain = 
+  let open Gen in 
+  list_size (return 100) bool >>= fun bools -> 
+  int_range 1 50 >>=
+  sized_shuffled_pair_gen >>= fun (shuffled, pqtree) ->
+  let elts = PqTree.frontier shuffled in 
+  let n = List.length elts in 
+  int_range 0 (n-1) >>= fun pivot_rank -> 
+  let ints =
+    bools
+    |> List.fold_left (fun (accu,i) bool -> (i::accu, if bool then i else i+1)) ([],0)
+    |> fst
+  in
+  let pivot = List.nth elts pivot_rank in 
+  let pivot_v = List.nth ints pivot_rank in 
+  return (pqtree, (pivot, zip elts (List.map (fun i -> abs (i - pivot_v)) ints)))
+  
+
+
+let new_valid_permutation_is_old_valid_permutation (pqtree, (source,distances)) =
+  let f i = List.assoc i distances in  
+  match PqChainInsertion.refine_by_distances source f pqtree with
+  | None -> false
+| Some new_pqtree -> Ref.is_refinement new_pqtree pqtree 
+
+let test_new_valid_permutation_is_old_valid_permutation =
+  Test.make
+    ~name:"Chain insertion returns a refinement of the original PQ-tree"
+    ~print:print_tree_and_chain
+    ~count:1000
+    gen_tree_and_chain 
+    new_valid_permutation_is_old_valid_permutation
+    
+  
+
+
+
+
+
 let tests = 
   [ 
-    test_interval_insertion_does_not_fail
+    test_interval_insertion_does_not_fail;
+    test_new_valid_permutation_is_old_valid_permutation;
   ]
diff --git a/test/unit/refinementOrderTest.ml b/test/unit/refinementOrderTest.ml
new file mode 100644
index 0000000000000000000000000000000000000000..a9c60f09161e5546b1455d9816445fad9096dbed
--- /dev/null
+++ b/test/unit/refinementOrderTest.ml
@@ -0,0 +1,107 @@
+open PqTreeLib
+open PqTree 
+open RobinsonTest 
+
+open IntPqTree 
+
+module IntSet = Set.Make(Int)
+
+
+let pp_sep sep fmt () = Format.(fprintf fmt "%s@ " sep)
+
+let pp_delimiter left right inside_formatter fmt value =
+  Format.(fprintf fmt "%s%a%s" left inside_formatter value right)
+
+let pp_delimited_seq left sep right elt_formatter = 
+  let open Format in 
+  pp_delimiter left right 
+    (pp_print_seq elt_formatter ~pp_sep:(pp_sep sep))
+ 
+let pp_block fmt block = 
+  pp_delimited_seq "{" ";" "}" Format.pp_print_int fmt (IntSet.to_seq block)
+
+
+let pp_block_seq =
+  pp_delimited_seq "[" ";" "]" pp_block
+
+
+let output_blocks blocks =
+  Format.(printf "%a" pp_block_seq blocks) 
+  
+
+let output result = 
+  result
+  |> Option.map Canonical.canonical
+  |> Option.map to_string
+  |> Option.value ~default:"not an interval"
+  |> print_endline
+
+module M = PqRefinementOrder.Make(IntSet)
+
+
+
+let tree0 = P [Leaf 1; Leaf 2; Leaf 3]
+
+let%expect_test _ = 
+  M.enumerate_non_trivial_blocks tree0
+  |> output_blocks; [%expect{|
+    []|}]
+
+
+let tree1 = Q [Leaf 1; Leaf 2; Leaf 3]
+
+let%expect_test _ = 
+  M.enumerate_non_trivial_blocks tree1
+  |> output_blocks; [%expect{|
+    [{2; 3}; {1;
+    2}]|}]
+
+
+let tree2 = P [ Q [Leaf 1; Leaf 2; Leaf 3]; P [Leaf 4; Leaf 5]] 
+
+let%expect_test _ = 
+  M.enumerate_non_trivial_blocks tree2
+  |> output_blocks; [%expect{|
+    [{1; 2; 3}; {4; 5}; {2; 3}; {1;
+    2}]|}]
+
+let tree3 = 
+  Q [
+    P [Leaf 1; Leaf 2; Leaf 3]; 
+    Q [Leaf 4; Leaf 5; Leaf 6]; 
+    Leaf 7;
+    P [P [Leaf 8; Leaf 9]; Leaf 10; Leaf 11]
+  ]
+
+let%expect_test _ = 
+  M.enumerate_non_trivial_blocks tree3
+  |> output_blocks; [%expect{|
+    [{4; 5; 6; 7; 8; 9; 10; 11}; {7; 8; 9; 10; 11}; {1; 2; 3; 4; 5; 6}; {1; 2; 3;
+    4; 5; 6; 7}; {1; 2; 3}; {4; 5; 6}; {8; 9; 10; 11}; {5; 6}; {4; 5}; {8;
+    9}]|}]
+
+let%expect_test _ =
+  [ ([1;2], tree1);
+    ([2;3], tree1);
+    ([4;5], tree2);
+    ([1;2;3;4;5], tree2);
+    ([1;2;3], tree2);
+    ([2], tree2);
+    ([4;5;6;7], tree3);
+    ([1;2;3;4;5;6], tree3);
+    ([8;9],tree3);
+    ([1;3], tree0);
+    ([1;3], tree1);
+    ([1;3], tree2);
+    ([1;2;4;5], tree2);
+    ([2;3;4;5;6], tree3);
+    ([1;2;3;7], tree3);
+    ([8;9;10], tree3);
+  ]
+  |> List.to_seq
+  |> Seq.map (fun (block, tree) -> M.is_a_block tree (IntSet.of_list block)) 
+  |> Format.printf "%a" (pp_delimited_seq "[" ";" "]" Format.pp_print_bool);
+  [%expect{|
+    [true; true; true; true; true; true; true; true; true; false; false; false;
+    false; false; false;
+    false] |}]