diff --git a/src/expand_n_contract.rs b/src/expand_n_contract.rs
index a043c718cf4e13fa910438677939c4ae2e56fc85..7241a11edead3cf49c15d257c07302a3fe744d80 100644
--- a/src/expand_n_contract.rs
+++ b/src/expand_n_contract.rs
@@ -5,8 +5,42 @@ use std::io::{Seek, Write};
 
 pub fn expand_n_contract(
     num_spokes: usize,
-    sparse_matrix_file: &mut File,
+    cocycle_graphs_filename: &String,
+    cocycle_differential_graphs_filename: &String,
+    cocycle_differential_matrix_filename: &String,
 ) -> Result<(usize, usize, usize), std::io::Error> {
+    // TODO: Avoid overwriting existing files.
+
+    let cocycle_graphs_file_res: Result<File, std::io::Error> =
+        File::create(cocycle_graphs_filename);
+    if cocycle_graphs_file_res.is_err() {
+        eprintln!("Error opening file: {}", cocycle_graphs_filename);
+        std::process::exit(1);
+    }
+    let mut cocycle_graphs_file: File = cocycle_graphs_file_res.unwrap();
+
+    let cocycle_differential_graphs_file_res: Result<File, std::io::Error> =
+        File::create(cocycle_differential_graphs_filename);
+    if cocycle_differential_graphs_file_res.is_err() {
+        eprintln!(
+            "Error opening file: {}",
+            cocycle_differential_graphs_filename
+        );
+        std::process::exit(1);
+    }
+    let mut cocycle_differential_graphs_file: File = cocycle_differential_graphs_file_res.unwrap();
+
+    let cocycle_differential_matrix_file_res: Result<File, std::io::Error> =
+        File::create(cocycle_differential_matrix_filename);
+    if cocycle_differential_matrix_file_res.is_err() {
+        eprintln!(
+            "Error opening file: {}",
+            cocycle_differential_matrix_filename
+        );
+        std::process::exit(1);
+    }
+    let mut cocycle_differential_matrix_file: File = cocycle_differential_matrix_file_res.unwrap();
+
     let mut cocycle_graphs: Vec<UndirectedGraph> = vec![];
     let mut cocycle_graph_index: HashMap<UndirectedGraph, usize> = HashMap::new();
     let mut cocycle_graph_vertex_orbits: Vec<Vec<usize>> = vec![];
@@ -20,12 +54,18 @@ pub fn expand_n_contract(
     let (wheel_graph_sign, wheel_graph_vertex_orbits) = wheel_graph.normal_form(false);
     assert!(wheel_graph_sign != 0);
     cocycle_graphs.push(wheel_graph.clone());
-    cocycle_graph_index.insert(wheel_graph, 0);
+    cocycle_graph_index.insert(wheel_graph.clone(), 0);
     cocycle_graph_vertex_orbits.push(wheel_graph_vertex_orbits);
 
+    writeln!(cocycle_graphs_file, "{}", wheel_graph.to_graph6())?;
+
     // Write a placeholder for the header.
     let header_line_length: usize = 64;
-    writeln!(sparse_matrix_file, "{}", "x".repeat(header_line_length))?;
+    writeln!(
+        cocycle_differential_matrix_file,
+        "{}",
+        "x".repeat(header_line_length)
+    )?;
 
     let mut num_nonzeros: usize = 0;
     let mut g_idx: usize = 0;
@@ -45,10 +85,17 @@ pub fn expand_n_contract(
                 cocycle_differential_graphs.push(dg.clone());
                 cocycle_differential_graph_edge_orbits.push(dg_edge_orbits.clone());
                 cocycle_differential_graph_index.insert(dg.clone(), idx);
+                writeln!(cocycle_differential_graphs_file, "{}", dg.to_graph6())?;
                 idx
             };
             // TODO: Make the output lexicographically ordered? Strictly speaking this is not the SMS format right now.
-            writeln!(sparse_matrix_file, "{} {} {}", dg_idx + 1, g_idx + 1, c)?;
+            writeln!(
+                cocycle_differential_matrix_file,
+                "{} {} {}",
+                dg_idx + 1,
+                g_idx + 1,
+                c
+            )?;
             num_nonzeros += 1;
 
             let cg_data: Vec<(UndirectedGraph, Vec<usize>)> = dg.contractions(&dg_edge_orbits);
@@ -60,6 +107,7 @@ pub fn expand_n_contract(
                     cocycle_graphs.push(cg.clone());
                     cocycle_graph_vertex_orbits.push(cg_vertex_orbits);
                     cocycle_graph_index.insert(cg.clone(), idx);
+                    writeln!(cocycle_graphs_file, "{}", cg.to_graph6())?;
                 }
             }
         }
