diff --git a/src/expand_n_contract.rs b/src/expand_n_contract.rs
index 18c60e58268e50c2480da87a3ca30bf69a0437d5..f16949b784d03f419e6976427381a778c206f8a4 100644
--- a/src/expand_n_contract.rs
+++ b/src/expand_n_contract.rs
@@ -9,7 +9,7 @@ pub fn expand_n_contract(
 ) -> Result<(usize, usize, usize), std::io::Error> {
     let mut cocycle_graphs: Vec<UndirectedGraph> = vec![];
     let mut cocycle_graph_index: HashMap<UndirectedGraph, usize> = HashMap::new();
-    let mut cocycle_graph_vertex_orbits: Vec<HashMap<usize, usize>> = vec![];
+    let mut cocycle_graph_vertex_orbits: Vec<Vec<usize>> = vec![];
 
     let mut cocycle_differential_graphs: Vec<UndirectedGraph> = vec![];
     let mut cocycle_differential_graph_index: HashMap<UndirectedGraph, usize> = HashMap::new();
@@ -51,7 +51,7 @@ pub fn expand_n_contract(
             writeln!(sparse_matrix_file, "{} {} {}", dg_idx + 1, g_idx + 1, c)?;
             num_nonzeros += 1;
 
-            let cg_data: HashMap<UndirectedGraph, HashMap<usize, usize>> =
+            let cg_data: HashMap<UndirectedGraph, Vec<usize>> =
                 dg.contractions(&dg_edge_orbits);
             for (cg, cg_vertex_orbits) in cg_data {
                 // eprintln!("{:?}", cg);
diff --git a/src/undirected_graph.rs b/src/undirected_graph.rs
index a18cab99bed23dcd899b075cd8ad6554c9a86524..b297db669ed36f51cf891ffee3451a031ef4d81b 100644
--- a/src/undirected_graph.rs
+++ b/src/undirected_graph.rs
@@ -241,10 +241,7 @@ impl UndirectedGraph {
         }
     }
 
-    pub fn normal_form(
-        &mut self,
-        compute_edge_orbits: bool,
-    ) -> (i32, HashMap<usize, usize>, Vec<usize>) {
+    pub fn normal_form(&mut self, compute_edge_orbits: bool) -> (i32, Vec<usize>, Vec<usize>) {
         let mut options: nauty_Traces_sys::optionblk = nauty_Traces_sys::optionblk {
             getcanon: nauty_Traces_sys::TRUE,
             userautomproc: Some(Self::process_nauty_automorphism),
@@ -295,16 +292,10 @@ impl UndirectedGraph {
             lab_inv[lab[i] as usize] = i as i32;
         }
 
-        // TODO: Check that passing around hashmaps is not too expensive.
-        let mut normal_self_orbits: HashMap<usize, usize> = HashMap::new();
-        for i in 0..n {
-            let orbit_rep: usize = lab_inv[orbits[i] as usize] as usize;
-            if let Some(orbit_size) = normal_self_orbits.get_mut(&orbit_rep) {
-                *orbit_size += 1;
-            } else {
-                normal_self_orbits.insert(orbit_rep, 1);
-            }
-        }
+        let normal_self_orbits: Vec<usize> = orbits
+            .iter()
+            .map(|&v| lab_inv[v as usize] as usize)
+            .collect();
 
         let mut sign: i32 = 1;
         let mut normal_self_edge_orbits: Vec<usize> = vec![];
@@ -468,11 +459,20 @@ impl UndirectedGraph {
 
     pub fn expanding_differential(
         &self,
-        orbits: &HashMap<usize, usize>,
+        orbits: &[usize],
     ) -> HashMap<UndirectedGraph, (i64, Vec<usize>)> {
         let mut diff: HashMap<UndirectedGraph, (i64, Vec<usize>)> = HashMap::new();
 
-        for (&orbit_rep, &orbit_size) in orbits {
+        let mut orbit_reps: HashMap<usize, usize> = HashMap::new();
+        for &orbit_rep in orbits {
+            if let Some(orbit_size) = orbit_reps.get_mut(&orbit_rep) {
+                *orbit_size += 1;
+            } else {
+                orbit_reps.insert(orbit_rep, 1);
+            }
+        }
+
+        for (orbit_rep, orbit_size) in orbit_reps {
             for (c, mut dg) in self.expand_vertex(&orbit_rep) {
                 // TODO: Avoid computing orbits when not used.
                 let (normal_dg_sign, _normal_dg_orbits, normal_dg_edge_orbits) =
@@ -493,12 +493,8 @@ impl UndirectedGraph {
         diff
     }
 
-    pub fn contractions(
-        &self,
-        edge_orbits: &Vec<usize>,
-    ) -> HashMap<UndirectedGraph, HashMap<usize, usize>> {
-        // TODO: Check that passing around hashmaps is not too expensive.
-        let mut contractions: HashMap<UndirectedGraph, HashMap<usize, usize>> = HashMap::new();
+    pub fn contractions(&self, edge_orbits: &Vec<usize>) -> HashMap<UndirectedGraph, Vec<usize>> {
+        let mut contractions: HashMap<UndirectedGraph, Vec<usize>> = HashMap::new();
         let mut edge_orbit_reps: HashSet<usize> = HashSet::new();
         for &edge_orbit_rep in edge_orbits {
             // Skip orbits already seen.