diff --git a/doc/oper.xml b/doc/oper.xml
index 616a8f609..f41484f4a 100644
--- a/doc/oper.xml
+++ b/doc/oper.xml
@@ -1899,7 +1899,7 @@ fail
the k-closure of digraph is defined to be the unique
smallest symmetric loopless digraph C with no multiple edges on the
vertices of digraph that contains all the edges of digraph
- and satsifies the property that the sum of the degrees of every two
+ and satisfies the property that the sum of the degrees of every two
non-adjacenct vertices in C is less than k. See , , , and .
diff --git a/gap/io.gd b/gap/io.gd
index 4d440cffc..85e340389 100644
--- a/gap/io.gd
+++ b/gap/io.gd
@@ -55,4 +55,6 @@ DeclareOperation("DiSparse6String", [IsDigraph]);
DeclareOperation("PlainTextString", [IsDigraph]);
DeclareOperation("WriteDIMACSDigraph", [IsString, IsDigraph]);
DeclareGlobalFunction("WritePlainTextDigraph");
+DeclareOperation("WriteDreadnautGraph", [IsString, IsDigraph]);
+DeclareOperation("ReadDreadnautGraph", [IsString]);
DeclareGlobalFunction("DigraphPlainTextLineEncoder");
diff --git a/gap/io.gi b/gap/io.gi
index ebf3b0310..c45bbfd02 100644
--- a/gap/io.gi
+++ b/gap/io.gi
@@ -1389,6 +1389,568 @@ function(str)
return ConvertToImmutableDigraphNC(out);
end);
+BindGlobal("DIGRAPHS_ParseDreadnautConfig",
+function(config, key, r)
+ local Pos, tempStr, tempConfig, test, localNewlineCount;
+
+ RemoveCharacters(config, " \r\t=-+");
+
+ tempConfig := ShallowCopy(config);
+ RemoveCharacters(tempConfig, "Ag$ntd1234567890");
+
+ test := PositionProperty(tempConfig, x -> x <> '\n');
+
+ if test <> fail and key <> "f" then
+ ErrorNoReturn("the format of the file given as the 1st argument ",
+ "cannot be determined as it contains an unexpected ",
+ "character: ",
+ tempConfig[test],
+ " on line ", 1 + Length(tempConfig{[1 .. test - 1]}));
+ fi;
+
+ Pos := PositionProperty(config, x -> x = key[1]);
+ localNewlineCount := Length(PositionsProperty(config{[1 .. Pos]},
+ x -> x = '\n'));
+
+ if Pos <> fail then
+ tempStr := "";
+ Pos := Pos + 1;
+
+ while (config[Pos] = '\n') or (Int(config{[Pos]}) <> fail) do
+ tempStr := Concatenation(tempStr, config{[Pos]});
+
+ if key = "f" and config[Pos] = '\n' then
+ r.newlineCount := r.newlineCount + 1;
+ fi;
+
+ Pos := Pos + 1;
+ if Pos > Length(config) then
+ break;
+ fi;
+ od;
+ if tempStr = "" then
+ if key <> "f" then
+ ErrorNoReturn("the format of the file given as the 2nd ",
+ "argument cannot be determined. '", key,
+ "' (line ", localNewlineCount, ")",
+ " is not followed by a value,");
+ else
+ ErrorNoReturn("the partition cannot be determined.",
+ " 'f' (line ", localNewlineCount, ")",
+ " is neither followed",
+ " by a single value nor by a list of values,");
+ fi;
+ fi;
+ RemoveCharacters(tempStr, "\n");
+ return Int(tempStr);
+
+ else
+ if key = "$" then
+ return 0;
+ else
+ ErrorNoReturn("the number of vertices has not been declared. ",
+ "Ensure that ",
+ "n=# is included before the declaration of 'g', ");
+ fi;
+ fi;
+end);
+
+BindGlobal("DIGRAPHS_LegalDreadnautEdge",
+function(vertex, x, r, part)
+ local tempPart;
+
+ tempPart := ShallowCopy(part);
+ RemoveCharacters(tempPart, " ");
+
+ if x > r.nValue or x < 1 then
+ Info(InfoWarning, 1, "Ignoring illegal edge ",
+ vertex + r.dollarValue - 1, " -> ",
+ x + r.dollarValue - 1, " (original indexing) on line ",
+ r.newlineCount, " (original indexing). ");
+ return false;
+ fi;
+ if not r.dExists and x = vertex then
+ Info(InfoWarning, 1, "Ignoring illegal edge ",
+ vertex + r.dollarValue - 1, " -> ",
+ x + r.dollarValue - 1, " (original indexing) on line ",
+ r.newlineCount,
+ ". Ensure 'd' is declared to include loops.");
+ return false;
+ fi;
+ return true;
+end);
+
+BindGlobal("DIGRAPHS_SplitDreadnautLines",
+function(inputString, r)
+ local startPos, currentPos, segments, currentChar, nextChar, index,
+ partition, char, localNewlineCount, temp;
+
+ startPos := 1;
+ segments := [];
+ localNewlineCount := r.newlineCount;
+
+ # Iterate over the string
+ for currentPos in [1 .. Length(inputString) - 1] do
+ currentChar := inputString[currentPos];
+ nextChar := inputString[currentPos + 1];
+
+ if currentChar = '\n' then
+ localNewlineCount := localNewlineCount + 1;
+ continue;
+ fi;
+
+ if currentChar = ';' then
+ Add(segments, inputString{[startPos .. currentPos]});
+ startPos := currentPos + 1;
+ continue;
+ fi;
+
+ if currentChar = '$' and nextChar = '$' then
+ Info(InfoWarning, 1, "Vertex indexing will start at 1");
+ temp := PositionProperty(
+ inputString{[currentPos + 2 .. Length(inputString)]},
+ c -> c in ".:");
+ if temp <> fail then
+ ErrorNoReturn("Syntax error: unexpected characters",
+ "(including '.' or ':')",
+ " after \"$$\" (line ",
+ localNewlineCount + Length(
+ PositionsProperty(
+ inputString{[currentPos + 2 .. temp]},
+ c -> c in "\n")),
+ ")");
+ else
+ Add(segments, inputString{[startPos .. currentPos - 1]});
+ Add(segments, "$$");
+ startPos := currentPos + 2;
+ continue;
+ fi;
+
+ fi;
+
+ if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q" then
+ ErrorNoReturn("while parsing dreadnaut file,",
+ " found operation ",
+ currentChar, " on line ", localNewlineCount,
+ ", which is not supported.");
+ startPos := currentPos + 1;
+ fi;
+
+ if currentChar = 'f' then # partition
+ Add(segments, inputString{[startPos .. currentPos - 1]});
+ if PositionSublist(
+ inputString{[currentPos + 1 .. Length(inputString)]},
+ "[") = fail then
+ if ForAll(inputString{[currentPos + 1 .. Length(inputString)]},
+ c -> c in
+ Concatenation("$ \nferRjstTvfFiIOlw+campyGS*kKVu?&Px@b=[]",
+ "z#oMh<>q0123456789;")) then
+ index := DIGRAPHS_ParseDreadnautConfig(inputString{[currentPos ..
+ Length(inputString)]},
+ "f", r);
+ partition := [r.dollarValue .. r.nValue + r.dollarValue - 1];
+ Remove(partition, index - r.dollarValue + 1);
+
+ Add(segments, Concatenation(
+ Concatenation(
+ Concatenation("f", String(index)),
+ " | "),
+ JoinStringsWithSeparator(partition, " ")));
+
+ startPos := PositionSublist(
+ inputString{[currentPos + 1 .. Length(inputString)]},
+ String(index)) + currentPos + 1;
+ else
+ ErrorNoReturn("Syntax error: Partition defined on line ",
+ localNewlineCount,
+ " and is then followed by unexpected characters (",
+ JoinStringsWithSeparator(
+ Filtered(
+ inputString{[currentPos + 1 .. Length(inputString)]},
+ c -> not c in
+ Concatenation(
+ "$ \nferRjstTvfFiIOlw+campyGS*kKVu?&Px@b=[]",
+ "z#oMh<>q0123456789;")),
+ ","),
+ "), ");
+ fi;
+
+ else
+ repeat
+ currentPos := currentPos + 1;
+ until Int(inputString{[currentPos]}) <> fail;
+ startPos := currentPos;
+ repeat
+ currentPos := currentPos + 1;
+ until currentPos > Length(inputString)
+ or inputString[currentPos] = ']';
+ if currentPos > Length(inputString) then
+ ErrorNoReturn("Syntax error: missing ']'",
+ " in declaration of partition");
+ else
+ if ForAll(inputString{[currentPos + 1 .. Length(inputString)]},
+ c -> c in
+ Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b",
+ "z#oMh<>q0123456789;f[]=")) then
+ Add(segments,
+ Concatenation("f",
+ inputString{[startPos .. currentPos - 1]}));
+ startPos := currentPos + 1;
+ else
+ ErrorNoReturn(
+ "Syntax error: partition defined on line ",
+ localNewlineCount,
+ " and is then followed by unexpected characters (",
+ JoinStringsWithSeparator(
+ Filtered(
+ inputString{[currentPos + 1 .. Length(inputString)]},
+ c -> not c in
+ Concatenation(
+ "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b",
+ "z#oMh<>q0123456789;f[]=")),
+ ","),
+ "), ");
+ fi;
+ fi;
+ fi;
+ fi;
+
+ if currentChar = ':' then
+ repeat # backtrack to find the start of the vertex
+ currentPos := currentPos - 1;
+ if (inputString[currentPos] in " \n") <> true and
+ not IsDigitChar(inputString[currentPos]) then
+ ErrorNoReturn("Syntax error: (line ",
+ r.newlineCount + Length(PositionsProperty(
+ inputString{[1 .. currentPos]},
+ x -> x in "\n")),
+ ") unexpected character (",
+ inputString[currentPos],
+ ") before \":\"");
+ fi;
+ until currentPos <= 1 or IsDigitChar(inputString[currentPos]);
+ repeat
+ currentPos := currentPos - 1;
+ until currentPos <= 1 or (not IsDigitChar(inputString[currentPos]));
+ if startPos < currentPos then
+ Add(segments, inputString{[startPos .. currentPos - 1]});
+ fi;
+ if currentPos > 1 then
+ startPos := currentPos;
+ fi;
+ fi;
+ od;
+
+ if ForAny(inputString{[startPos .. Length(inputString)]},
+ # change this to looping over i
+ c -> c in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q") then
+ for char in Filtered(inputString{[startPos .. Length(inputString)]},
+ c -> c in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q") do
+ temp := PositionSublist(inputString{[startPos .. Length(inputString)]},
+ [char]);
+ Info(InfoWarning, 1, "while parsing dreadnaut file, found operation ",
+ char,
+ "') on line ",
+ Length(PositionsProperty(
+ inputString{[1 .. temp]}, x -> x in "\n")),
+ ", which is not supported.");
+ od;
+ else
+ Add(segments, inputString{[startPos .. Length(inputString)]});
+ fi;
+ return segments;
+end);
+
+BindGlobal("DIGRAPHS_ParseDreadnautGraph",
+function(graphData, r)
+ local edgeList, part, parts, subparts, vertex, connectedTo,
+ adjacencyPart, pparts, partition, i, j, num, iter,
+ pos, char, localNewlineCount, failure, temp, vertices,
+ components, p, runningSemi, lastVertex;
+
+ edgeList := List([1 .. r.nValue], x -> []);
+ RemoveCharacters(graphData, "\r\t");
+ parts := DIGRAPHS_SplitDreadnautLines(graphData, r);
+ runningSemi := false;
+ iter := 0;
+ localNewlineCount := r.newlineCount;
+ lastVertex := 0;
+
+ for part in parts do
+ iter := iter + 1;
+
+ pos := PositionSublist(part, ".");
+
+ if pos <> fail then
+ part := Concatenation(part{[1 .. pos - 1]},
+ Filtered(part{[pos .. Length(part)]},
+ x -> not IsDigitChar(x)));
+ RemoveCharacters(part, ".");
+ if ForAny(parts{[iter + 1 .. Length(parts)]},
+ c -> (':' in c or '.' in c)) then
+ ErrorNoReturn("Syntax error: unexpected characters (including ':'",
+ " or '.') after \".\"",
+ "(note that edges cannot be declared after \".\")");
+ fi;
+ fi;
+
+ if part = "" or part = ' ' or part = " " or part = '\n' then
+ continue;
+ fi;
+
+ if '$' in part then
+ if ForAny(part{[iter + 1 .. Length(part)]}, c -> c in ".:") then
+ ErrorNoReturn("Syntax error: unexpected characters (including ':'",
+ "or '.') after \".\"",
+ "(note that edges cannot be declared after vertex",
+ " reindexing)");
+ fi;
+
+ if part = "$$" then
+ r.dollarValue := 0;
+ else
+ r.dollarValue := DIGRAPHS_ParseDreadnautConfig(part, "$", r);
+ fi;
+ fi;
+
+ if part[1] = 'f' then
+ if Length(part) = 1 then # empty partition
+ continue;
+ fi;
+
+ pparts := SplitString(part{[2 .. Length(part)]}, "|");
+ partition := List([1 .. r.nValue], x -> -1);
+ pparts[Length(pparts)] := Concatenation(pparts[Length(pparts)], " ");
+ for i in [1 .. Length(pparts)] do
+ num := "";
+ for j in pparts[i] do
+ if IsDigitChar(j) then
+ num := Concatenation(num, [j]);
+
+ elif j <> ' ' and j <> '\n' then
+ ErrorNoReturn("illegal character ", j, " in partition");
+
+ else
+ if num <> "" then
+ num := Int(num) - r.dollarValue + 1;
+ if num > r.nValue or num < 1 then
+ ErrorNoReturn("illegal part ",
+ num + r.dollarValue - 1,
+ " in partition");
+ else
+ partition[num] := i;
+ fi;
+ num := "";
+ fi;
+ fi;
+ od;
+ od;
+
+ if - 1 in partition then
+ ErrorNoReturn("partition is incomplete. The following vertices ",
+ PositionsProperty(partition, x -> x = -1),
+ "(1-indexed) do not feature in any part.");
+ else
+ r.partition := partition;
+ fi;
+ continue;
+ fi;
+
+ subparts := SplitString(part, ":");
+
+ if Length(subparts) = 0 then
+ continue;
+ elif Length(subparts) = 1 then
+ if PositionSublist(" $$;", subparts[1]) <> fail then
+ continue;
+ elif Length(PositionsProperty(subparts[1],
+ x -> x = '\n')) = Length(subparts[1]) then
+ localNewlineCount := localNewlineCount + Length(subparts[1]);
+ continue;
+ elif runningSemi then
+ adjacencyPart := subparts[1];
+ vertices := [lastVertex + 1];
+ if lastVertex = r.nValue - r.dollarValue + 1 then
+ ErrorNoReturn("formatting error ('", part, "'),");
+ fi;
+ else
+ ErrorNoReturn("formatting error ('", part, "'),");
+ fi;
+ else
+ vertices := [];
+ components := SplitString(subparts[1], "\n");
+
+ for i in [1 .. Length(components)] do
+ for p in SplitString(components[i], " ") do
+ if p = "" then
+ continue;
+ fi;
+ if not ForAll(p, IsDigitChar) then
+ ErrorNoReturn("Formatting error: ", subparts[1],
+ " on line ", localNewlineCount);
+ else
+ Add(vertices, Int(p) - r.dollarValue + 1);
+ fi;
+ od;
+
+ localNewlineCount := localNewlineCount + 1;
+ od;
+ r.newlineCount := localNewlineCount;
+ adjacencyPart := subparts[2];
+ fi;
+
+ for vertex in vertices do
+
+ if vertex > r.nValue or vertex < 1 then
+ # shouldn't this be vertex + r.dollarValue - 1?
+ Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex,
+ " (reindexed) on line ", localNewlineCount);
+ continue;
+ fi;
+
+ od;
+
+ if PositionSublist(adjacencyPart, ";") <> fail then
+ runningSemi := true;
+ fi;
+
+ RemoveCharacters(adjacencyPart, ",;");
+ connectedTo := [];
+ temp := "";
+
+ for char in adjacencyPart do
+ if char = '\n' then
+ localNewlineCount := localNewlineCount + 1;
+ if temp <> "" then
+ Add(connectedTo, Int(temp));
+ temp := "";
+ fi;
+ elif char = ' ' then
+ if temp <> "" then
+ Add(connectedTo, Int(temp));
+ temp := "";
+ fi;
+ continue;
+ else
+ if IsDigitChar(char) then
+ temp := Concatenation(temp, [char]);
+ else
+ ErrorNoReturn("formatting error (", part, ") on line ",
+ localNewlineCount);
+ fi;
+ fi;
+ od;
+ if temp <> "" then
+ Add(connectedTo, Int(temp));
+ fi;
+
+ failure := PositionProperty(connectedTo, x -> x = fail);
+ if failure <> fail then
+ ErrorNoReturn("Formatting error (", part, ") on line ",
+ localNewlineCount + Length(
+ PositionProperty(adjacencyPart{[1 .. failure]},
+ x -> x = '\n')));
+ fi;
+
+ connectedTo := List(connectedTo, x -> x - r.dollarValue + 1);
+
+ for vertex in vertices do
+ connectedTo := Filtered(connectedTo,
+ x -> DIGRAPHS_LegalDreadnautEdge(vertex,
+ x, r, part));
+
+ Append(edgeList[vertex], connectedTo);
+ edgeList[vertex] := DuplicateFreeList(edgeList[vertex]);
+ od;
+ lastVertex := vertex;
+ od;
+
+ return edgeList;
+end);
+
+InstallMethod(ReadDreadnautGraph, "for a digraph", [IsString],
+function(name)
+ local file, config, graphData, line, edgeList, foundG, r, D, exclamPosition;
+ file := IO_CompressedFile(UserHomeExpand(name), "r");
+
+ if file = fail then
+ ErrorNoReturn("cannot open the file given as the 1st argument , \"",
+ name,
+ "\",");
+ fi;
+
+ config := "";
+ foundG := false;
+
+ # Read file line by line until 'g' is found
+ repeat
+ line := IO_ReadLine(file);
+ if not IsEmpty(line) then
+ exclamPosition := PositionSublist(line, "!");
+ if exclamPosition <> fail and exclamPosition > 1 then
+ line := line{[1 .. exclamPosition - 1]};
+ elif exclamPosition = 1 then
+ continue;
+ fi;
+ config := Concatenation(config, line);
+ foundG := PositionSublist(line, "g") <> fail;
+ fi;
+ until foundG or IsEmpty(line);
+
+ if not foundG then
+ ErrorNoReturn("'g' not declared");
+ fi;
+
+ config := SplitString(config, "g")[1];
+ graphData := line{[PositionSublist(line, "g") + 1 .. Length(line)]};
+
+ repeat
+ line := IO_ReadLine(file);
+ if not IsEmpty(line) then
+ exclamPosition := PositionSublist(line, "!");
+ if exclamPosition <> fail and exclamPosition > 1 then
+ line := line{[1 .. exclamPosition - 1]};
+ elif exclamPosition = 1 then
+ continue;
+ fi;
+ graphData := Concatenation(graphData, line);
+ fi;
+ until IsEmpty(line);
+
+ file := IO_CompressedFile(UserHomeExpand(name), "r");
+
+ r := rec(dExists := PositionSublist(config, "d") <> fail,
+ partition := fail,
+ newlineCount := 1 + Length(PositionsProperty(config, x -> x = '\n')));
+
+ r.configNewlineCount := r.newlineCount;
+ r.dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$", r);
+ r.nValue := DIGRAPHS_ParseDreadnautConfig(config, "n", r);
+
+ if r.dollarValue <> 1 then
+ Info(InfoWarning, 1,
+ "The graph will be reindexed such that the indexing starts",
+ " at 1. i.e. effectively adding $=1 to the end of the file.");
+ fi;
+
+ edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r);
+
+ if r.dExists then
+ D := Digraph(edgeList);
+ if r.partition <> fail then
+ SetDigraphVertexLabels(D, r.partition);
+ fi;
+ else
+ Info(InfoWarning, 1,
+ "The graph is undirected and so will be symmetrised.");
+ D := DigraphSymmetricClosure(Digraph(edgeList));
+ if r.partition <> fail then
+ SetDigraphVertexLabels(D, r.partition);
+ fi;
+ fi;
+ return D;
+end);
+
################################################################################
# 4. Encoders
################################################################################
@@ -1459,6 +2021,70 @@ function(name, D)
return IO_OK;
end);
+InstallMethod(WriteDreadnautGraph, "for a digraph", [IsString, IsDigraph],
+function(name, D)
+ local file, n, verts, nbs, labels, i, degs, filteredVerts,
+ out, positions, joinedPositions, dflabels;
+
+ file := IO_CompressedFile(UserHomeExpand(name), "w");
+ if file = fail then
+ ErrorNoReturn("cannot open the file given as the 1st argument , \"",
+ name,
+ "\",");
+ fi;
+
+ n := DigraphNrVertices(D);
+ verts := DigraphVertices(D);
+ nbs := OutNeighbours(D);
+ degs := OutDegrees(D);
+ labels := DigraphVertexLabels(D);
+
+ if n = 0 then
+ ErrorNoReturn("the 2nd argument must be a non-empty digraph,");
+ fi;
+
+ IO_WriteLine(file, "d");
+ IO_WriteLine(file, "$=1");
+ IO_WriteLine(file, Concatenation("n=", String(n)));
+ IO_WriteLine(file, "g");
+
+ filteredVerts := Filtered(verts, x -> degs[x] > 0);
+ for i in filteredVerts do
+ labels := List(nbs[i], String);
+ IO_WriteLine(file, Concatenation(String(i), " : ",
+ JoinStringsWithSeparator(labels, " "), ";"));
+ od;
+ IO_WriteLine(file, ".");
+
+ if labels <> [1 .. n] then
+ dflabels := DuplicateFreeList(labels);
+ if ForAll(dflabels, IsInt) then
+ out := "f = [";
+
+ for i in dflabels do
+ positions := PositionsProperty(labels, x -> x = i);
+ joinedPositions := JoinStringsWithSeparator(positions, " ");
+ out := Concatenation(out, joinedPositions);
+ if i <> dflabels[Length(dflabels)] then
+ out := Concatenation(out, " | ");
+ fi;
+ od;
+ out := Concatenation(out, " ]");
+
+ IO_WriteLine(file, out);
+ else
+ Info(InfoDigraphs, 1,
+ "Only integer vertex labels are supported by the dreadnaut format.");
+ Info(InfoDigraphs, 1,
+ "The vertex labels of the 2nd argument ",
+ " will not be saved.");
+ fi;
+ fi;
+
+ IO_Close(file);
+ return;
+end);
+
InstallGlobalFunction(DigraphPlainTextLineEncoder,
{delimiter1, delimiter2, offset} ->
function(D)
diff --git a/tst/standard/io.tst b/tst/standard/io.tst
index ad77eec19..a1c5ddadc 100644
--- a/tst/standard/io.tst
+++ b/tst/standard/io.tst
@@ -923,6 +923,63 @@ gap> filename := Concatenation(DIGRAPHS_Dir(), "/tst/out/test.p");;
gap> ReadDigraphs(filename, IO_Unpickle);
[ ]
+# WriteDreadnautGraph
+gap> gr := EmptyDigraph(0);;
+gap> filename := "does/not/exist.dre";;
+gap> WriteDreadnautGraph(filename, gr);
+Error, cannot open the file given as the 1st argument , "does/not/exist.\
+dre",
+gap> WriteDreadnautGraph(filename, 0);
+Error, no method found! For debugging hints type ?Recovery from NoMethodFound
+Error, no 1st choice method found for `WriteDreadnautGraph' on 2 arguments
+gap> WriteDreadnautGraph(".", RandomDigraph(2));
+Error, cannot open the file given as the 1st argument , ".",
+gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/temp.dre");;
+gap> D := CompleteDigraph(3);;
+gap> WriteDreadnautGraph(filename, D);
+
+# ReadDreadnautGraph
+gap> ReadDreadnautGraph(filename) = D;
+true
+gap> ReadDreadnautGraph("fakedir.dre");
+Error, cannot open the file given as the 1st argument , "fakedir.dre",
+gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/bad.dre");;
+gap> file := IO_CompressedFile(UserHomeExpand(filename), "w");;
+gap> IO_WriteLine(file, "$1n3");;
+gap> IO_WriteLine(file, "dg");;
+gap> IO_WriteLine(file, "1:1;");;
+gap> IO_WriteLine(file, "2:21");;
+gap> IO_Close(file);;
+gap> ReadDreadnautGraph(filename);
+
+gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/temp.dre");;
+gap> D := EmptyDigraph(5);;
+gap> WriteDreadnautGraph(filename, D);;
+gap> D = ReadDreadnautGraph(filename);
+true
+gap> D := Digraph([[3, 5, 10], [9, 8, 10], [4], [6], [7, 11], [7], [8], [], [11], [], []]);;
+gap> WriteDreadnautGraph(filename, D);;
+gap> D = ReadDreadnautGraph(filename);
+true
+gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/repeats.dre");;
+gap> file := IO_CompressedFile(UserHomeExpand(filename), "w");;
+gap> IO_WriteLine(file, "$=1n=3-d");;
+gap> IO_WriteLine(file, "g1 : 1 2 3 1 2;");;
+gap> IO_WriteLine(file, " 2 : 1 2;");;
+gap> IO_WriteLine(file, " 3 : 2;");;
+gap> IO_Close(file);;
+gap> ReadDreadnautGraph(filename);
+
+gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/temp.dre");;
+gap> file := IO_CompressedFile(UserHomeExpand(filename), "w");;
+gap> IO_WriteLine(file, "silly text for testing");;
+gap> IO_WriteLine(file, "n=1dg");;
+gap> IO_WriteLine(file, "1: 1.");;
+gap> IO_Close(file);;
+gap> ReadDreadnautGraph(filename);
+Error, the format of the file given as the 1st argument cannot be deter\
+mined as it contains an unexpected character: 's' on line 1
+
# DIGRAPHS_UnbindVariables
gap> Unbind(D);
gap> Unbind(badfilename);