@@ -69,17 +117,15 @@ pub fn expand_n_contract(
             break;
         }
     }
-    writeln!(sparse_matrix_file, "0 0 0")?;
-    sparse_matrix_file.rewind()?;
+    writeln!(cocycle_differential_matrix_file, "0 0 0")?;
+    cocycle_differential_matrix_file.rewind()?;
     let mut header_line: String = format!(
         "{} {} M",
         cocycle_differential_graphs.len(),
         cocycle_graphs.len()
     );
     header_line += &" ".repeat(header_line_length - header_line.len());
-    writeln!(sparse_matrix_file, "{}", header_line)?;
-
-    // TODO: Also output the ordered bases of graphs.
+    writeln!(cocycle_differential_matrix_file, "{}", header_line)?;
 
     Ok((
         cocycle_differential_graphs.len(),
diff --git a/src/main.rs b/src/main.rs
index c7833078877077df059aea003b78a661c77bc6f2..1faa8acafbd367b6a393c1771ef15137ac959ca6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,16 +2,22 @@ mod expand_n_contract;
 mod expand_n_contract_sqlite;
 mod undirected_graph;
 use std::env;
-use std::fs::File;
 use std::process;
 
 fn main() -> std::io::Result<()> {
     let args: Vec<String> = env::args().collect();
+    let num_args: usize = args.len();
 
-    if args.len() != 3 {
+    const NUM_ARGS_FOR_DB: usize = 3;
+    const NUM_ARGS_FOR_TXT: usize = 5;
+
+    if num_args != NUM_ARGS_FOR_DB && num_args != NUM_ARGS_FOR_TXT {
         eprintln!(
-            "Usage: {} <number-of-spokes-in-wheel> <output-filename.txt | output-filename.db>",
-            args[0]
+            "Usage:\n\
+            \x20 {} <number-of-spokes-in-wheel> <output-filename.db>\n\
+            or\n\
+            \x20 {} <number-of-spokes-in-wheel> <cocycle-graphs.txt> <cocycle-differential-graphs.txt> <cocycle-differential-matrix.txt>",
+            args[0], args[0]
         );
         process::exit(1);
     }
@@ -33,9 +39,9 @@ fn main() -> std::io::Result<()> {
         process::exit(1);
     }
 
-    let filename: &String = &args[2];
+    if num_args == NUM_ARGS_FOR_DB {
+        let filename: &String = &args[2];
 
-    if filename.ends_with(".db") {
         let result: Result<(usize, usize, usize), rusqlite::Error> =
             expand_n_contract_sqlite::expand_n_contract(num_spokes, filename);
 
@@ -55,16 +61,18 @@ fn main() -> std::io::Result<()> {
                 ))
             }
         }
-    } else if filename.ends_with(".txt") {
-        let sparse_matrix_file_res: Result<File, std::io::Error> = File::create(filename);
-        if sparse_matrix_file_res.is_err() {
-            eprintln!("Error opening file: {}", filename);
-            process::exit(1);
-        }
-        let mut sparse_matrix_file: File = sparse_matrix_file_res.unwrap();
+    } else if num_args == NUM_ARGS_FOR_TXT {
+        let cocycle_graphs_filename: &String = &args[2];
+        let cocycle_differential_graphs_filename: &String = &args[3];
+        let cocycle_differential_matrix_filename: &String = &args[4];
 
         let result: Result<(usize, usize, usize), std::io::Error> =
-            expand_n_contract::expand_n_contract(num_spokes, &mut sparse_matrix_file);
+            expand_n_contract::expand_n_contract(
+                num_spokes,
+                cocycle_graphs_filename,
+                cocycle_differential_graphs_filename,
+                cocycle_differential_matrix_filename,
+            );
 
         match result {
             Ok((num_rows, num_columns, num_nonzeros)) => {