From 2dea414a624c10408f60c3ab27f1f4802c5b756e Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:17:07 +0000 Subject: [PATCH 01/55] Encoder function w/out tests --- gap/io.gi | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/gap/io.gi b/gap/io.gi index ebf3b0310..0640b165f 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1459,6 +1459,37 @@ function(name, D) return IO_OK; end); +InstallMethod(WriteDreadnautGraph, "for a digraph", [IsString, IsDigraph], +function(name, D) + local file, n, verts, nbs, labels, i, j; + + file := IO_CompressedFile(UserHomeExpand(name), "w"); + if file = fail then + ErrorNoReturn("cannot open the file given as the 1st argument ,"); + fi; + + n := DigraphNrVertices(D); + verts := DigraphVertices(D); + nbs := OutNeighbours(D); + + + IO_WriteLine(file, "d"); + IO_WriteLine(file, "$=1"); + + IO_WriteLine(file, Concatenation("n=", String(n))); + + IO_WriteLine(file, "g"); + for i in [1 .. n] do + labels := List(nbs[i], j -> String(j)); + IO_WriteLine(file, Concatenation(String(i), ":", JoinStringsWithSeparator(labels, " "), ";")); + od; + + IO_WriteLine(file, "."); + + IO_Close(file); + return; +end); + InstallGlobalFunction(DigraphPlainTextLineEncoder, {delimiter1, delimiter2, offset} -> function(D) From a11aa5074962aa7f6fe49f96a6099b32224748fa Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 20 Mar 2024 00:06:52 +0000 Subject: [PATCH 02/55] WriteDreadnautGraph bug fix and prelim tests --- gap/io.gi | 12 +++++++++--- tst/standard/io.tst | 10 ++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 0640b165f..ecbaad31d 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1468,10 +1468,18 @@ function(name, D) ErrorNoReturn("cannot open the file given as the 1st argument ,"); fi; + if not IsDigraph(D) then + ErrorNoReturn("the 2nd argument must be a digraph,"); + fi; + n := DigraphNrVertices(D); verts := DigraphVertices(D); nbs := OutNeighbours(D); + if n = 0 then + ErrorNoReturn("the 2nd argument must be a non-empty digraph,"); + fi; + IO_WriteLine(file, "d"); IO_WriteLine(file, "$=1"); @@ -1481,10 +1489,8 @@ function(name, D) IO_WriteLine(file, "g"); for i in [1 .. n] do labels := List(nbs[i], j -> String(j)); - IO_WriteLine(file, Concatenation(String(i), ":", JoinStringsWithSeparator(labels, " "), ";")); + IO_WriteLine(file, Concatenation(String(i), " : ", JoinStringsWithSeparator(labels, " "), ";")); od; - - IO_WriteLine(file, "."); IO_Close(file); return; diff --git a/tst/standard/io.tst b/tst/standard/io.tst index ad77eec19..9adda1dff 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -923,6 +923,16 @@ 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, the 2nd argument must be a non-empty digraph +gap> WriteDreadnautGraph(filename, 0); +Error, the 2nd argument must be a digraph +gap> WriteDreadnautGraph(".", RandomDigraph(2)); +Error, cannot open the file given as the 1st argument + # DIGRAPHS_UnbindVariables gap> Unbind(D); gap> Unbind(badfilename); From 3e1087fdecebd717b136c7f32f859a67a3e3cfa3 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:15:55 +0000 Subject: [PATCH 03/55] ReadDreadnaut with tests passed --- gap/io.gd | 1 + gap/io.gi | 5 +---- tst/standard/io.tst | 12 +++++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/gap/io.gd b/gap/io.gd index 4d440cffc..3a9110120 100644 --- a/gap/io.gd +++ b/gap/io.gd @@ -55,4 +55,5 @@ DeclareOperation("DiSparse6String", [IsDigraph]); DeclareOperation("PlainTextString", [IsDigraph]); DeclareOperation("WriteDIMACSDigraph", [IsString, IsDigraph]); DeclareGlobalFunction("WritePlainTextDigraph"); +DeclareOperation("WriteDreadnautGraph", [IsString, IsDigraph]); DeclareGlobalFunction("DigraphPlainTextLineEncoder"); diff --git a/gap/io.gi b/gap/io.gi index ecbaad31d..b67a8499d 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1468,9 +1468,6 @@ function(name, D) ErrorNoReturn("cannot open the file given as the 1st argument ,"); fi; - if not IsDigraph(D) then - ErrorNoReturn("the 2nd argument must be a digraph,"); - fi; n := DigraphNrVertices(D); verts := DigraphVertices(D); @@ -1493,7 +1490,7 @@ function(name, D) od; IO_Close(file); - return; + return IO_OK; end); InstallGlobalFunction(DigraphPlainTextLineEncoder, diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 9adda1dff..3ad9951a2 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -927,11 +927,17 @@ gap> ReadDigraphs(filename, IO_Unpickle); gap> gr := EmptyDigraph(0);; gap> filename := "does/not/exist.dre";; gap> WriteDreadnautGraph(filename, gr); -Error, the 2nd argument must be a non-empty digraph +Error, cannot open the file given as the 1st argument , gap> WriteDreadnautGraph(filename, 0); -Error, the 2nd argument must be a digraph +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 +Error, cannot open the file given as the 1st argument , +gap> filename := "tmp.dre";; +gap> D := CompleteDigraph(3);; +gap> WriteDreadnautGraph(filename, CompleteDigraph(3)); +IO_OK +gap> Exec("rm -f tmp.dre"); # DIGRAPHS_UnbindVariables gap> Unbind(D); From b533858be0b0fc9fab6bf92079e40fccc538c141 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:41:25 +0000 Subject: [PATCH 04/55] mend --- gap/io.gd | 1 + gap/io.gi | 121 ++++++++++++++++++++++++++++++++++++++++++++ tst/standard/io.tst | 8 ++- 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/gap/io.gd b/gap/io.gd index 3a9110120..85e340389 100644 --- a/gap/io.gd +++ b/gap/io.gd @@ -56,4 +56,5 @@ 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 b67a8499d..0d7496c4f 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1389,6 +1389,127 @@ function(str) return ConvertToImmutableDigraphNC(out); end); +InstallGlobalFunction(ReadDreadnautGraph, "for a digraph", [IsString], +function(name) + local file + file := IO_CompressedFile(UserHomeExpand(name), "r"); + + if file = fail then + ErrorNoReturn("cannot open the file given as the 1st argument ,"); + fi; + + # Initialize variables + content := ""; + foundG := false; + configEndIndex := 0; + + # Read file line by line until 'g' is found + repeat + line := ReadLine(file); + if not IsEOF(line) then + content := Concatenation(content, line, "\n"); # Keep newlines for clarity + if PositionSublist(line, 'g') <> fail; then + foundG := true; # Mark that 'g' has been found + configEndIndex := Length(content); + fi; + fi; + until foundG or IsEOF(line); + + if not foundG then + ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); + fi; + # Split the content + config := Substring(content, 1, configEndIndex); + graphData := Substring(content, configEndIndex + 1, Length(content)); + + rconf := ParseDreadnautConfig(config); + if rconf.dExists then + edgeList := ParseDreadnautGraph(graphData); + return Digraph(edgeList); + else + return DigraphSymmetricClosure(Digraph(edgeList)); +) + + +BindGlobal("ParseDreadnautConfig", function(config) + local nValue, dExists, dollarValue, startPos, endPos, tempStr; + + dollarValue := fail; + nValue := fail; + dExists := false; + + # Search for the '$' part, if present + startPos := PositionSublist(config, "$"); + if startPos <> fail then + # Assuming the value follows immediately or after an equals sign + tempStr := Substring(config, startPos + 1, Length(config)); + if First(tempStr) = '=' then + tempStr := Rest(tempStr); # Skip '=' + fi; + endPos := PositionSublist(tempStr, " "); + if endPos = fail then + endPos := Length(tempStr) + 1; # Use the rest of the string + fi; + dollarValue := Substring(tempStr, 1, endPos - 1); + fi; + + # Search for the 'n' part + startPos := PositionSublist(config, "n"); + if startPos <> fail then + tempStr := Substring(config, startPos + 1, Length(config)); # Skip 'n' + if First(tempStr) = '=' then + tempStr := Rest(tempStr); # Skip '=' + fi; + endPos := Minimum([PositionSublist(tempStr, " "), PositionSublist(tempStr, "g"), Length(tempStr) + 1]) - 1; + nValue := Int(Substring(tempStr, 1, endPos)); + if nValue = fail then + Error("Invalid 'n' value."); + fi; + else + Error("The 'n' part is required but was not found."); + fi; + + # Check if the 'd' part exists + dExists := PositionSublist(config, "d") <> fail; + + return rec(dollarPart := dollarValue, nValue := nValue, dExists := dExists); +end); + +BindGlobal("ParseDreadnautGraph", function(graphData) + local lines, digraph, edgeList, i, line, parts, vertex, connectedTo; + + # Split the graph data into lines + lines := SplitString(graphData, "\n"); + + # Initialize an empty list to hold the edges + edgeList := []; + + # Iterate over each line to extract edges + for i in [1..Length(lines)] do + line := lines[i]; + if IsEmpty(line) or line = "\n" then + continue; + fi; + + # if line[Length(line)] = "." then + # line := Substring(line, 1, Length(line) - 1); + # fi; + + parts := SplitString(line, ":"); + vertex := Int(parts[1]); + connectedTo := List([2..Length(parts)-1], x -> Int(parts[x])); + # Assuming -1 marks the end of the list + Remove(connectedTo, -1); + for j in connectedTo do + Add(edgeList, [vertex, j]); + od; + od; + + # Construct the digraph from the edge list + return edgeList; +end); + + ################################################################################ # 4. Encoders ################################################################################ diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 3ad9951a2..16c06c574 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -936,9 +936,15 @@ Error, cannot open the file given as the 1st argument , gap> filename := "tmp.dre";; gap> D := CompleteDigraph(3);; gap> WriteDreadnautGraph(filename, CompleteDigraph(3)); -IO_OK gap> Exec("rm -f tmp.dre"); +# ReadDreadnautGraph +gap> filename := "tmp.dre";; +gap> D = CompleteDigraph(3);; +gap> WriteDreadnautGraph(filename, D); +gap> ReadDreadnautGraph(filename, D); + + # DIGRAPHS_UnbindVariables gap> Unbind(D); gap> Unbind(badfilename); From 8ef4d97c4a8bc0b596008d4d31271cab88d21f4a Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:42:11 +0000 Subject: [PATCH 05/55] ReadDreadnaut (untested) --- gap/io.gi | 175 ++++++++++++++++++++++++-------------------- tst/standard/io.tst | 1 + 2 files changed, 97 insertions(+), 79 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 0d7496c4f..6b98fd66d 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1391,44 +1391,52 @@ end); InstallGlobalFunction(ReadDreadnautGraph, "for a digraph", [IsString], function(name) - local file + local file config graphData line edgeList foundG configEndIndex; file := IO_CompressedFile(UserHomeExpand(name), "r"); if file = fail then ErrorNoReturn("cannot open the file given as the 1st argument ,"); fi; - # Initialize variables - content := ""; - foundG := false; - configEndIndex := 0; + # Initialize variables + config := ""; + foundG := false; + configEndIndex := 0; - # Read file line by line until 'g' is found - repeat - line := ReadLine(file); - if not IsEOF(line) then - content := Concatenation(content, line, "\n"); # Keep newlines for clarity - if PositionSublist(line, 'g') <> fail; then - foundG := true; # Mark that 'g' has been found - configEndIndex := Length(content); - fi; - fi; - until foundG or IsEOF(line); + # Read file line by line until 'g' is found + repeat + line := IO_ReadLine(file); + if not IsEmpty(line) then + config := Concatenation(config, line); # Keep newlines for clarity + if PositionSublist(line, "g") <> fail then + foundG := true; # Mark that 'g' has been found + configEndIndex := Length(config); + fi; + fi; + until foundG or IsEmpty(line); + + if not foundG then + ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); + fi; + # Split the content + graphData := ""; + + repeat + line := IO_ReadLine(file); + if not IsEmpty(line) then + graphData := Concatenation(graphData, line); # Keep newlines for clarity + fi; + until IsEmpty(line); + + #if "d" is in config, then the graph is directed + if PositionSublist(config, "d") <> fail then + edgeList := DIGRAPHS_ParseDreadnautGraph(graphData); + return Digraph(edgeList); + else + return DigraphSymmetricClosure(Digraph(edgeList)); + fi; +end); - if not foundG then - ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); - fi; - # Split the content - config := Substring(content, 1, configEndIndex); - graphData := Substring(content, configEndIndex + 1, Length(content)); - - rconf := ParseDreadnautConfig(config); - if rconf.dExists then - edgeList := ParseDreadnautGraph(graphData); - return Digraph(edgeList); - else - return DigraphSymmetricClosure(Digraph(edgeList)); -) BindGlobal("ParseDreadnautConfig", function(config) @@ -1436,47 +1444,37 @@ BindGlobal("ParseDreadnautConfig", function(config) dollarValue := fail; nValue := fail; - dExists := false; - - # Search for the '$' part, if present - startPos := PositionSublist(config, "$"); - if startPos <> fail then - # Assuming the value follows immediately or after an equals sign - tempStr := Substring(config, startPos + 1, Length(config)); - if First(tempStr) = '=' then - tempStr := Rest(tempStr); # Skip '=' - fi; - endPos := PositionSublist(tempStr, " "); - if endPos = fail then - endPos := Length(tempStr) + 1; # Use the rest of the string - fi; - dollarValue := Substring(tempStr, 1, endPos - 1); - fi; - - # Search for the 'n' part - startPos := PositionSublist(config, "n"); - if startPos <> fail then - tempStr := Substring(config, startPos + 1, Length(config)); # Skip 'n' - if First(tempStr) = '=' then - tempStr := Rest(tempStr); # Skip '=' - fi; - endPos := Minimum([PositionSublist(tempStr, " "), PositionSublist(tempStr, "g"), Length(tempStr) + 1]) - 1; - nValue := Int(Substring(tempStr, 1, endPos)); - if nValue = fail then - Error("Invalid 'n' value."); - fi; - else - Error("The 'n' part is required but was not found."); - fi; + dExists := PositionSublist(config, "d"); + + for char in ["n","$"] do + startPos := PositionSublist(config, char); + if startPos <> fail then + # Assuming the value follows immediately or after an equals sign + tempStr := config{[startPos+1..startPos+2]}; + if char = "$" then + if First(tempStr) = '=' then + dollarValue := tempStr[2]; + else + dollarValue := tempStr[1]; + fi; + else + if First(tempStr) = '=' then + nValue := tempStr[2]; + else + nValue := tempStr[1]; + fi; + fi; - # Check if the 'd' part exists - dExists := PositionSublist(config, "d") <> fail; + else + ErrorNoReturn(StringFormatted("{} not specified.", char)); + fi; + od; return rec(dollarPart := dollarValue, nValue := nValue, dExists := dExists); end); -BindGlobal("ParseDreadnautGraph", function(graphData) - local lines, digraph, edgeList, i, line, parts, vertex, connectedTo; +BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData) + local lines, digraph, edgeList, i, line, parts, vertex, connectedTo, adjacencyPart, flag; # Split the graph data into lines lines := SplitString(graphData, "\n"); @@ -1484,32 +1482,51 @@ BindGlobal("ParseDreadnautGraph", function(graphData) # Initialize an empty list to hold the edges edgeList := []; + flag = false; + # Iterate over each line to extract edges for i in [1..Length(lines)] do line := lines[i]; if IsEmpty(line) or line = "\n" then - continue; + continue; # Skip empty lines fi; - # if line[Length(line)] = "." then - # line := Substring(line, 1, Length(line) - 1); - # fi; - + if PositionSublist(line, ".") <> fail then + flag = true; + fi; + + # Separate the vertex identifier from its adjacency list + # Remove spaces around ':' to consistently identify the split point + line := ReplacedString(line, " :", ":"); + line := ReplacedString(line, ": ", ":"); parts := SplitString(line, ":"); + + # Extract the vertex number and its adjacency list vertex := Int(parts[1]); - connectedTo := List([2..Length(parts)-1], x -> Int(parts[x])); - # Assuming -1 marks the end of the list - Remove(connectedTo, -1); - for j in connectedTo do - Add(edgeList, [vertex, j]); - od; + adjacencyPart := parts[2]; + + # Handle the adjacency list, terminating with ';' + adjacencyPart := ReplacedString(adjacencyPart, ";", " "); # Replace ';' with space for uniform splitting + NormalizeWhitespace(adjacencyPart); # Remove extra spaces + connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); + Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included + + # Add edges to the edge list + Add(edgeList, connectedTo); + + if flag then + for j in [1..Length(lines)-i] do + Add(edgeList, []); + od; + break; + fi; od; - # Construct the digraph from the edge list return edgeList; end); + ################################################################################ # 4. Encoders ################################################################################ @@ -1611,7 +1628,7 @@ function(name, D) od; IO_Close(file); - return IO_OK; + return; end); InstallGlobalFunction(DigraphPlainTextLineEncoder, diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 16c06c574..d5fbca2c1 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -944,6 +944,7 @@ gap> D = CompleteDigraph(3);; gap> WriteDreadnautGraph(filename, D); gap> ReadDreadnautGraph(filename, D); +gap> Exec("rm -f tmp.dre"); # DIGRAPHS_UnbindVariables gap> Unbind(D); From 781520b875d89489dd9e61a92eebc9b9bd4b7d19 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 21 Mar 2024 22:42:24 +0000 Subject: [PATCH 06/55] working functions, tests needed --- gap/io.gi | 171 ++++++++++++++++++++++---------------------- tst/standard/io.tst | 4 +- 2 files changed, 89 insertions(+), 86 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 6b98fd66d..819888892 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1389,92 +1389,42 @@ function(str) return ConvertToImmutableDigraphNC(out); end); -InstallGlobalFunction(ReadDreadnautGraph, "for a digraph", [IsString], -function(name) - local file config graphData line edgeList foundG configEndIndex; - file := IO_CompressedFile(UserHomeExpand(name), "r"); - - if file = fail then - ErrorNoReturn("cannot open the file given as the 1st argument ,"); - fi; - - # Initialize variables - config := ""; - foundG := false; - configEndIndex := 0; - - # Read file line by line until 'g' is found - repeat - line := IO_ReadLine(file); - if not IsEmpty(line) then - config := Concatenation(config, line); # Keep newlines for clarity - if PositionSublist(line, "g") <> fail then - foundG := true; # Mark that 'g' has been found - configEndIndex := Length(config); - fi; - fi; - until foundG or IsEmpty(line); - - if not foundG then - ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); - fi; - # Split the content - graphData := ""; - - repeat - line := IO_ReadLine(file); - if not IsEmpty(line) then - graphData := Concatenation(graphData, line); # Keep newlines for clarity - fi; - until IsEmpty(line); - - #if "d" is in config, then the graph is directed - if PositionSublist(config, "d") <> fail then - edgeList := DIGRAPHS_ParseDreadnautGraph(graphData); - return Digraph(edgeList); - else - return DigraphSymmetricClosure(Digraph(edgeList)); - fi; -end); - - - -BindGlobal("ParseDreadnautConfig", function(config) - local nValue, dExists, dollarValue, startPos, endPos, tempStr; +BindGlobal("DIGRAPHS_ParseDreadnautConfig", +function(config) + local nValue, dExists, dollarValue, tempStr, Pos, getValue; + + + config := ReplacedString(config, " ", ""); # Remove spaces + config := ReplacedString(config, "\n", ""); # Remove newlines + config := ReplacedString(config, "\r", ""); # Remove carriage returns + config := ReplacedString(config, "\t", ""); # Remove tabs + config := ReplacedString(config, "=", ""); + + getValue := function(config, key) + local Pos, tempStr; + Pos := PositionSublist(config, key) + 1; + tempStr := ""; + + while IsInt(Int(config{[Pos]})) do + Concatenation(tempStr, config{[Pos]}); + Pos := Pos + 1; + if Pos > Length(config) then + break; + fi; + od; + return Int(tempStr); + end; - dollarValue := fail; - nValue := fail; dExists := PositionSublist(config, "d"); - - for char in ["n","$"] do - startPos := PositionSublist(config, char); - if startPos <> fail then - # Assuming the value follows immediately or after an equals sign - tempStr := config{[startPos+1..startPos+2]}; - if char = "$" then - if First(tempStr) = '=' then - dollarValue := tempStr[2]; - else - dollarValue := tempStr[1]; - fi; - else - if First(tempStr) = '=' then - nValue := tempStr[2]; - else - nValue := tempStr[1]; - fi; - fi; - - else - ErrorNoReturn(StringFormatted("{} not specified.", char)); - fi; - od; + dollarValue := getValue(config, "$"); + nValue := getValue(config, "n"); return rec(dollarPart := dollarValue, nValue := nValue, dExists := dExists); end); -BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData) - local lines, digraph, edgeList, i, line, parts, vertex, connectedTo, adjacencyPart, flag; +BindGlobal("DIGRAPHS_ParseDreadnautGraph", +function(graphData, r) + local lines, digraph, edgeList, line, parts, vertex, connectedTo, adjacencyPart, flag, i, j; # Split the graph data into lines lines := SplitString(graphData, "\n"); @@ -1482,7 +1432,7 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData) # Initialize an empty list to hold the edges edgeList := []; - flag = false; + flag := false; # Iterate over each line to extract edges for i in [1..Length(lines)] do @@ -1492,7 +1442,7 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData) fi; if PositionSublist(line, ".") <> fail then - flag = true; + flag := true; fi; # Separate the vertex identifier from its adjacency list @@ -1514,8 +1464,8 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData) # Add edges to the edge list Add(edgeList, connectedTo); - if flag then - for j in [1..Length(lines)-i] do + if flag <> false then + for j in [1..r.nValue-i] do Add(edgeList, []); od; break; @@ -1525,6 +1475,59 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData) return edgeList; end); +InstallMethod(ReadDreadnautGraph, "for a digraph", [IsString], +function(name) + local file, config, graphData, line, edgeList, foundG, configEndIndex, r; + file := IO_CompressedFile(UserHomeExpand(name), "r"); + + if file = fail then + ErrorNoReturn("cannot open the file given as the 1st argument ,"); + fi; + + # Initialize variables + config := ""; + foundG := false; + configEndIndex := 0; + + # Read file line by line until 'g' is found + repeat + line := IO_ReadLine(file); + if not IsEmpty(line) then + config := Concatenation(config, line); # Keep newlines for clarity + if PositionSublist(line, "g") <> fail then + foundG := true; # Mark that 'g' has been found + configEndIndex := Length(config); + fi; + fi; + until foundG or IsEmpty(line); + + if not foundG then + ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); + fi; + # Split the content + graphData := ""; + + repeat + line := IO_ReadLine(file); + if not IsEmpty(line) then + graphData := Concatenation(graphData, line); # Keep newlines for clarity + fi; + until IsEmpty(line); + + r := DIGRAPHS_ParseDreadnautConfig(config); + edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r); + + if r.dollarValue <> 1 then + Info(InfoWarning, 1, "The vertex numbering in the dreadnaut file does not start at 1, but will be read in as such."); + + if r.dExists <> fail then + return Digraph(edgeList); + else + return DigraphSymmetricClosure(Digraph(edgeList)); + fi; +end); + + ################################################################################ diff --git a/tst/standard/io.tst b/tst/standard/io.tst index d5fbca2c1..66e0af9dd 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -942,8 +942,8 @@ gap> Exec("rm -f tmp.dre"); gap> filename := "tmp.dre";; gap> D = CompleteDigraph(3);; gap> WriteDreadnautGraph(filename, D); -gap> ReadDreadnautGraph(filename, D); - +gap> ReadDreadnautGraph(filename) = D; +true gap> Exec("rm -f tmp.dre"); # DIGRAPHS_UnbindVariables From 0502023950d24984dd2ea0a9628c36adf79bfb12 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:05:36 +0000 Subject: [PATCH 07/55] more edge cases covered --- gap/io.gi | 81 +++++++++++++++++++++++++-------------------- tst/standard/io.tst | 18 +++++++--- 2 files changed, 58 insertions(+), 41 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 819888892..0cbbaa8ea 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1393,85 +1393,94 @@ BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config) local nValue, dExists, dollarValue, tempStr, Pos, getValue; - - config := ReplacedString(config, " ", ""); # Remove spaces - config := ReplacedString(config, "\n", ""); # Remove newlines - config := ReplacedString(config, "\r", ""); # Remove carriage returns - config := ReplacedString(config, "\t", ""); # Remove tabs + config := ReplacedString(config, " ", ""); + config := ReplacedString(config, "\n", ""); + config := ReplacedString(config, "\r", ""); + config := ReplacedString(config, "\t", ""); config := ReplacedString(config, "=", ""); getValue := function(config, key) local Pos, tempStr; + if PositionSublist(config, key) <> fail then Pos := PositionSublist(config, key) + 1; tempStr := ""; while IsInt(Int(config{[Pos]})) do - Concatenation(tempStr, config{[Pos]}); + tempStr := Concatenation(tempStr, config{[Pos]}); Pos := Pos + 1; if Pos > Length(config) then break; fi; od; return Int(tempStr); + else + if key = "$" then + return 0; + else + ErrorNoReturn("The number of vertices has not been defined in the dreadnaut file. Check your file and ensure n is declared."); + fi; + fi; end; - dExists := PositionSublist(config, "d"); + dExists := PositionSublist(config, "d") <> fail; dollarValue := getValue(config, "$"); nValue := getValue(config, "n"); - return rec(dollarPart := dollarValue, nValue := nValue, dExists := dExists); + return rec(dollarValue := dollarValue, nValue := nValue, dExists := dExists); end); -BindGlobal("DIGRAPHS_ParseDreadnautGraph", + +BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local lines, digraph, edgeList, line, parts, vertex, connectedTo, adjacencyPart, flag, i, j; + local lines, digraph, edgeList, line, parts, vertex, connectedTo, adjacencyPart, flag, i, j, len, EOL; # Split the graph data into lines lines := SplitString(graphData, "\n"); # Initialize an empty list to hold the edges - edgeList := []; - - flag := false; + edgeList := List([1..r.nValue], x -> []); + EOL := false; - # Iterate over each line to extract edges for i in [1..Length(lines)] do line := lines[i]; if IsEmpty(line) or line = "\n" then - continue; # Skip empty lines + continue; fi; if PositionSublist(line, ".") <> fail then flag := true; + line := ReplacedString(line, ".", ""); fi; - # Separate the vertex identifier from its adjacency list - # Remove spaces around ':' to consistently identify the split point line := ReplacedString(line, " :", ":"); line := ReplacedString(line, ": ", ":"); parts := SplitString(line, ":"); - - # Extract the vertex number and its adjacency list - vertex := Int(parts[1]); + + if Length(parts) = 1 then + continue; + fi; + + vertex := parts[1]; + NormalizeWhitespace(vertex); + vertex := Int(vertex); adjacencyPart := parts[2]; - # Handle the adjacency list, terminating with ';' - adjacencyPart := ReplacedString(adjacencyPart, ";", " "); # Replace ';' with space for uniform splitting NormalizeWhitespace(adjacencyPart); # Remove extra spaces + adjacencyPart := ReplacedString(adjacencyPart, ".", ""); connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); - Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included - - # Add edges to the edge list - Add(edgeList, connectedTo); + connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included + connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 + len := Length(connectedTo); + connectedTo := Filtered(connectedTo, x -> x<=r.nValue); # Ensure the vertex is within the range of the number of vertices - if flag <> false then - for j in [1..r.nValue-i] do - Add(edgeList, []); - od; - break; + if len <> Length(connectedTo) then + Info(InfoWarning, 1, "Illegal edges have been removed"); fi; + + Append(edgeList[vertex], connectedTo); od; + return edgeList; end); @@ -1484,7 +1493,6 @@ function(name) ErrorNoReturn("cannot open the file given as the 1st argument ,"); fi; - # Initialize variables config := ""; foundG := false; configEndIndex := 0; @@ -1493,9 +1501,9 @@ function(name) repeat line := IO_ReadLine(file); if not IsEmpty(line) then - config := Concatenation(config, line); # Keep newlines for clarity + config := Concatenation(config, line); if PositionSublist(line, "g") <> fail then - foundG := true; # Mark that 'g' has been found + foundG := true; configEndIndex := Length(config); fi; fi; @@ -1504,13 +1512,13 @@ function(name) if not foundG then ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); fi; - # Split the content + graphData := ""; repeat line := IO_ReadLine(file); if not IsEmpty(line) then - graphData := Concatenation(graphData, line); # Keep newlines for clarity + graphData := Concatenation(graphData, line); fi; until IsEmpty(line); @@ -1519,6 +1527,7 @@ function(name) if r.dollarValue <> 1 then Info(InfoWarning, 1, "The vertex numbering in the dreadnaut file does not start at 1, but will be read in as such."); + fi; if r.dExists <> fail then return Digraph(edgeList); diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 66e0af9dd..74506c692 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -933,17 +933,25 @@ 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 := "tmp.dre";; +gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/temp.dre");; gap> D := CompleteDigraph(3);; gap> WriteDreadnautGraph(filename, CompleteDigraph(3)); -gap> Exec("rm -f tmp.dre"); # ReadDreadnautGraph -gap> filename := "tmp.dre";; -gap> D = CompleteDigraph(3);; -gap> WriteDreadnautGraph(filename, D); gap> ReadDreadnautGraph(filename) = D; true +gap> ReadDreadnautGraph("fakedir.dre"); +Error, cannot open the file given as the 1st argument , +gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/bad.dre");; +gap> ReadDreadnautGraph(filename); +#I Illegal edges have been removed + +gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/space.dre");; +gap> ReadDreadnautGraph(filename); +yes +gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/good.dre");; +gap> ReadDreadnautGraph(filename); + gap> Exec("rm -f tmp.dre"); # DIGRAPHS_UnbindVariables From c0417d75e40db0b568e57850376489400024377e Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 28 Mar 2024 14:52:50 +0000 Subject: [PATCH 08/55] more tests (passed) --- tst/standard/io.tst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 74506c692..1494b51b9 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -944,15 +944,14 @@ gap> ReadDreadnautGraph("fakedir.dre"); Error, cannot open the file given as the 1st argument , gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/bad.dre");; gap> ReadDreadnautGraph(filename); -#I Illegal edges have been removed gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/space.dre");; gap> ReadDreadnautGraph(filename); -yes + gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/good.dre");; gap> ReadDreadnautGraph(filename); -gap> Exec("rm -f tmp.dre"); +gap> Exec("rm -f temp.dre"); # DIGRAPHS_UnbindVariables gap> Unbind(D); From 23e4ab18be2d1087323cfba453323a38d2b6f3c0 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 28 Mar 2024 14:53:29 +0000 Subject: [PATCH 09/55] dealing with whitespace, nodes in wrong order, dealing with . --- gap/io.gi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gap/io.gi b/gap/io.gi index 0cbbaa8ea..97a12fa10 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1467,17 +1467,18 @@ function(graphData, r) NormalizeWhitespace(adjacencyPart); # Remove extra spaces adjacencyPart := ReplacedString(adjacencyPart, ".", ""); + adjacencyPart := ReplacedString(adjacencyPart, ";", ""); connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 len := Length(connectedTo); connectedTo := Filtered(connectedTo, x -> x<=r.nValue); # Ensure the vertex is within the range of the number of vertices - if len <> Length(connectedTo) then Info(InfoWarning, 1, "Illegal edges have been removed"); fi; Append(edgeList[vertex], connectedTo); + edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); od; From 51d528504952238ae0bf35673d8823325430e296 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 30 Mar 2024 00:10:36 +0000 Subject: [PATCH 10/55] reading edges continued onto next line --- gap/io.gi | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 97a12fa10..aa748bc23 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1432,14 +1432,15 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local lines, digraph, edgeList, line, parts, vertex, connectedTo, adjacencyPart, flag, i, j, len, EOL; + local lines, digraph, edgeList, line, parts, vertex, connectedTo, adjacencyPart, flag, i, j, len, EOL, lastVertex; # Split the graph data into lines lines := SplitString(graphData, "\n"); # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); - EOL := false; + EOL := fail; + lastVertex := fail; for i in [1..Length(lines)] do line := lines[i]; @@ -1457,16 +1458,27 @@ function(graphData, r) parts := SplitString(line, ":"); if Length(parts) = 1 then - continue; + if PositionSublist(line, ":") <> fail then + continue; + else + if EOL = fail then + Info(InfoWarning, 1, "Ignoring line ", i, " due to formatting error."); + continue; + else + vertex := lastVertex; + adjacencyPart := parts[1]; + fi; + fi; + else + vertex := parts[1]; + NormalizeWhitespace(vertex); + vertex := Int(vertex); + adjacencyPart := parts[2]; fi; - - vertex := parts[1]; - NormalizeWhitespace(vertex); - vertex := Int(vertex); - adjacencyPart := parts[2]; NormalizeWhitespace(adjacencyPart); # Remove extra spaces adjacencyPart := ReplacedString(adjacencyPart, ".", ""); + EOL := PositionSublist(line, ";") <> fail; #indicator to be used for next line adjacencyPart := ReplacedString(adjacencyPart, ";", ""); connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included @@ -1479,6 +1491,7 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); + vertex := lastVertex; od; From eeba1db2262469c3c7f785b1e6fa1ad9a43be41d Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 30 Mar 2024 00:33:00 +0000 Subject: [PATCH 11/55] overline bug fix --- gap/io.gi | 12 ++++-------- tst/standard/io.tst | 3 +++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index aa748bc23..769eda26a 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1439,7 +1439,7 @@ function(graphData, r) # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); - EOL := fail; + EOL := false; lastVertex := fail; for i in [1..Length(lines)] do @@ -1458,17 +1458,13 @@ function(graphData, r) parts := SplitString(line, ":"); if Length(parts) = 1 then - if PositionSublist(line, ":") <> fail then - continue; - else - if EOL = fail then + if EOL = true then Info(InfoWarning, 1, "Ignoring line ", i, " due to formatting error."); continue; else vertex := lastVertex; adjacencyPart := parts[1]; fi; - fi; else vertex := parts[1]; NormalizeWhitespace(vertex); @@ -1491,7 +1487,7 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - vertex := lastVertex; + lastVertex := vertex; od; @@ -1543,7 +1539,7 @@ function(name) Info(InfoWarning, 1, "The vertex numbering in the dreadnaut file does not start at 1, but will be read in as such."); fi; - if r.dExists <> fail then + if r.dExists then return Digraph(edgeList); else return DigraphSymmetricClosure(Digraph(edgeList)); diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 1494b51b9..5896344a1 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -951,6 +951,9 @@ gap> ReadDreadnautGraph(filename); gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/good.dre");; gap> ReadDreadnautGraph(filename); +gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/overline.dre");; +gap> ReadDreadnautGraph(filename); + gap> Exec("rm -f temp.dre"); # DIGRAPHS_UnbindVariables From a74be35848fd9e9d1b5751dc4773ffbb43afa413 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 30 Mar 2024 12:42:46 +0000 Subject: [PATCH 12/55] . in its own line --- gap/io.gi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 769eda26a..19bc76077 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1441,6 +1441,7 @@ function(graphData, r) edgeList := List([1..r.nValue], x -> []); EOL := false; lastVertex := fail; + flag := false; for i in [1..Length(lines)] do line := lines[i]; @@ -1450,14 +1451,15 @@ function(graphData, r) if PositionSublist(line, ".") <> fail then flag := true; - line := ReplacedString(line, ".", ""); fi; line := ReplacedString(line, " :", ":"); line := ReplacedString(line, ": ", ":"); parts := SplitString(line, ":"); - if Length(parts) = 1 then + if Length(parts) = 0 then + continue; + elif Length(parts) = 1 then if EOL = true then Info(InfoWarning, 1, "Ignoring line ", i, " due to formatting error."); continue; @@ -1488,6 +1490,10 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); lastVertex := vertex; + + if flag then + break; + fi; od; From e2df61cc7bda935b08a1581095a8ef10b0b6d286 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 30 Mar 2024 13:59:05 +0000 Subject: [PATCH 13/55] $$ and q support, additional tests --- gap/io.gi | 7 ++++++- tst/standard/io.tst | 10 +++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 19bc76077..702f9126b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1449,9 +1449,14 @@ function(graphData, r) continue; fi; - if PositionSublist(line, ".") <> fail then + if PositionSublist(line, ".") <> fail or PositionSublist(line, "q") then flag := true; fi; + + if PositionSublist(line, "$$") <> fail then + Info(InfoWarning, 1, "Indexing will start at 1."); + break; + fi; line := ReplacedString(line, " :", ":"); line := ReplacedString(line, ": ", ":"); diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 5896344a1..25ea1bfdb 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -935,7 +935,7 @@ 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, CompleteDigraph(3)); +gap> WriteDreadnautGraph(filename, D); # ReadDreadnautGraph gap> ReadDreadnautGraph(filename) = D; @@ -954,6 +954,14 @@ gap> ReadDreadnautGraph(filename); gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/overline.dre");; 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> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/repeats.dre");; +gap> ReadDreadnautGraph(filename); + gap> Exec("rm -f temp.dre"); # DIGRAPHS_UnbindVariables From 338c88a213853a8848de0c1eade718dc698be253 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 30 Mar 2024 14:22:02 +0000 Subject: [PATCH 14/55] q functionality and legaledges --- gap/io.gi | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 702f9126b..4894be6b1 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1429,6 +1429,21 @@ function(config) return rec(dollarValue := dollarValue, nValue := nValue, dExists := dExists); end); +BindGlobal("DIGRAPHS_LegalEdge", +function(vertex, connectedTo, nValue, dExists) + local i; + for i in connectedTo do + if i > nValue then + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", vertex); + return false; + elif not dExists and i = nValue then + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", i, ". Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); + return false; + fi; + return true; + od; +end); + BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) @@ -1449,8 +1464,10 @@ function(graphData, r) continue; fi; - if PositionSublist(line, ".") <> fail or PositionSublist(line, "q") then + if PositionSublist(line, ".") <> fail or PositionSublist(line, "q") <> fail then flag := true; + line := ReplacedString(line, ".", ""); + line := ReplacedString(line, "q", ""); fi; if PositionSublist(line, "$$") <> fail then @@ -1478,19 +1495,20 @@ function(graphData, r) vertex := Int(vertex); adjacencyPart := parts[2]; fi; + + if vertex > r.nValue or vertex < r.dollarValue then + Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex); + continue; + fi; NormalizeWhitespace(adjacencyPart); # Remove extra spaces - adjacencyPart := ReplacedString(adjacencyPart, ".", ""); EOL := PositionSublist(line, ";") <> fail; #indicator to be used for next line adjacencyPart := ReplacedString(adjacencyPart, ";", ""); connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 len := Length(connectedTo); - connectedTo := Filtered(connectedTo, x -> x<=r.nValue); # Ensure the vertex is within the range of the number of vertices - if len <> Length(connectedTo) then - Info(InfoWarning, 1, "Illegal edges have been removed"); - fi; + connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, connectedTo, r.nValue, r.dExists)); Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); @@ -1547,7 +1565,7 @@ function(name) edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r); if r.dollarValue <> 1 then - Info(InfoWarning, 1, "The vertex numbering in the dreadnaut file does not start at 1, but will be read in as such."); + Info(InfoWarning, 1, "The vertex indexing in the dreadnaut file does not start at 1, but will be read in as such."); fi; if r.dExists then From 45c3b445ef5c61a7c2e3b9fe8a23ab52f4da9110 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 30 Mar 2024 14:26:50 +0000 Subject: [PATCH 15/55] syntax --- gap/io.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/io.gi b/gap/io.gi index 4894be6b1..0577739e1 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1440,8 +1440,8 @@ function(vertex, connectedTo, nValue, dExists) Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", i, ". Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); return false; fi; - return true; od; + return true; end); From f20d7ee8be2af0030488aceff2ffe131471aaa0c Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:06:23 +0100 Subject: [PATCH 16/55] graphdata sharing lines with config, increased readability --- gap/io.gi | 80 +++++++++++++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 0577739e1..54058d28b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1391,42 +1391,34 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config) - local nValue, dExists, dollarValue, tempStr, Pos, getValue; + local tempStr, Pos, getValue; - config := ReplacedString(config, " ", ""); - config := ReplacedString(config, "\n", ""); - config := ReplacedString(config, "\r", ""); - config := ReplacedString(config, "\t", ""); - config := ReplacedString(config, "=", ""); + RemoveCharacters(config, " \n\r\t=-+"); getValue := function(config, key) - local Pos, tempStr; - if PositionSublist(config, key) <> fail then - Pos := PositionSublist(config, key) + 1; - tempStr := ""; - - while IsInt(Int(config{[Pos]})) do - tempStr := Concatenation(tempStr, config{[Pos]}); - Pos := Pos + 1; - if Pos > Length(config) then - break; - fi; - od; - return Int(tempStr); - else - if key = "$" then - return 0; + local Pos, tempStr; + if PositionSublist(config, key) <> fail then + Pos := PositionSublist(config, key) + 1; + tempStr := ""; + + while IsInt(Int(config{[Pos]})) do + tempStr := Concatenation(tempStr, config{[Pos]}); + Pos := Pos + 1; + if Pos > Length(config) then + break; + fi; + od; + return Int(tempStr); else - ErrorNoReturn("The number of vertices has not been defined in the dreadnaut file. Check your file and ensure n is declared."); + if key = "$" then + return 0; + else + ErrorNoReturn("The number of vertices has not been defined in the dreadnaut file. Check your file and ensure n is declared."); + fi; fi; - fi; end; - dExists := PositionSublist(config, "d") <> fail; - dollarValue := getValue(config, "$"); - nValue := getValue(config, "n"); - - return rec(dollarValue := dollarValue, nValue := nValue, dExists := dExists); + return rec(dollarValue := getValue(config, "$"), nValue := getValue(config, "n"), dExists := PositionSublist(config, "d") <> fail); end); BindGlobal("DIGRAPHS_LegalEdge", @@ -1436,7 +1428,8 @@ function(vertex, connectedTo, nValue, dExists) if i > nValue then Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", vertex); return false; - elif not dExists and i = nValue then + fi; + if not dExists and i = vertex then Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", i, ". Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); return false; fi; @@ -1447,7 +1440,7 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local lines, digraph, edgeList, line, parts, vertex, connectedTo, adjacencyPart, flag, i, j, len, EOL, lastVertex; + local lines, edgeList, line, parts, vertex, connectedTo, adjacencyPart, breakflag, i, j, EOL, lastVertex; # Split the graph data into lines lines := SplitString(graphData, "\n"); @@ -1456,7 +1449,7 @@ function(graphData, r) edgeList := List([1..r.nValue], x -> []); EOL := false; lastVertex := fail; - flag := false; + breakflag := false; for i in [1..Length(lines)] do line := lines[i]; @@ -1465,9 +1458,8 @@ function(graphData, r) fi; if PositionSublist(line, ".") <> fail or PositionSublist(line, "q") <> fail then - flag := true; - line := ReplacedString(line, ".", ""); - line := ReplacedString(line, "q", ""); + breakflag := true; + RemoveCharacters(line, ".q"); fi; if PositionSublist(line, "$$") <> fail then @@ -1500,21 +1492,21 @@ function(graphData, r) Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex); continue; fi; - + NormalizeWhitespace(adjacencyPart); # Remove extra spaces EOL := PositionSublist(line, ";") <> fail; #indicator to be used for next line - adjacencyPart := ReplacedString(adjacencyPart, ";", ""); + adjacencyPart := SplitString(adjacencyPart, "!")[1]; + RemoveCharacters(adjacencyPart, ",;"); connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - len := Length(connectedTo); connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, connectedTo, r.nValue, r.dExists)); Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); lastVertex := vertex; - if flag then + if breakflag then break; fi; od; @@ -1525,7 +1517,7 @@ end); InstallMethod(ReadDreadnautGraph, "for a digraph", [IsString], function(name) - local file, config, graphData, line, edgeList, foundG, configEndIndex, r; + local file, config, graphData, line, edgeList, foundG, r; file := IO_CompressedFile(UserHomeExpand(name), "r"); if file = fail then @@ -1534,17 +1526,13 @@ function(name) config := ""; foundG := false; - configEndIndex := 0; # Read file line by line until 'g' is found repeat line := IO_ReadLine(file); if not IsEmpty(line) then config := Concatenation(config, line); - if PositionSublist(line, "g") <> fail then - foundG := true; - configEndIndex := Length(config); - fi; + foundG := PositionSublist(line, "g") <> fail; fi; until foundG or IsEmpty(line); @@ -1552,7 +1540,7 @@ function(name) ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); fi; - graphData := ""; + graphData := line{[PositionSublist(line, "g") + 1..Length(line)]}; repeat line := IO_ReadLine(file); From 536676704f6b84383b8713fd466082f91ed791bb Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 1 Apr 2024 18:59:17 +0100 Subject: [PATCH 17/55] multiple vertices on one line functionality --- gap/io.gi | 157 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 71 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 54058d28b..289dacb4e 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1390,57 +1390,62 @@ function(str) end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", -function(config) - local tempStr, Pos, getValue; +function(config, key) + local Pos, tempStr; RemoveCharacters(config, " \n\r\t=-+"); - getValue := function(config, key) - local Pos, tempStr; - if PositionSublist(config, key) <> fail then - Pos := PositionSublist(config, key) + 1; - tempStr := ""; + if PositionSublist(config, key) <> fail then + Pos := PositionSublist(config, key) + 1; + tempStr := ""; - while IsInt(Int(config{[Pos]})) do - tempStr := Concatenation(tempStr, config{[Pos]}); - Pos := Pos + 1; - if Pos > Length(config) then - break; - fi; - od; - return Int(tempStr); - else - if key = "$" then - return 0; - else - ErrorNoReturn("The number of vertices has not been defined in the dreadnaut file. Check your file and ensure n is declared."); + while IsInt(Int(config{[Pos]})) do + tempStr := Concatenation(tempStr, config{[Pos]}); + Pos := Pos + 1; + if Pos > Length(config) then + break; fi; + od; + return Int(tempStr); + else + if key = "$" then + return 0; + else + ErrorNoReturn("The number of vertices has not been defined in the dreadnaut file. Check your file and ensure n is declared."); fi; - end; - - return rec(dollarValue := getValue(config, "$"), nValue := getValue(config, "n"), dExists := PositionSublist(config, "d") <> fail); + fi; end); BindGlobal("DIGRAPHS_LegalEdge", -function(vertex, connectedTo, nValue, dExists) - local i; - for i in connectedTo do - if i > nValue then - Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", vertex); - return false; - fi; - if not dExists and i = vertex then - Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", i, ". Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); - return false; - fi; - od; +function(vertex, x, r) + if x > r.nValue then + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", x); + return false; + fi; + if not r.dExists and x = vertex then + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", x, ". Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); + return false; + fi; return true; end); +BindGlobal("DIGRAPHS_SplitOnIndices", +function(s, indices) + local i, j, out; + out := []; + i := 1; + indices := indices{[2..Length(indices)]}; + for j in indices do + Add(out, s{[i..j-3]}); + i := j - 3 + 1; + od; + Add(out, s{[i..Length(s)]}); + return out; +end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local lines, edgeList, line, parts, vertex, connectedTo, adjacencyPart, breakflag, i, j, EOL, lastVertex; + local lines, edgeList, line, parts, vertex, connectedTo, adjacencyPart, breakflag, i, j, EOL, lastVertex, part, colonIndices; # Split the graph data into lines lines := SplitString(graphData, "\n"); @@ -1467,44 +1472,53 @@ function(graphData, r) break; fi; - line := ReplacedString(line, " :", ":"); - line := ReplacedString(line, ": ", ":"); - parts := SplitString(line, ":"); + line := ReplacedString(line, ":", " : "); + NormalizeWhitespace(line); + colonIndices := PositionsProperty(line, x -> x = ':'); + parts := DIGRAPHS_SplitOnIndices(line, colonIndices); - if Length(parts) = 0 then - continue; - elif Length(parts) = 1 then - if EOL = true then - Info(InfoWarning, 1, "Ignoring line ", i, " due to formatting error."); + + for part in parts do + part := SplitString(part, ":"); + + if Length(part) = 0 then continue; - else - vertex := lastVertex; - adjacencyPart := parts[1]; - fi; - else - vertex := parts[1]; - NormalizeWhitespace(vertex); - vertex := Int(vertex); - adjacencyPart := parts[2]; - fi; + elif Length(part) = 1 then + if EOL = true then + Info(InfoWarning, 1, "Ignoring line ", i, " due to formatting error."); + continue; + else + vertex := lastVertex; + adjacencyPart := part[1]; + fi; + else + vertex := part[1]; + RemoveCharacters(vertex, " "); + vertex := Int(vertex); + adjacencyPart := part[2]; + fi; - if vertex > r.nValue or vertex < r.dollarValue then - Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex); - continue; - fi; - NormalizeWhitespace(adjacencyPart); # Remove extra spaces - EOL := PositionSublist(line, ";") <> fail; #indicator to be used for next line - adjacencyPart := SplitString(adjacencyPart, "!")[1]; - RemoveCharacters(adjacencyPart, ",;"); - connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); - connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included - connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, connectedTo, r.nValue, r.dExists)); + if vertex > r.nValue or vertex < r.dollarValue then + Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex); + continue; + fi; + + NormalizeWhitespace(adjacencyPart); # Remove extra spaces + EOL := PositionSublist(adjacencyPart, ";") <> fail; #indicator to be used for next line + adjacencyPart := SplitString(adjacencyPart, "!")[1]; + RemoveCharacters(adjacencyPart, ",;"); + connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); + connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included + connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - Append(edgeList[vertex], connectedTo); - edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - lastVertex := vertex; + connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, x, r)); + + + Append(edgeList[vertex], connectedTo); + edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); + lastVertex := vertex; + od; if breakflag then break; @@ -1540,6 +1554,7 @@ function(name) ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); fi; + config := SplitString(config, "g")[1]; graphData := line{[PositionSublist(line, "g") + 1..Length(line)]}; repeat @@ -1548,8 +1563,8 @@ function(name) graphData := Concatenation(graphData, line); fi; until IsEmpty(line); - - r := DIGRAPHS_ParseDreadnautConfig(config); + + r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail); edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r); if r.dollarValue <> 1 then From e762c368a56e30a4f7ac04d8a1d623e4c92b3390 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 1 Apr 2024 18:59:22 +0100 Subject: [PATCH 18/55] addded tests --- tst/standard/io.tst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 25ea1bfdb..6136c0399 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -962,6 +962,9 @@ true gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/repeats.dre");; gap> ReadDreadnautGraph(filename); +gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/more bad.dre");; +gap> ReadDreadnautGraph(filename); + gap> Exec("rm -f temp.dre"); # DIGRAPHS_UnbindVariables From 53572d3cae3d90df6d3c9694a9c5779d2aeb8a25 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:59:23 +0100 Subject: [PATCH 19/55] corrected splitline function --- gap/io.gi | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 289dacb4e..c13fe353a 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1429,18 +1429,43 @@ function(vertex, x, r) return true; end); -BindGlobal("DIGRAPHS_SplitOnIndices", -function(s, indices) - local i, j, out; - out := []; - i := 1; - indices := indices{[2..Length(indices)]}; - for j in indices do - Add(out, s{[i..j-3]}); - i := j - 3 + 1; - od; - Add(out, s{[i..Length(s)]}); - return out; +BindGlobal("DIGRAPHS_SplitDreadnautLine", +function(inputString) + local startPos, currentPos, segments, currentChar, nextChar, flag; + + # Initialize variables + startPos := 1; + segments := []; + + # Iterate over the string + for currentPos in [1..Length(inputString)-1] do + currentChar := inputString[currentPos]; + nextChar := inputString[currentPos + 1]; + + flag := false; + + if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then + # if not flag then + # flag := true; + # continue; + # fi; + + 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; + + # Add the last segment + Add(segments, inputString{[startPos..Length(inputString)]}); + + return segments; end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", @@ -1474,9 +1499,7 @@ function(graphData, r) line := ReplacedString(line, ":", " : "); NormalizeWhitespace(line); - colonIndices := PositionsProperty(line, x -> x = ':'); - parts := DIGRAPHS_SplitOnIndices(line, colonIndices); - + parts := DIGRAPHS_SplitDreadnautLine(line); for part in parts do part := SplitString(part, ":"); From 24a8ef784c478ec2d778f396c899d329c5133267 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:41:34 +0100 Subject: [PATCH 20/55] r.dollarValue <> 1 support --- gap/io.gi | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index c13fe353a..35582d05a 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1419,11 +1419,15 @@ end); BindGlobal("DIGRAPHS_LegalEdge", function(vertex, x, r) if x > r.nValue then - Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", x); + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); return false; fi; if not r.dExists and x = vertex then - Info(InfoWarning, 1, "Ignoring illegal edge ", vertex, " -> ", x, ". Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing). Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); + return false; + fi; + if x < 1 then + Info(InfoWarning, 1, "Ignoring illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); return false; fi; return true; @@ -1445,11 +1449,6 @@ function(inputString) flag := false; if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then - # if not flag then - # flag := true; - # continue; - # fi; - repeat currentPos := currentPos - 1; until currentPos <= 1 or not IsDigitChar(inputString[currentPos]); @@ -1521,8 +1520,9 @@ function(graphData, r) adjacencyPart := part[2]; fi; + vertex := vertex - r.dollarValue + 1; - if vertex > r.nValue or vertex < r.dollarValue then + if vertex > r.nValue or vertex < 1 then Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex); continue; fi; @@ -1540,7 +1540,7 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - lastVertex := vertex; + lastVertex := vertex + r.dollarValue - 1; od; if breakflag then @@ -1588,12 +1588,13 @@ function(name) until IsEmpty(line); r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail); - edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r); if r.dollarValue <> 1 then - Info(InfoWarning, 1, "The vertex indexing in the dreadnaut file does not start at 1, but will be read in as such."); + Info(InfoWarning, 1, "The graph will be reindexed such that the first vertex is 1. i.e. effectively adding $=1 to the end of the file."); fi; + edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r); + if r.dExists then return Digraph(edgeList); else From 33946feef4b2a88aeb1e4f42cf0c7a8d4cb3e68c Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Tue, 2 Apr 2024 00:09:22 +0100 Subject: [PATCH 21/55] improved write function --- gap/io.gi | 18 ++++++++++-------- tst/standard/io.tst | 4 ++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 35582d05a..cd87608de 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1411,7 +1411,7 @@ function(config, key) if key = "$" then return 0; else - ErrorNoReturn("The number of vertices has not been defined in the dreadnaut file. Check your file and ensure n is declared."); + ErrorNoReturn("The number of vertices has not been defined. Check your file and ensure n is declared."); fi; fi; end); @@ -1491,8 +1491,8 @@ function(graphData, r) RemoveCharacters(line, ".q"); fi; - if PositionSublist(line, "$$") <> fail then - Info(InfoWarning, 1, "Indexing will start at 1."); + if PositionSublist(line, "$") <> fail then + Info(InfoWarning, 1, "Indexing will start at 1"); break; fi; @@ -1523,7 +1523,7 @@ function(graphData, r) vertex := vertex - r.dollarValue + 1; if vertex > r.nValue or vertex < 1 then - Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex); + Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex, " (original indexing)"); continue; fi; @@ -1548,7 +1548,6 @@ function(graphData, r) fi; od; - return edgeList; end); @@ -1677,7 +1676,7 @@ end); InstallMethod(WriteDreadnautGraph, "for a digraph", [IsString, IsDigraph], function(name, D) - local file, n, verts, nbs, labels, i, j; + local file, n, verts, nbs, labels, i, j, degs, filteredVerts; file := IO_CompressedFile(UserHomeExpand(name), "w"); if file = fail then @@ -1688,6 +1687,7 @@ function(name, D) n := DigraphNrVertices(D); verts := DigraphVertices(D); nbs := OutNeighbours(D); + degs := OutDegrees(D); if n = 0 then ErrorNoReturn("the 2nd argument must be a non-empty digraph,"); @@ -1700,11 +1700,13 @@ function(name, D) IO_WriteLine(file, Concatenation("n=", String(n))); IO_WriteLine(file, "g"); - for i in [1 .. n] do + + filteredVerts := Filtered(verts, x -> degs[x] > 0); + for i in filteredVerts do labels := List(nbs[i], j -> String(j)); IO_WriteLine(file, Concatenation(String(i), " : ", JoinStringsWithSeparator(labels, " "), ";")); od; - + IO_WriteLine(file, "."); IO_Close(file); return; end); diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 6136c0399..6b1a1f310 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -959,6 +959,10 @@ 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> ReadDreadnautGraph(filename); From 91150866973746442cedcd4bdf43e5b42f689da5 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 3 Apr 2024 12:59:36 +0100 Subject: [PATCH 22/55] support for multiple $/n declarations --- gap/io.gi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index cd87608de..197e44ab8 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1391,12 +1391,14 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) - local Pos, tempStr; + local L, Pos, tempStr; RemoveCharacters(config, " \n\r\t=-+"); - if PositionSublist(config, key) <> fail then - Pos := PositionSublist(config, key) + 1; + L := PositionsProperty(config, x -> x = key[1]); + + if L <> [] then + Pos := L[Length(L)] + 1; tempStr := ""; while IsInt(Int(config{[Pos]})) do From 014c19fd5068480854fa9557bf941a81c555dd9f Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:31:51 +0100 Subject: [PATCH 23/55] minor fixes --- gap/io.gi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 197e44ab8..e070fdc9f 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1509,7 +1509,7 @@ function(graphData, r) continue; elif Length(part) = 1 then if EOL = true then - Info(InfoWarning, 1, "Ignoring line ", i, " due to formatting error."); + Info(InfoWarning, 1, "Ignoring line ", i + r.configLength, " due to formatting error."); continue; else vertex := lastVertex; @@ -1588,7 +1588,7 @@ function(name) fi; until IsEmpty(line); - r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail); + r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail, configLength := Length(SplitString(config, "\n")); if r.dollarValue <> 1 then Info(InfoWarning, 1, "The graph will be reindexed such that the first vertex is 1. i.e. effectively adding $=1 to the end of the file."); From df6a3b14a269233e1cda1a0827fb5c890f6793e3 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 5 May 2024 15:27:09 +0100 Subject: [PATCH 24/55] condense onto one line, throw error instead of ignoring --- gap/io.gi | 161 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 71 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index e070fdc9f..9b11ac456 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1413,7 +1413,7 @@ function(config, key) if key = "$" then return 0; else - ErrorNoReturn("The number of vertices has not been defined. Check your file and ensure n is declared."); + ErrorNoReturn("the number of vertices has not been declared"); fi; fi; end); @@ -1421,34 +1421,54 @@ end); BindGlobal("DIGRAPHS_LegalEdge", function(vertex, x, r) if x > r.nValue then - Info(InfoWarning, 1, "Ignoring illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); + Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (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). Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); + Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing). Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); return false; fi; if x < 1 then - Info(InfoWarning, 1, "Ignoring illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); + Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); return false; fi; return true; end); -BindGlobal("DIGRAPHS_SplitDreadnautLine", +BindGlobal("DIGRAPHS_SplitDreadnautLines", function(inputString) - local startPos, currentPos, segments, currentChar, nextChar, flag; + local startPos, currentPos, segments, currentChar, nextChar; # Initialize variables startPos := 1; segments := []; - + # inputString := ReplacedString(inputString, "\n", " \n "); # Iterate over the string for currentPos in [1..Length(inputString)-1] do currentChar := inputString[currentPos]; nextChar := inputString[currentPos + 1]; - flag := false; + if currentChar = ';' then + Add(segments, inputString{[startPos..currentPos]}); + startPos := currentPos + 1; + continue; + fi; + + if currentChar = '$' and nextChar = '$' then + # Add(segments, inputString{[startPos..currentPos+1]}); + Info(InfoWarning, 1, "Vertex indexing will start at 1"); + if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; + break; + else + ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); + fi; + fi; + + if currentChar in "erRjstTvfFiIO" then + Error("Operation (", currentChar, ") not supported."); + Add(segments, inputString{[startPos..currentPos-1]}); + return segments; + fi; if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then repeat @@ -1471,85 +1491,84 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local lines, edgeList, line, parts, vertex, connectedTo, adjacencyPart, breakflag, i, j, EOL, lastVertex, part, colonIndices; + local lines, edgeList, line, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, i, j, lastVertex, colonIndices, newlineCounter; - # Split the graph data into lines - lines := SplitString(graphData, "\n"); + # lines := ReplacedString(graphData, "\n", " "); # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); - EOL := false; lastVertex := fail; breakflag := false; + newlineCounter := 1; - for i in [1..Length(lines)] do - line := lines[i]; - if IsEmpty(line) or line = "\n" then - continue; - fi; + graphData := ReplacedString(graphData, ":", " : "); + graphData := ReplacedString(graphData, ";", " ; "); + NormalizeWhitespace(graphData); + parts := DIGRAPHS_SplitDreadnautLines(graphData); - if PositionSublist(line, ".") <> fail or PositionSublist(line, "q") <> fail then - breakflag := true; - RemoveCharacters(line, ".q"); - fi; + for part in parts do - if PositionSublist(line, "$") <> fail then - Info(InfoWarning, 1, "Indexing will start at 1"); - break; - fi; - - line := ReplacedString(line, ":", " : "); - NormalizeWhitespace(line); - parts := DIGRAPHS_SplitDreadnautLine(line); - - for part in parts do - part := SplitString(part, ":"); - - if Length(part) = 0 then - continue; - elif Length(part) = 1 then - if EOL = true then - Info(InfoWarning, 1, "Ignoring line ", i + r.configLength, " due to formatting error."); - continue; - else - vertex := lastVertex; - adjacencyPart := part[1]; - fi; - else - vertex := part[1]; - RemoveCharacters(vertex, " "); - vertex := Int(vertex); - adjacencyPart := part[2]; - fi; + if PositionSublist(part, ".") <> fail or PositionSublist(part, "q") <> fail then + breakflag := true; + RemoveCharacters(part, ".q"); + fi; - vertex := vertex - r.dollarValue + 1; + # if PositionSublist(part, "$$") <> fail then + # if part <> parts[Length(parts)] then + # Info(InfoWarning, 1, "Ignoring illegal characters on line "); + # part := part{[1..PositionSublist(part, "$") - 1]}; + # else + # Info(InfoWarning, 1, "Indexing will start at 1"); + # break; + # fi; + # fi; + + if part = "" or part = ' ' or part = " " then + continue; + fi; + + subparts := SplitString(part, ":"); - if vertex > r.nValue or vertex < 1 then - Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex, " (original indexing)"); + if Length(subparts) = 0 then + continue; + elif Length(subparts) = 1 then + Info(InfoWarning, 1, "Ignoring line", part, "due to formatting error."); ### HOW TO FIND I? continue; - fi; + else + vertex := subparts[1]; + RemoveCharacters(vertex, " "); + vertex := Int(vertex); + adjacencyPart := subparts[2]; + fi; + + vertex := vertex - r.dollarValue + 1; + + if vertex > r.nValue or vertex < 1 then + Error("Illegal vertex ", vertex, " (original indexing)"); + continue; + fi; - NormalizeWhitespace(adjacencyPart); # Remove extra spaces - EOL := PositionSublist(adjacencyPart, ";") <> fail; #indicator to be used for next line - adjacencyPart := SplitString(adjacencyPart, "!")[1]; - RemoveCharacters(adjacencyPart, ",;"); - connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); - connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included - connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 + NormalizeWhitespace(adjacencyPart); # Remove extra spaces + adjacencyPart := SplitString(adjacencyPart, "!")[1]; + RemoveCharacters(adjacencyPart, ",;"); + connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); + connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included + connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, x, r)); + connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, x, r)); - Append(edgeList[vertex], connectedTo); - edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - lastVertex := vertex + r.dollarValue - 1; - od; + Append(edgeList[vertex], connectedTo); + edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); + lastVertex := vertex + r.dollarValue - 1; - if breakflag then - break; - fi; + if breakflag then + break; + fi; od; + + return edgeList; end); @@ -1575,7 +1594,7 @@ function(name) until foundG or IsEmpty(line); if not foundG then - ErrorNoReturn("g is not defined. Check your file and ensure g is declared."); + ErrorNoReturn("g not declared"); fi; config := SplitString(config, "g")[1]; @@ -1588,10 +1607,10 @@ function(name) fi; until IsEmpty(line); - r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail, configLength := Length(SplitString(config, "\n")); + r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail, configLength := Length(SplitString(config, "\n"))); if r.dollarValue <> 1 then - Info(InfoWarning, 1, "The graph will be reindexed such that the first vertex is 1. i.e. effectively adding $=1 to the end of the file."); + 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); From 9fd642c4713ac6a78e1c34dd6a8c2fcc3b6bebfd Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 5 May 2024 15:27:17 +0100 Subject: [PATCH 25/55] updated test outputs --- tst/standard/io.tst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 6b1a1f310..cb1f9c81c 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -944,7 +944,7 @@ gap> ReadDreadnautGraph("fakedir.dre"); Error, cannot open the file given as the 1st argument , gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/bad.dre");; gap> ReadDreadnautGraph(filename); - +Error, Illegal edge 2 -> 21 (original indexing) gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/space.dre");; gap> ReadDreadnautGraph(filename); @@ -968,7 +968,7 @@ gap> ReadDreadnautGraph(filename); gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/more bad.dre");; gap> ReadDreadnautGraph(filename); - +Error, Illegal edge 3 -> 16 (original indexing) gap> Exec("rm -f temp.dre"); # DIGRAPHS_UnbindVariables From 8094163a9f78a756202ba8a6736acb145ff713b4 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 5 May 2024 15:54:33 +0100 Subject: [PATCH 26/55] cleanup --- gap/io.gi | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 9b11ac456..e73884abc 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1425,7 +1425,7 @@ function(vertex, x, r) return false; fi; if not r.dExists and x = vertex then - Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing). Ensure the graph is as a diagraph in its dreadnaut formatting to include loops."); + Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing). Ensure 'd' is declared to include loops."); return false; fi; if x < 1 then @@ -1439,10 +1439,9 @@ BindGlobal("DIGRAPHS_SplitDreadnautLines", function(inputString) local startPos, currentPos, segments, currentChar, nextChar; - # Initialize variables startPos := 1; segments := []; - # inputString := ReplacedString(inputString, "\n", " \n "); + # Iterate over the string for currentPos in [1..Length(inputString)-1] do currentChar := inputString[currentPos]; @@ -1455,7 +1454,6 @@ function(inputString) fi; if currentChar = '$' and nextChar = '$' then - # Add(segments, inputString{[startPos..currentPos+1]}); Info(InfoWarning, 1, "Vertex indexing will start at 1"); if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; break; @@ -1470,8 +1468,8 @@ function(inputString) return segments; fi; - if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then - repeat + if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then #in the case of a new vertex + repeat #backtrack to find the start of the vertex currentPos := currentPos - 1; until currentPos <= 1 or not IsDigitChar(inputString[currentPos]); if startPos < currentPos then @@ -1483,21 +1481,16 @@ function(inputString) fi; od; - # Add the last segment Add(segments, inputString{[startPos..Length(inputString)]}); - return segments; end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local lines, edgeList, line, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, i, j, lastVertex, colonIndices, newlineCounter; - - # lines := ReplacedString(graphData, "\n", " "); + local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, newlineCounter; # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); - lastVertex := fail; breakflag := false; newlineCounter := 1; @@ -1513,16 +1506,6 @@ function(graphData, r) RemoveCharacters(part, ".q"); fi; - # if PositionSublist(part, "$$") <> fail then - # if part <> parts[Length(parts)] then - # Info(InfoWarning, 1, "Ignoring illegal characters on line "); - # part := part{[1..PositionSublist(part, "$") - 1]}; - # else - # Info(InfoWarning, 1, "Indexing will start at 1"); - # break; - # fi; - # fi; - if part = "" or part = ' ' or part = " " then continue; fi; @@ -1560,15 +1543,12 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - lastVertex := vertex + r.dollarValue - 1; if breakflag then break; fi; od; - - return edgeList; end); @@ -1607,7 +1587,7 @@ function(name) fi; until IsEmpty(line); - r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail, configLength := Length(SplitString(config, "\n"))); + r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail); 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."); From ad734fea2db82f43bf6b0c1d5ae90ccd76a1af47 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 6 May 2024 11:57:14 +0100 Subject: [PATCH 27/55] error messages --- gap/io.gi | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index e73884abc..4aed81b52 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1496,7 +1496,7 @@ function(graphData, r) graphData := ReplacedString(graphData, ":", " : "); graphData := ReplacedString(graphData, ";", " ; "); - NormalizeWhitespace(graphData); + NormalizeWhitespace(graphData); #losing newlines here parts := DIGRAPHS_SplitDreadnautLines(graphData); for part in parts do @@ -1515,8 +1515,8 @@ function(graphData, r) if Length(subparts) = 0 then continue; elif Length(subparts) = 1 then - Info(InfoWarning, 1, "Ignoring line", part, "due to formatting error."); ### HOW TO FIND I? - continue; + Error("Formatting error", part); ### HOW TO FIND I? + continue; else vertex := subparts[1]; RemoveCharacters(vertex, " "); @@ -1535,9 +1535,13 @@ function(graphData, r) adjacencyPart := SplitString(adjacencyPart, "!")[1]; RemoveCharacters(adjacencyPart, ",;"); connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); + + if fail in connectedTo then + Error("Formatting error (", part, ")"); + fi; + connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, x, r)); @@ -1568,7 +1572,7 @@ function(name) repeat line := IO_ReadLine(file); if not IsEmpty(line) then - config := Concatenation(config, line); + config := Concatenation(config, line); foundG := PositionSublist(line, "g") <> fail; fi; until foundG or IsEmpty(line); From fb1cab16f025469b242807c4332f263ed188bcad Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 6 May 2024 20:56:29 +0100 Subject: [PATCH 28/55] more error handling --- gap/io.gi | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 4aed81b52..a51953bb5 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1418,7 +1418,7 @@ function(config, key) fi; end); -BindGlobal("DIGRAPHS_LegalEdge", +BindGlobal("DIGRAPHS_LegalDreadnautEdge", function(vertex, x, r) if x > r.nValue then Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); @@ -1456,7 +1456,8 @@ function(inputString) if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; - break; + Add(segments, inputString{[startPos..currentPos - 1]}); + return segments; else ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); fi; @@ -1468,9 +1469,27 @@ function(inputString) return segments; fi; - if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then #in the case of a new vertex + # if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then #in the case of a new vertex + # repeat #backtrack to find the start of the vertex + # 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; + + if currentChar = ':' then repeat #backtrack to find the start of the vertex currentPos := currentPos - 1; + if inputString[currentPos] <> ' ' and not IsDigitChar(inputString[currentPos]) then + ErrorNoReturn("Syntax error: unexpected character (", inputString[currentPos],") before \":\""); #catches 1: 3\n : 4 + 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]}); @@ -1487,12 +1506,11 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, newlineCounter; + local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag; # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); breakflag := false; - newlineCounter := 1; graphData := ReplacedString(graphData, ":", " : "); graphData := ReplacedString(graphData, ";", " ; "); @@ -1512,11 +1530,11 @@ function(graphData, r) subparts := SplitString(part, ":"); - if Length(subparts) = 0 then - continue; - elif Length(subparts) = 1 then - Error("Formatting error", part); ### HOW TO FIND I? + if Length(subparts) = 0 or Length(subparts) = 1 then continue; + # elif Length(subparts) = 1 then + # Error("Formatting error", part); ### HOW TO FIND I? + # continue; else vertex := subparts[1]; RemoveCharacters(vertex, " "); @@ -1542,7 +1560,7 @@ function(graphData, r) connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalEdge(vertex, x, r)); + connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); Append(edgeList[vertex], connectedTo); From 52d78413364ee6137620bdcf7015cf90992a2bb1 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 6 May 2024 21:28:08 +0100 Subject: [PATCH 29/55] minor changes --- gap/io.gi | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index a51953bb5..6b77033dc 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1401,7 +1401,7 @@ function(config, key) Pos := L[Length(L)] + 1; tempStr := ""; - while IsInt(Int(config{[Pos]})) do + while Int(config{[Pos]}) <> fail do tempStr := Concatenation(tempStr, config{[Pos]}); Pos := Pos + 1; if Pos > Length(config) then @@ -1420,7 +1420,7 @@ end); BindGlobal("DIGRAPHS_LegalDreadnautEdge", function(vertex, x, r) - if x > r.nValue then + if x > r.nValue or x < 1 then Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); return false; fi; @@ -1428,10 +1428,6 @@ function(vertex, x, r) Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing). Ensure 'd' is declared to include loops."); return false; fi; - if x < 1 then - Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); - return false; - fi; return true; end); @@ -1512,8 +1508,8 @@ function(graphData, r) edgeList := List([1..r.nValue], x -> []); breakflag := false; - graphData := ReplacedString(graphData, ":", " : "); - graphData := ReplacedString(graphData, ";", " ; "); + # graphData := ReplacedString(graphData, ":", " : "); + # graphData := ReplacedString(graphData, ";", " ; "); NormalizeWhitespace(graphData); #losing newlines here parts := DIGRAPHS_SplitDreadnautLines(graphData); From a65158bf4b95338270ac60e280af5adf9f96124d Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sat, 25 May 2024 21:53:09 +0100 Subject: [PATCH 30/55] partition support --- gap/io.gi | 90 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 11 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 6b77033dc..19fd60c81 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1451,7 +1451,7 @@ function(inputString) if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); - if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; + if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; #what if currentpos+2>length? Add(segments, inputString{[startPos..currentPos - 1]}); return segments; else @@ -1459,12 +1459,34 @@ function(inputString) fi; fi; - if currentChar in "erRjstTvfFiIO" then - Error("Operation (", currentChar, ") not supported."); + if currentChar in "erRjstTvFiIO" then + Info(InfoWarning, 1, "Operation (", currentChar, ") not supported."); Add(segments, inputString{[startPos..currentPos-1]}); return segments; fi; + if currentChar = 'f' then + Add(segments, inputString{[startPos..currentPos-1]}); + 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 = ' ' or c = '\n' or c = '$') then; + Add(segments, Concatenation("f",inputString{[startPos..currentPos - 1]})); + startPos := currentPos + 1; + else + ErrorNoReturn("Syntax error: unexpected characters after \"]\""); + fi; + fi; + fi; + + # if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then #in the case of a new vertex # repeat #backtrack to find the start of the vertex # currentPos := currentPos - 1; @@ -1502,7 +1524,7 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag; + local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, pparts, partition, i, j, num; # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); @@ -1524,13 +1546,51 @@ function(graphData, r) continue; fi; + if part[1] = 'f' then + breakflag := true; + + 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, " 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), " do not feature in any part."); + else + r.partition := partition; + fi; + fi; + subparts := SplitString(part, ":"); if Length(subparts) = 0 or Length(subparts) = 1 then continue; - # elif Length(subparts) = 1 then - # Error("Formatting error", part); ### HOW TO FIND I? - # continue; + else vertex := subparts[1]; RemoveCharacters(vertex, " "); @@ -1572,7 +1632,7 @@ end); InstallMethod(ReadDreadnautGraph, "for a digraph", [IsString], function(name) - local file, config, graphData, line, edgeList, foundG, r; + local file, config, graphData, line, edgeList, foundG, r, D; file := IO_CompressedFile(UserHomeExpand(name), "r"); if file = fail then @@ -1605,7 +1665,7 @@ function(name) fi; until IsEmpty(line); - r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail); + r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail, partition := fail); 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."); @@ -1614,9 +1674,17 @@ function(name) edgeList := DIGRAPHS_ParseDreadnautGraph(graphData, r); if r.dExists then - return Digraph(edgeList); + D := Digraph(edgeList); + if r.partition <> fail then + SetDigraphVertexLabels(D, r.partition); + fi; + return D; else - return DigraphSymmetricClosure(Digraph(edgeList)); + D := DigraphSymmetricClosure(Digraph(edgeList)); + if r.partition <> fail then + SetDigraphVertexLabels(D, r.partition); + fi; + return D; fi; end); From 2cd78a29b92c27c5777e4b0caaac773bcc3ac8a0 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 18:16:01 +0100 Subject: [PATCH 31/55] cleanup --- gap/io.gi | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 19fd60c81..6b08ff1c4 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1409,6 +1409,7 @@ function(config, key) fi; od; return Int(tempStr); + else if key = "$" then return 0; @@ -1451,7 +1452,7 @@ function(inputString) if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); - if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; #what if currentpos+2>length? + if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; Add(segments, inputString{[startPos..currentPos - 1]}); return segments; else @@ -1465,7 +1466,7 @@ function(inputString) return segments; fi; - if currentChar = 'f' then + if currentChar = 'f' then #partition Add(segments, inputString{[startPos..currentPos-1]}); repeat currentPos := currentPos + 1; @@ -1486,19 +1487,6 @@ function(inputString) fi; fi; - - # if IsDigitChar(currentChar) and nextChar = ' ' and inputString[currentPos + 2] = ':' then #in the case of a new vertex - # repeat #backtrack to find the start of the vertex - # 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; - if currentChar = ':' then repeat #backtrack to find the start of the vertex currentPos := currentPos - 1; @@ -1526,17 +1514,13 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, pparts, partition, i, j, num; - # Initialize an empty list to hold the edges edgeList := List([1..r.nValue], x -> []); breakflag := false; - # graphData := ReplacedString(graphData, ":", " : "); - # graphData := ReplacedString(graphData, ";", " ; "); NormalizeWhitespace(graphData); #losing newlines here parts := DIGRAPHS_SplitDreadnautLines(graphData); for part in parts do - if PositionSublist(part, ".") <> fail or PositionSublist(part, "q") <> fail then breakflag := true; RemoveCharacters(part, ".q"); From 0f90a5461406787ac03bab9627bfddb43e7c7be6 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 18:32:17 +0100 Subject: [PATCH 32/55] unsupoorted commands --- gap/io.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/io.gi b/gap/io.gi index 6b08ff1c4..265352385 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1460,7 +1460,7 @@ function(inputString) fi; fi; - if currentChar in "erRjstTvFiIO" then + if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>" then Info(InfoWarning, 1, "Operation (", currentChar, ") not supported."); Add(segments, inputString{[startPos..currentPos-1]}); return segments; From f436bbd6adc9a89513809883a575d4c025ef7d21 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 19:41:51 +0100 Subject: [PATCH 33/55] gaplint --- gap/io.gi | 90 ++++++++++++++++++++++++--------------------- tst/standard/io.tst | 2 +- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 265352385..1a5eae61f 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1422,11 +1422,14 @@ end); BindGlobal("DIGRAPHS_LegalDreadnautEdge", function(vertex, x, r) if x > r.nValue or x < 1 then - Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing)"); + Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", + x + r.dollarValue - 1, " (original indexing)"); return false; fi; if not r.dExists and x = vertex then - Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", x + r.dollarValue - 1, " (original indexing). Ensure 'd' is declared to include loops."); + Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", + x + r.dollarValue - 1, " (original indexing). + Ensure 'd' is declared to include loops."); return false; fi; return true; @@ -1440,20 +1443,21 @@ function(inputString) segments := []; # Iterate over the string - for currentPos in [1..Length(inputString)-1] do + for currentPos in [1 .. Length(inputString)-1] do currentChar := inputString[currentPos]; nextChar := inputString[currentPos + 1]; if currentChar = ';' then - Add(segments, inputString{[startPos..currentPos]}); + Add(segments, inputString{[startPos .. currentPos]}); startPos := currentPos + 1; continue; fi; if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); - if ForAll(inputString{[currentPos + 2..Length(inputString)]}, c -> c = ' ' or c = '\n') then; - Add(segments, inputString{[startPos..currentPos - 1]}); + if ForAll(inputString{[currentPos + 2 .. Length(inputString)]}, + c -> c = ' ' or c = '\n') then + Add(segments, inputString{[startPos .. currentPos - 1]}); return segments; else ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); @@ -1462,12 +1466,12 @@ function(inputString) if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>" then Info(InfoWarning, 1, "Operation (", currentChar, ") not supported."); - Add(segments, inputString{[startPos..currentPos-1]}); + Add(segments, inputString{[startPos .. currentPos - 1]}); return segments; fi; - if currentChar = 'f' then #partition - Add(segments, inputString{[startPos..currentPos-1]}); + if currentChar = 'f' then # partition + Add(segments, inputString{[startPos .. currentPos - 1]}); repeat currentPos := currentPos + 1; until Int(inputString{[currentPos]}) <> fail; @@ -1478,8 +1482,8 @@ function(inputString) if currentPos > Length(inputString) then ErrorNoReturn("Syntax error: missing ']' in declaration of partition"); else - if ForAll(inputString{[currentPos + 1..Length(inputString)]}, c -> c = ' ' or c = '\n' or c = '$') then; - Add(segments, Concatenation("f",inputString{[startPos..currentPos - 1]})); + if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, c -> c = ' ' or c = '\n' or c = '$') then; + Add(segments, Concatenation("f",inputString{[startPos .. currentPos - 1]})); startPos := currentPos + 1; else ErrorNoReturn("Syntax error: unexpected characters after \"]\""); @@ -1498,7 +1502,7 @@ function(inputString) currentPos := currentPos - 1; until currentPos <= 1 or not IsDigitChar(inputString[currentPos]); if startPos < currentPos then - Add(segments, inputString{[startPos..currentPos-1]}); + Add(segments, inputString{[startPos .. currentPos - 1]}); fi; if currentPos > 1 then startPos := currentPos; @@ -1506,22 +1510,24 @@ function(inputString) fi; od; - Add(segments, inputString{[startPos..Length(inputString)]}); + Add(segments, inputString{[startPos .. Length(inputString)]}); return segments; end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) - local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, breakflag, pparts, partition, i, j, num; + local edgeList, part, parts, subparts, vertex, connectedTo, + adjacencyPart, breakflag, pparts, partition, i, j, num; - edgeList := List([1..r.nValue], x -> []); + edgeList := List([1 .. r.nValue], x -> []); breakflag := false; - NormalizeWhitespace(graphData); #losing newlines here + NormalizeWhitespace(graphData); parts := DIGRAPHS_SplitDreadnautLines(graphData); for part in parts do - if PositionSublist(part, ".") <> fail or PositionSublist(part, "q") <> fail then + if PositionSublist(part, ".") <> fail or + PositionSublist(part, "q") <> fail then breakflag := true; RemoveCharacters(part, ".q"); fi; @@ -1533,14 +1539,14 @@ function(graphData, r) if part[1] = 'f' then breakflag := true; - if Length(part) = 1 then #empty partition + if Length(part) = 1 then # empty partition continue; fi; - pparts := SplitString(part{[2..Length(part)]}, "|"); - partition := List([1..r.nValue], x -> -1); + 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 + for i in [1 .. Length(pparts)] do num := ""; for j in pparts[i] do if IsDigitChar(j) then @@ -1564,7 +1570,9 @@ function(graphData, r) od; if -1 in partition then - ErrorNoReturn("Partition is incomplete. The following vertices ", PositionsProperty(partition, x -> x = -1), " do not feature in any part."); + ErrorNoReturn("Partition is incomplete. The following vertices ", + PositionsProperty(partition, x -> x = -1), + " do not feature in any part."); else r.partition := partition; fi; @@ -1592,16 +1600,16 @@ function(graphData, r) NormalizeWhitespace(adjacencyPart); # Remove extra spaces adjacencyPart := SplitString(adjacencyPart, "!")[1]; RemoveCharacters(adjacencyPart, ",;"); - connectedTo := List(SplitString(adjacencyPart, " "), x -> Int(x)); + connectedTo := List(SplitString(adjacencyPart, " "), Int(x)); if fail in connectedTo then Error("Formatting error (", part, ")"); fi; - connectedTo := Filtered(connectedTo, y -> IsInt(y)); # Ensure only integers are included - connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); # Adjust the vertex numbering to start at 1 - connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); - + connectedTo := Filtered(connectedTo, IsInt(y)); + connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); + connectedTo := Filtered(connectedTo, + x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); @@ -1640,19 +1648,24 @@ function(name) fi; config := SplitString(config, "g")[1]; - graphData := line{[PositionSublist(line, "g") + 1..Length(line)]}; + graphData := line{[PositionSublist(line, "g") + 1 .. Length(line)]}; repeat line := IO_ReadLine(file); if not IsEmpty(line) then - graphData := Concatenation(graphData, line); + graphData := Concatenation(graphData, line); fi; until IsEmpty(line); - - r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), dExists := PositionSublist(config, "d") <> fail, partition := fail); + + r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), + nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), + dExists := PositionSublist(config, "d") <> fail, + partition := fail); 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."); + 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); @@ -1672,9 +1685,6 @@ function(name) fi; end); - - - ################################################################################ # 4. Encoders ################################################################################ @@ -1754,7 +1764,6 @@ function(name, D) ErrorNoReturn("cannot open the file given as the 1st argument ,"); fi; - n := DigraphNrVertices(D); verts := DigraphVertices(D); nbs := OutNeighbours(D); @@ -1764,19 +1773,18 @@ function(name, D) 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], j -> String(j)); - IO_WriteLine(file, Concatenation(String(i), " : ", JoinStringsWithSeparator(labels, " "), ";")); + labels := List(nbs[i], String(j)); + IO_WriteLine(file, Concatenation(String(i), " : ", + JoinStringsWithSeparator(labels, " "), ";")); od; + IO_WriteLine(file, "."); IO_Close(file); return; diff --git a/tst/standard/io.tst b/tst/standard/io.tst index cb1f9c81c..72dde3f3e 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -959,7 +959,7 @@ 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> D := Digraph([[ 3, 5, 10 ], [ 9, 8, 10 ], [ 4 ], [ 6 ], [ 7, 11 ], [ 7 ], [ 8 ], [ ], [ 11 ], [ ], [ ]]);; gap> WriteDreadnautGraph(filename, D);; gap> D = ReadDreadnautGraph(filename); true From f6535547c353a81fad7544dd7cf9376a5bf5ef4b Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 19:58:49 +0100 Subject: [PATCH 34/55] minor fix --- gap/io.gi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 1a5eae61f..a553d081d 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1428,8 +1428,8 @@ function(vertex, x, r) fi; if not r.dExists and x = vertex then Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", - x + r.dollarValue - 1, " (original indexing). - Ensure 'd' is declared to include loops."); + x + r.dollarValue - 1, " (original indexing). ", + "Ensure 'd' is declared to include loops."); return false; fi; return true; @@ -1600,13 +1600,13 @@ function(graphData, r) NormalizeWhitespace(adjacencyPart); # Remove extra spaces adjacencyPart := SplitString(adjacencyPart, "!")[1]; RemoveCharacters(adjacencyPart, ",;"); - connectedTo := List(SplitString(adjacencyPart, " "), Int(x)); + connectedTo := List(SplitString(adjacencyPart, " "), Int); if fail in connectedTo then Error("Formatting error (", part, ")"); fi; - connectedTo := Filtered(connectedTo, IsInt(y)); + connectedTo := Filtered(connectedTo, IsInt); connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); @@ -1664,8 +1664,8 @@ function(name) 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."); + "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); @@ -1757,7 +1757,7 @@ end); InstallMethod(WriteDreadnautGraph, "for a digraph", [IsString, IsDigraph], function(name, D) - local file, n, verts, nbs, labels, i, j, degs, filteredVerts; + local file, n, verts, nbs, labels, i, degs, filteredVerts; file := IO_CompressedFile(UserHomeExpand(name), "w"); if file = fail then @@ -1780,7 +1780,7 @@ function(name, D) filteredVerts := Filtered(verts, x -> degs[x] > 0); for i in filteredVerts do - labels := List(nbs[i], String(j)); + labels := List(nbs[i], String); IO_WriteLine(file, Concatenation(String(i), " : ", JoinStringsWithSeparator(labels, " "), ";")); od; From 19085162f9b652e16b9a35b639c8758ebffe8cd8 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 20:14:24 +0100 Subject: [PATCH 35/55] more gaplint --- gap/io.gi | 34 +++++++++++++++++++++------------- tst/standard/io.tst | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index a553d081d..1fc05dbee 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1389,7 +1389,7 @@ function(str) return ConvertToImmutableDigraphNC(out); end); -BindGlobal("DIGRAPHS_ParseDreadnautConfig", +BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) local L, Pos, tempStr; @@ -1443,7 +1443,7 @@ function(inputString) segments := []; # Iterate over the string - for currentPos in [1 .. Length(inputString)-1] do + for currentPos in [1 .. Length(inputString) - 1] do currentChar := inputString[currentPos]; nextChar := inputString[currentPos + 1]; @@ -1478,12 +1478,17 @@ function(inputString) startPos := currentPos; repeat currentPos := currentPos + 1; - until currentPos > Length(inputString) or inputString[currentPos] = ']'; + until currentPos > Length(inputString) + or inputString[currentPos] = ']'; if currentPos > Length(inputString) then - ErrorNoReturn("Syntax error: missing ']' in declaration of partition"); + ErrorNoReturn("Syntax error: missing ']'", + " in declaration of partition"); else - if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, c -> c = ' ' or c = '\n' or c = '$') then; - Add(segments, Concatenation("f",inputString{[startPos .. currentPos - 1]})); + if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, + c -> c = ' ' or c = '\n' or c = '$') then + Add(segments, + Concatenation("f", + inputString{[startPos .. currentPos - 1]})); startPos := currentPos + 1; else ErrorNoReturn("Syntax error: unexpected characters after \"]\""); @@ -1492,10 +1497,13 @@ function(inputString) fi; if currentChar = ':' then - repeat #backtrack to find the start of the vertex + repeat # backtrack to find the start of the vertex currentPos := currentPos - 1; - if inputString[currentPos] <> ' ' and not IsDigitChar(inputString[currentPos]) then - ErrorNoReturn("Syntax error: unexpected character (", inputString[currentPos],") before \":\""); #catches 1: 3\n : 4 + if inputString[currentPos] <> ' ' and + not IsDigitChar(inputString[currentPos]) then + ErrorNoReturn("Syntax error: unexpected character (", + inputString[currentPos], + ") before \":\""); fi; until currentPos <= 1 or IsDigitChar(inputString[currentPos]); repeat @@ -1526,7 +1534,7 @@ function(graphData, r) parts := DIGRAPHS_SplitDreadnautLines(graphData); for part in parts do - if PositionSublist(part, ".") <> fail or + if PositionSublist(part, ".") <> fail or PositionSublist(part, "q") <> fail then breakflag := true; RemoveCharacters(part, ".q"); @@ -1606,10 +1614,10 @@ function(graphData, r) Error("Formatting error (", part, ")"); fi; - connectedTo := Filtered(connectedTo, IsInt); + connectedTo := Filtered(connectedTo, IsInt); connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); connectedTo := Filtered(connectedTo, - x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); + x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); @@ -1780,7 +1788,7 @@ function(name, D) filteredVerts := Filtered(verts, x -> degs[x] > 0); for i in filteredVerts do - labels := List(nbs[i], String); + labels := List(nbs[i], String); IO_WriteLine(file, Concatenation(String(i), " : ", JoinStringsWithSeparator(labels, " "), ";")); od; diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 72dde3f3e..9b9cd2684 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -959,7 +959,7 @@ 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> D := Digraph([[3, 5, 10], [9, 8, 10], [4], [6], [7, 11], [7], [8], [], [11], [], []]);; gap> WriteDreadnautGraph(filename, D);; gap> D = ReadDreadnautGraph(filename); true From 7ac0bacf86276327c7dbdeb7ec350b689cce9943 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 22:14:28 +0100 Subject: [PATCH 36/55] fixed tests --- gap/io.gi | 12 ++++++++++-- tst/standard/io.tst | 30 +++++++++++++++++++----------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 1fc05dbee..da0d4fccb 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1391,10 +1391,18 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) - local L, Pos, tempStr; - + local L, Pos, tempStr, tempConfig; + RemoveCharacters(config, " \n\r\t=-+"); + tempConfig := ShallowCopy(config); + RemoveCharacters(tempConfig, "Ag$ntd1234567890"); + + if tempConfig <> "" then + ErrorNoReturn("the format of the file given as the 2nd argument ", + "cannot be determined,"); + fi; + L := PositionsProperty(config, x -> x = key[1]); if L <> [] then diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 9b9cd2684..33a7c6d50 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -943,17 +943,14 @@ true gap> ReadDreadnautGraph("fakedir.dre"); Error, cannot open the file given as the 1st argument , 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); Error, Illegal edge 2 -> 21 (original indexing) -gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/space.dre");; -gap> ReadDreadnautGraph(filename); - -gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/good.dre");; -gap> ReadDreadnautGraph(filename); - -gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/overline.dre");; -gap> ReadDreadnautGraph(filename); - gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/temp.dre");; gap> D := EmptyDigraph(5);; gap> WriteDreadnautGraph(filename, D);; @@ -964,11 +961,22 @@ 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;q");; +gap> IO_Close(file);; gap> ReadDreadnautGraph(filename); -gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/more bad.dre");; +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> ReadDreadnautGraph(filename); -Error, Illegal edge 3 -> 16 (original indexing) +Error, the format of the file given as the 2nd argument cannot be deter\ +mined, gap> Exec("rm -f temp.dre"); # DIGRAPHS_UnbindVariables From cd748ddf66d3aa90d14662a34f487cd407b420c1 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Sun, 26 May 2024 22:36:43 +0100 Subject: [PATCH 37/55] gaplint again --- gap/io.gi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index da0d4fccb..918df9518 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1392,7 +1392,7 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) local L, Pos, tempStr, tempConfig; - + RemoveCharacters(config, " \n\r\t=-+"); tempConfig := ShallowCopy(config); @@ -1507,11 +1507,11 @@ function(inputString) if currentChar = ':' then repeat # backtrack to find the start of the vertex currentPos := currentPos - 1; - if inputString[currentPos] <> ' ' and + if inputString[currentPos] <> ' ' and not IsDigitChar(inputString[currentPos]) then ErrorNoReturn("Syntax error: unexpected character (", inputString[currentPos], - ") before \":\""); + ") before \":\""); fi; until currentPos <= 1 or IsDigitChar(inputString[currentPos]); repeat @@ -1585,7 +1585,7 @@ function(graphData, r) od; od; - if -1 in partition then + if - 1 in partition then ErrorNoReturn("Partition is incomplete. The following vertices ", PositionsProperty(partition, x -> x = -1), " do not feature in any part."); From f7b92faf86d29f9571458e03618ea55cef98a17c Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 10:24:19 +0100 Subject: [PATCH 38/55] missing IO_Close --- tst/standard/io.tst | 1 + 1 file changed, 1 insertion(+) diff --git a/tst/standard/io.tst b/tst/standard/io.tst index 33a7c6d50..d693474e1 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -974,6 +974,7 @@ 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 2nd argument cannot be deter\ mined, From 620e649ad2a6d046cf2ad48f85427919b1b82fd9 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 12:44:57 +0100 Subject: [PATCH 39/55] write out partition --- gap/io.gi | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 918df9518..8b3611294 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1773,7 +1773,8 @@ end); InstallMethod(WriteDreadnautGraph, "for a digraph", [IsString, IsDigraph], function(name, D) - local file, n, verts, nbs, labels, i, degs, filteredVerts; + local file, n, verts, nbs, labels, i, degs, filteredVerts, + out, positions, joinedPositions; file := IO_CompressedFile(UserHomeExpand(name), "w"); if file = fail then @@ -1800,8 +1801,22 @@ function(name, D) IO_WriteLine(file, Concatenation(String(i), " : ", JoinStringsWithSeparator(labels, " "), ";")); od; - IO_WriteLine(file, "."); + + if DigraphVertexLabels(D) <> [1 .. n] then + labels := DuplicateFreeList(DigraphVertexLabels(D)); + out := "f = ["; + + for i in labels do + positions := PositionsProperty(labels, x -> x = i); + joinedPositions := JoinStringsWithSeparator(positions, " "); + out := Concatenation(out, joinedPositions); + out := Concatenation(out, " ]"); + od; + + IO_WriteLine(file, out); + fi; + IO_Close(file); return; end); From 24bb778f7bc536c8d54c4a911319a60d9aa8a0a4 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 13:09:15 +0100 Subject: [PATCH 40/55] checks for integer vertex labels, additional warnings --- gap/io.gi | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 8b3611294..32185fad0 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1693,6 +1693,8 @@ function(name) fi; return D; 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); @@ -1805,16 +1807,24 @@ function(name, D) if DigraphVertexLabels(D) <> [1 .. n] then labels := DuplicateFreeList(DigraphVertexLabels(D)); - out := "f = ["; - - for i in labels do - positions := PositionsProperty(labels, x -> x = i); - joinedPositions := JoinStringsWithSeparator(positions, " "); - out := Concatenation(out, joinedPositions); - out := Concatenation(out, " ]"); - od; + if ForAll(labels, IsInt) then + out := "f = ["; + + for i in labels do + positions := PositionsProperty(labels, x -> x = i); + joinedPositions := JoinStringsWithSeparator(positions, " "); + out := Concatenation(out, joinedPositions); + out := Concatenation(out, " ]"); + od; - IO_WriteLine(file, 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); From 5ab5f911e15ab6e908bd3ccf7eb454d621460948 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 13:30:02 +0100 Subject: [PATCH 41/55] fix typo (unsure why this happened) --- doc/oper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 .

From d729e876a5197eb6f5c37289ca4d34c892c7bb0d Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 14:37:52 +0100 Subject: [PATCH 42/55] fixed comment support --- gap/io.gi | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 32185fad0..a2cf3f93b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1614,7 +1614,6 @@ function(graphData, r) fi; NormalizeWhitespace(adjacencyPart); # Remove extra spaces - adjacencyPart := SplitString(adjacencyPart, "!")[1]; RemoveCharacters(adjacencyPart, ",;"); connectedTo := List(SplitString(adjacencyPart, " "), Int); @@ -1640,7 +1639,7 @@ end); InstallMethod(ReadDreadnautGraph, "for a digraph", [IsString], function(name) - local file, config, graphData, line, edgeList, foundG, r, D; + local file, config, graphData, line, edgeList, foundG, r, D, exclamPosition; file := IO_CompressedFile(UserHomeExpand(name), "r"); if file = fail then @@ -1654,6 +1653,12 @@ function(name) 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; @@ -1669,6 +1674,12 @@ function(name) 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); From 5b84e4f6b88a2739d44b3a211bb1b56e8fd66435 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 21:16:06 +0100 Subject: [PATCH 43/55] fixed dealing with unsupported operations --- gap/io.gi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index a2cf3f93b..46fa5ee6a 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1464,9 +1464,11 @@ function(inputString) if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); if ForAll(inputString{[currentPos + 2 .. Length(inputString)]}, - c -> c = ' ' or c = '\n') then + c -> not c in ".:") then Add(segments, inputString{[startPos .. currentPos - 1]}); - return segments; + startPos := currentPos + 2; + continue; + # return segments; else ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); fi; @@ -1493,7 +1495,7 @@ function(inputString) " in declaration of partition"); else if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, - c -> c = ' ' or c = '\n' or c = '$') then + c -> c in "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>") then Add(segments, Concatenation("f", inputString{[startPos .. currentPos - 1]})); From c4697a78121f1b70c2dcfeeb382b24a342ed6309 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 21:17:18 +0100 Subject: [PATCH 44/55] again --- gap/io.gi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gap/io.gi b/gap/io.gi index 46fa5ee6a..6a98ea7d0 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1495,7 +1495,8 @@ function(inputString) " in declaration of partition"); else if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, - c -> c in "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>") then + c -> c in + "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>") then Add(segments, Concatenation("f", inputString{[startPos .. currentPos - 1]})); From 9c6ed6a011c5672f22d65f6af6b6eaed9893b29f Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 22:13:38 +0100 Subject: [PATCH 45/55] support reindex before partition defintion, fixed partition write out --- gap/io.gi | 56 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 6a98ea7d0..22d73be2a 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1466,6 +1466,7 @@ function(inputString) if ForAll(inputString{[currentPos + 2 .. Length(inputString)]}, c -> not c in ".:") then Add(segments, inputString{[startPos .. currentPos - 1]}); + Add(segments, "$$"); startPos := currentPos + 2; continue; # return segments; @@ -1536,18 +1537,18 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) local edgeList, part, parts, subparts, vertex, connectedTo, - adjacencyPart, breakflag, pparts, partition, i, j, num; + adjacencyPart, pparts, partition, i, j, num, iter; edgeList := List([1 .. r.nValue], x -> []); - breakflag := false; - NormalizeWhitespace(graphData); parts := DIGRAPHS_SplitDreadnautLines(graphData); + iter := 0; for part in parts do + iter := iter + 1; + if PositionSublist(part, ".") <> fail or PositionSublist(part, "q") <> fail then - breakflag := true; RemoveCharacters(part, ".q"); fi; @@ -1555,9 +1556,20 @@ function(graphData, r) continue; fi; - if part[1] = 'f' then - breakflag := true; + if '$' in part then + if not ForAll(part{[iter + 1 .. Length(part)]}, c -> not c in ".:") then + ErrorNoReturn("Syntax error: unexpected characters after \"$\""); + fi; + if part = "$$" then + r.dollarValue := 0; + continue; + else + r.dollarValue := DIGRAPHS_ParseDreadnautConfig(part, "$"); + continue; + fi; + fi; + if part[1] = 'f' then if Length(part) = 1 then # empty partition continue; fi; @@ -1572,13 +1584,13 @@ function(graphData, r) num := Concatenation(num, [j]); elif j <> ' ' and j <> '\n' then - ErrorNoReturn("Illegal character ", j, " in partition"); + 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, " in partition"); + ErrorNoReturn("illegal part ", num + r.dollarValue - 1, " in partition"); else partition[num] := i; fi; @@ -1589,7 +1601,7 @@ function(graphData, r) od; if - 1 in partition then - ErrorNoReturn("Partition is incomplete. The following vertices ", + ErrorNoReturn("partition is incomplete. The following vertices ", PositionsProperty(partition, x -> x = -1), " do not feature in any part."); else @@ -1612,7 +1624,7 @@ function(graphData, r) vertex := vertex - r.dollarValue + 1; if vertex > r.nValue or vertex < 1 then - Error("Illegal vertex ", vertex, " (original indexing)"); + Error("illegal vertex ", vertex, " (original indexing)"); continue; fi; @@ -1631,10 +1643,6 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - - if breakflag then - break; - fi; od; return edgeList; @@ -1668,7 +1676,7 @@ function(name) until foundG or IsEmpty(line); if not foundG then - ErrorNoReturn("g not declared"); + ErrorNoReturn("'g' not declared"); fi; config := SplitString(config, "g")[1]; @@ -1694,7 +1702,7 @@ function(name) if r.dollarValue <> 1 then Info(InfoWarning, 1, - "the graph will be reindexed such that the indexing starts", + "The graph will be reindexed such that the indexing starts", " at 1. i.e. effectively adding $=1 to the end of the file."); fi; @@ -1790,7 +1798,7 @@ end); InstallMethod(WriteDreadnautGraph, "for a digraph", [IsString, IsDigraph], function(name, D) local file, n, verts, nbs, labels, i, degs, filteredVerts, - out, positions, joinedPositions; + out, positions, joinedPositions, dflabels; file := IO_CompressedFile(UserHomeExpand(name), "w"); if file = fail then @@ -1801,6 +1809,7 @@ function(name, 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,"); @@ -1819,17 +1828,20 @@ function(name, D) od; IO_WriteLine(file, "."); - if DigraphVertexLabels(D) <> [1 .. n] then - labels := DuplicateFreeList(DigraphVertexLabels(D)); - if ForAll(labels, IsInt) then + if labels <> [1 .. n] then + dflabels := DuplicateFreeList(labels); + if ForAll(dflabels, IsInt) then out := "f = ["; - for i in labels do + for i in dflabels do positions := PositionsProperty(labels, x -> x = i); joinedPositions := JoinStringsWithSeparator(positions, " "); out := Concatenation(out, joinedPositions); - out := Concatenation(out, " ]"); + if i <> dflabels[Length(dflabels)] then + out := Concatenation(out, " | "); + fi; od; + out := Concatenation(out, " ]"); IO_WriteLine(file, out); else From d49bbdcc1365b94ef80e7feec50de9b3d8ff80a1 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Mon, 27 May 2024 22:13:56 +0100 Subject: [PATCH 46/55] gaplint --- gap/io.gi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gap/io.gi b/gap/io.gi index 22d73be2a..5bd529409 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1590,7 +1590,9 @@ function(graphData, r) 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"); + ErrorNoReturn("illegal part ", + num + r.dollarValue - 1, + " in partition"); else partition[num] := i; fi; From 16ead34be0e93e45ddc5438b4145f61ed6e35a05 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Tue, 28 May 2024 01:53:01 +0100 Subject: [PATCH 47/55] fix .q support --- gap/io.gi | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 5bd529409..0e88a9abb 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1469,7 +1469,6 @@ function(inputString) Add(segments, "$$"); startPos := currentPos + 2; continue; - # return segments; else ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); fi; @@ -1478,7 +1477,6 @@ function(inputString) if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>" then Info(InfoWarning, 1, "Operation (", currentChar, ") not supported."); Add(segments, inputString{[startPos .. currentPos - 1]}); - return segments; fi; if currentChar = 'f' then # partition @@ -1530,26 +1528,41 @@ function(inputString) fi; od; - Add(segments, inputString{[startPos .. Length(inputString)]}); + if ForAny(inputString{[startPos .. Length(inputString)]}, + c -> c in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>") then + Info(InfoWarning, 1, "Ignoring unsupported operation."); + 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; + adjacencyPart, pparts, partition, i, j, num, iter, + breakflag; edgeList := List([1 .. r.nValue], x -> []); NormalizeWhitespace(graphData); parts := DIGRAPHS_SplitDreadnautLines(graphData); iter := 0; + breakflag := false; for part in parts do iter := iter + 1; - if PositionSublist(part, ".") <> fail or - PositionSublist(part, "q") <> fail then - RemoveCharacters(part, ".q"); + if PositionSublist(part, ".") <> fail then + RemoveCharacters(part, "."); + if ForAny(parts{[iter + 1 .. Length(parts)]}, + c -> ':' in c) then + ErrorNoReturn("Syntax error: unexpected characters after \".\""); + fi; + fi; + + if PositionSublist(part, "q") <> fail then + breakflag := true; + RemoveCharacters(part, "q"); fi; if part = "" or part = ' ' or part = " " then @@ -1645,6 +1658,10 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); + + if breakflag = true then + break; + fi; od; return edgeList; From dfd44885dba95ceae96be51da601da5ac55f6083 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Tue, 28 May 2024 04:22:08 +0100 Subject: [PATCH 48/55] minor fixes --- gap/io.gi | 61 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 0e88a9abb..3879d140b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1391,7 +1391,7 @@ end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) - local L, Pos, tempStr, tempConfig; + local Pos, tempStr, tempConfig; RemoveCharacters(config, " \n\r\t=-+"); @@ -1403,11 +1403,16 @@ function(config, key) "cannot be determined,"); fi; - L := PositionsProperty(config, x -> x = key[1]); + Pos := PositionProperty(config, x -> x = key[1]); - if L <> [] then - Pos := L[Length(L)] + 1; + if Pos <> fail then tempStr := ""; + Pos := Pos + 1; + + if Pos > Length(config) then + ErrorNoReturn("the format of the file given as the 2nd argument ", + "cannot be determined,"); + fi; while Int(config{[Pos]}) <> fail do tempStr := Concatenation(tempStr, config{[Pos]}); @@ -1416,6 +1421,10 @@ function(config, key) break; fi; od; + if tempStr = "" then + ErrorNoReturn("the format of the file given as the 2nd argument ", + "cannot be determined,"); + fi; return Int(tempStr); else @@ -1463,20 +1472,24 @@ function(inputString) if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); - if ForAll(inputString{[currentPos + 2 .. Length(inputString)]}, - c -> not c in ".:") then + if ForAny(inputString{[currentPos + 2 .. Length(inputString)]}, + c -> c in ".:") or + inputString{ + [currentPos + 2 .. Minimum([currentPos + 2, + Length(inputString)])]} = "$" + then + ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); + else Add(segments, inputString{[startPos .. currentPos - 1]}); Add(segments, "$$"); startPos := currentPos + 2; continue; - else - ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); fi; + fi; - if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>" then + if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q" then Info(InfoWarning, 1, "Operation (", currentChar, ") not supported."); - Add(segments, inputString{[startPos .. currentPos - 1]}); fi; if currentChar = 'f' then # partition @@ -1495,7 +1508,7 @@ function(inputString) else if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, c -> c in - "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>") then + "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q") then Add(segments, Concatenation("f", inputString{[startPos .. currentPos - 1]})); @@ -1529,7 +1542,7 @@ function(inputString) od; if ForAny(inputString{[startPos .. Length(inputString)]}, - c -> c in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>") then + c -> c in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q") then Info(InfoWarning, 1, "Ignoring unsupported operation."); else Add(segments, inputString{[startPos .. Length(inputString)]}); @@ -1541,18 +1554,22 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, pparts, partition, i, j, num, iter, - breakflag; + pos; edgeList := List([1 .. r.nValue], x -> []); NormalizeWhitespace(graphData); parts := DIGRAPHS_SplitDreadnautLines(graphData); iter := 0; - breakflag := false; for part in parts do iter := iter + 1; - if PositionSublist(part, ".") <> fail then + 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) then @@ -1560,11 +1577,6 @@ function(graphData, r) fi; fi; - if PositionSublist(part, "q") <> fail then - breakflag := true; - RemoveCharacters(part, "q"); - fi; - if part = "" or part = ' ' or part = " " then continue; fi; @@ -1573,12 +1585,13 @@ function(graphData, r) if not ForAll(part{[iter + 1 .. Length(part)]}, c -> not c in ".:") then ErrorNoReturn("Syntax error: unexpected characters after \"$\""); fi; + if part = "$$" then r.dollarValue := 0; - continue; + # continue; else r.dollarValue := DIGRAPHS_ParseDreadnautConfig(part, "$"); - continue; + # continue; fi; fi; @@ -1658,10 +1671,6 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); - - if breakflag = true then - break; - fi; od; return edgeList; From e01b2aa64dbd8138b706632a3c7d430e8037033f Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 29 May 2024 19:21:39 +0100 Subject: [PATCH 49/55] minor changes: errors -> infowarnings, more informative warnings --- gap/io.gi | 75 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 3879d140b..a01e14bbc 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1400,7 +1400,9 @@ function(config, key) if tempConfig <> "" then ErrorNoReturn("the format of the file given as the 2nd argument ", - "cannot be determined,"); + "cannot be determined as it contains unexpected ", + "characters: ", + tempConfig); fi; Pos := PositionProperty(config, x -> x = key[1]); @@ -1409,11 +1411,6 @@ function(config, key) tempStr := ""; Pos := Pos + 1; - if Pos > Length(config) then - ErrorNoReturn("the format of the file given as the 2nd argument ", - "cannot be determined,"); - fi; - while Int(config{[Pos]}) <> fail do tempStr := Concatenation(tempStr, config{[Pos]}); Pos := Pos + 1; @@ -1422,8 +1419,15 @@ function(config, key) fi; od; if tempStr = "" then - ErrorNoReturn("the format of the file given as the 2nd argument ", - "cannot be determined,"); + if key <> "f" then + ErrorNoReturn("the format of the file given as the 2nd ", + "argument cannot be determined. ", key, + " is not followed by a value"); + else + ErrorNoReturn("the partition cannot be determined.", + " 'f' is neither followed", + " by a single value nor by a list of values"); + fi; fi; return Int(tempStr); @@ -1431,7 +1435,9 @@ function(config, key) if key = "$" then return 0; else - ErrorNoReturn("the number of vertices has not been declared"); + ErrorNoReturn("the number of vertices has not been declared. ", + "Ensure that ", + "n=# is included before the declaration of 'g', "); fi; fi; end); @@ -1439,14 +1445,16 @@ end); BindGlobal("DIGRAPHS_LegalDreadnautEdge", function(vertex, x, r) if x > r.nValue or x < 1 then - Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", - x + r.dollarValue - 1, " (original indexing)"); + Info(InfoWarning, 1, "Ignoring illegal edge ", + vertex + r.dollarValue - 1, " -> ", + x + r.dollarValue - 1, " (original indexing)"); return false; fi; if not r.dExists and x = vertex then - Error("Illegal edge ", vertex + r.dollarValue - 1, " -> ", - x + r.dollarValue - 1, " (original indexing). ", - "Ensure 'd' is declared to include loops."); + Info(InfoWarning, 1, "Ignoring illegal edge ", + vertex + r.dollarValue - 1, " -> ", + x + r.dollarValue - 1, " (original indexing). ", + "Ensure 'd' is declared to include loops."); return false; fi; return true; @@ -1489,7 +1497,9 @@ function(inputString) fi; if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q" then - Info(InfoWarning, 1, "Operation (", currentChar, ") not supported."); + Info(InfoWarning, 1, "while parsing dreadnaut file config,", + " found operation ", + currentChar, " which is not supported."); fi; if currentChar = 'f' then # partition @@ -1508,13 +1518,23 @@ function(inputString) else if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, c -> c in - "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q") then + Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", + "z#oMh<>q0123456789")) then Add(segments, Concatenation("f", inputString{[startPos .. currentPos - 1]})); startPos := currentPos + 1; else - ErrorNoReturn("Syntax error: unexpected characters after \"]\""); + ErrorNoReturn( + "Syntax error: unexpected characters after \"]\" (", + JoinStringsWithSeparator( + Filtered( + inputString{[currentPos + 1 .. Length(inputString)]}, + c -> not c in + Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", + "z#oMh<>q0123456789"), + ","), + "), ")); fi; fi; fi; @@ -1573,7 +1593,8 @@ function(graphData, r) RemoveCharacters(part, "."); if ForAny(parts{[iter + 1 .. Length(parts)]}, c -> ':' in c) then - ErrorNoReturn("Syntax error: unexpected characters after \".\""); + ErrorNoReturn("Syntax error: unexpected characters after \".\"", + "(note that edges cannot be declared after \".\")"); fi; fi; @@ -1582,22 +1603,23 @@ function(graphData, r) fi; if '$' in part then - if not ForAll(part{[iter + 1 .. Length(part)]}, c -> not c in ".:") then - ErrorNoReturn("Syntax error: unexpected characters after \"$\""); + if ForAny(part{[iter + 1 .. Length(part)]}, c -> c in ".:") then + ErrorNoReturn("Syntax error: unexpected characters after \"$\"", + "(note that edges cannot be declared after \"$\")"); fi; if part = "$$" then r.dollarValue := 0; - # continue; else r.dollarValue := DIGRAPHS_ParseDreadnautConfig(part, "$"); - # continue; fi; fi; if part[1] = 'f' then if Length(part) = 1 then # empty partition continue; + elif not '[' in part then + DIGRAPHS_ParseDreadnautConfig(part, "f"); fi; pparts := SplitString(part{[2 .. Length(part)]}, "|"); @@ -1652,7 +1674,8 @@ function(graphData, r) vertex := vertex - r.dollarValue + 1; if vertex > r.nValue or vertex < 1 then - Error("illegal vertex ", vertex, " (original indexing)"); + Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex, + " (original indexing)"); continue; fi; @@ -1661,10 +1684,9 @@ function(graphData, r) connectedTo := List(SplitString(adjacencyPart, " "), Int); if fail in connectedTo then - Error("Formatting error (", part, ")"); + ErrorNoReturn("Formatting error (", part, ")"); fi; - connectedTo := Filtered(connectedTo, IsInt); connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); connectedTo := Filtered(connectedTo, x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); @@ -1682,7 +1704,8 @@ function(name) file := IO_CompressedFile(UserHomeExpand(name), "r"); if file = fail then - ErrorNoReturn("cannot open the file given as the 1st argument ,"); + ErrorNoReturn("cannot open the file given as the 1st argument ,", + name); fi; config := ""; From e86bb9a61ff00d139e20bf9206fba76bfff561eb Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 29 May 2024 20:30:18 +0100 Subject: [PATCH 50/55] updated tests --- gap/io.gi | 25 ++++++++++++++++--------- tst/standard/io.tst | 15 ++++++++------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index a01e14bbc..757429b2b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1399,10 +1399,11 @@ function(config, key) RemoveCharacters(tempConfig, "Ag$ntd1234567890"); if tempConfig <> "" then - ErrorNoReturn("the format of the file given as the 2nd argument ", + ErrorNoReturn("the format of the file given as the 1st argument ", "cannot be determined as it contains unexpected ", "characters: ", - tempConfig); + JoinStringsWithSeparator(tempConfig, ","), + ","); fi; Pos := PositionProperty(config, x -> x = key[1]); @@ -1486,7 +1487,8 @@ function(inputString) [currentPos + 2 .. Minimum([currentPos + 2, Length(inputString)])]} = "$" then - ErrorNoReturn("Syntax error: unexpected characters after \"$$\""); + ErrorNoReturn("Syntax error: unexpected characters", + " (including ':' or '.') after \"$$\""); else Add(segments, inputString{[startPos .. currentPos - 1]}); Add(segments, "$$"); @@ -1593,7 +1595,8 @@ function(graphData, r) RemoveCharacters(part, "."); if ForAny(parts{[iter + 1 .. Length(parts)]}, c -> ':' in c) then - ErrorNoReturn("Syntax error: unexpected characters after \".\"", + ErrorNoReturn("Syntax error: unexpected characters (including ':'", + ")after \".\"", "(note that edges cannot be declared after \".\")"); fi; fi; @@ -1604,8 +1607,9 @@ function(graphData, r) if '$' in part then if ForAny(part{[iter + 1 .. Length(part)]}, c -> c in ".:") then - ErrorNoReturn("Syntax error: unexpected characters after \"$\"", - "(note that edges cannot be declared after \"$\")"); + ErrorNoReturn("Syntax error: unexpected characters (including ':'", + "or '.')after \".\"", + "(note that edges cannot be declared after \".\")"); fi; if part = "$$" then @@ -1704,8 +1708,9 @@ function(name) file := IO_CompressedFile(UserHomeExpand(name), "r"); if file = fail then - ErrorNoReturn("cannot open the file given as the 1st argument ,", - name); + ErrorNoReturn("cannot open the file given as the 1st argument , \"", + name, + "\","); fi; config := ""; @@ -1853,7 +1858,9 @@ function(name, D) file := IO_CompressedFile(UserHomeExpand(name), "w"); if file = fail then - ErrorNoReturn("cannot open the file given as the 1st argument ,"); + ErrorNoReturn("cannot open the file given as the 1st argument , \"", + name, + "\","); fi; n := DigraphNrVertices(D); diff --git a/tst/standard/io.tst b/tst/standard/io.tst index d693474e1..e2117aa9b 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -927,12 +927,13 @@ gap> ReadDigraphs(filename, IO_Unpickle); gap> gr := EmptyDigraph(0);; gap> filename := "does/not/exist.dre";; gap> WriteDreadnautGraph(filename, gr); -Error, cannot open the file given as the 1st argument , +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 , +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); @@ -941,7 +942,7 @@ gap> WriteDreadnautGraph(filename, D); gap> ReadDreadnautGraph(filename) = D; true gap> ReadDreadnautGraph("fakedir.dre"); -Error, cannot open the file given as the 1st argument , +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");; @@ -950,7 +951,7 @@ gap> IO_WriteLine(file, "1:1;");; gap> IO_WriteLine(file, "2:21");; gap> IO_Close(file);; gap> ReadDreadnautGraph(filename); -Error, Illegal edge 2 -> 21 (original indexing) + gap> filename := Concatenation(DIGRAPHS_Dir(), "tst/out/temp.dre");; gap> D := EmptyDigraph(5);; gap> WriteDreadnautGraph(filename, D);; @@ -976,9 +977,9 @@ 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 2nd argument cannot be deter\ -mined, -gap> Exec("rm -f temp.dre"); +Error, the format of the file given as the 1st argument cannot be deter\ +mined as it contains unexpected characters: 's','i','l','l','y','e','x','f','o\ +','r','e','s','i', # DIGRAPHS_UnbindVariables gap> Unbind(D); From b26d7e7ea94845ad9cdffda565b5951f20708bef Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 30 May 2024 00:50:43 +0100 Subject: [PATCH 51/55] support f = # --- gap/io.gi | 96 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 757429b2b..1018e4be5 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1389,6 +1389,14 @@ function(str) return ConvertToImmutableDigraphNC(out); end); +# BindGlobal("DIGRAPHS_FindDreadnautLine", +# function(original, line) +# local start; +# start := PositionSublist(original, line); +# return Length(PositionsProperty(original{[1 .. start + Length(line)]}, +# x -> x = '\n')) + 1; +# end); + BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) local Pos, tempStr, tempConfig; @@ -1398,7 +1406,7 @@ function(config, key) tempConfig := ShallowCopy(config); RemoveCharacters(tempConfig, "Ag$ntd1234567890"); - if tempConfig <> "" then + if tempConfig <> "" and key <> "f" then ErrorNoReturn("the format of the file given as the 1st argument ", "cannot be determined as it contains unexpected ", "characters: ", @@ -1462,8 +1470,9 @@ function(vertex, x, r) end); BindGlobal("DIGRAPHS_SplitDreadnautLines", -function(inputString) - local startPos, currentPos, segments, currentChar, nextChar; +function(inputString, r) + local startPos, currentPos, segments, currentChar, nextChar, index, + partition; startPos := 1; segments := []; @@ -1506,37 +1515,58 @@ function(inputString) if currentChar = 'f' then # partition Add(segments, inputString{[startPos .. currentPos - 1]}); - 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"); + if PositionSublist( + inputString{[currentPos + 1 .. Length(inputString)]}, + "[") = fail then + index := DIGRAPHS_ParseDreadnautConfig(inputString{[currentPos .. + Length(inputString)]}, + "f"); + partition := [1 .. r.nValue]; + Remove(partition, index); + + Add(segments, Concatenation( + Concatenation( + Concatenation("f", String(index)), + " | "), JoinStringsWithSeparator(partition, " "))); + + startPos := PositionSublist( + inputString{[currentPos + 1 .. Length(inputString)]}, + String(index)) + currentPos + 1; + else - if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, - c -> c in - Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", - "z#oMh<>q0123456789")) then - Add(segments, - Concatenation("f", - inputString{[startPos .. currentPos - 1]})); - startPos := currentPos + 1; + 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 - ErrorNoReturn( - "Syntax error: unexpected characters after \"]\" (", - JoinStringsWithSeparator( - Filtered( + if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, + c -> c in + Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", + "z#oMh<>q0123456789")) then + Add(segments, + Concatenation("f", + inputString{[startPos .. currentPos - 1]})); + startPos := currentPos + 1; + else + ErrorNoReturn( + "Syntax error: unexpected characters after \"]\" (", + JoinStringsWithSeparator( + Filtered( inputString{[currentPos + 1 .. Length(inputString)]}, c -> not c in - Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", - "z#oMh<>q0123456789"), - ","), - "), ")); + Concatenation( + "$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", + "z#oMh<>q0123456789"), + ","), + "), ")); + fi; fi; fi; fi; @@ -1580,7 +1610,7 @@ function(graphData, r) edgeList := List([1 .. r.nValue], x -> []); NormalizeWhitespace(graphData); - parts := DIGRAPHS_SplitDreadnautLines(graphData); + parts := DIGRAPHS_SplitDreadnautLines(graphData, r); iter := 0; for part in parts do @@ -1622,8 +1652,8 @@ function(graphData, r) if part[1] = 'f' then if Length(part) = 1 then # empty partition continue; - elif not '[' in part then - DIGRAPHS_ParseDreadnautConfig(part, "f"); + # elif not '[' in part then + # DIGRAPHS_ParseDreadnautConfig(part, "f"); fi; pparts := SplitString(part{[2 .. Length(part)]}, "|"); From 656a6bd539e2edb00791f803343a8ac9cfe905b6 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 30 May 2024 00:52:31 +0100 Subject: [PATCH 52/55] remove redundant argument --- gap/io.gi | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 1018e4be5..a4273968c 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1389,13 +1389,13 @@ function(str) return ConvertToImmutableDigraphNC(out); end); -# BindGlobal("DIGRAPHS_FindDreadnautLine", -# function(original, line) -# local start; -# start := PositionSublist(original, line); -# return Length(PositionsProperty(original{[1 .. start + Length(line)]}, -# x -> x = '\n')) + 1; -# end); +BindGlobal("DIGRAPHS_FindDreadnautLine", +function(original, line) + local start; + start := PositionSublist(original, line); + return Length(PositionsProperty(original{[1 .. start + Length(line)]}, + x -> x = '\n')) + 1; +end); BindGlobal("DIGRAPHS_ParseDreadnautConfig", function(config, key) @@ -1470,7 +1470,7 @@ function(vertex, x, r) end); BindGlobal("DIGRAPHS_SplitDreadnautLines", -function(inputString, r) +function(inputString) local startPos, currentPos, segments, currentChar, nextChar, index, partition; @@ -1610,7 +1610,7 @@ function(graphData, r) edgeList := List([1 .. r.nValue], x -> []); NormalizeWhitespace(graphData); - parts := DIGRAPHS_SplitDreadnautLines(graphData, r); + parts := DIGRAPHS_SplitDreadnautLines(graphData); iter := 0; for part in parts do From 353c4ca66012c2517890bbe202469e0381a9fbfc Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:32:55 +0100 Subject: [PATCH 53/55] this works! need to make more robust + clean and there are probably more places where i could add in line on which error occurs --- gap/io.gi | 281 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 197 insertions(+), 84 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index a4273968c..1f7019c4b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1389,39 +1389,40 @@ function(str) return ConvertToImmutableDigraphNC(out); end); -BindGlobal("DIGRAPHS_FindDreadnautLine", -function(original, line) - local start; - start := PositionSublist(original, line); - return Length(PositionsProperty(original{[1 .. start + Length(line)]}, - x -> x = '\n')) + 1; -end); - BindGlobal("DIGRAPHS_ParseDreadnautConfig", -function(config, key) - local Pos, tempStr, tempConfig; +function(config, key, r) + local Pos, tempStr, tempConfig, test, localNewlineCount; - RemoveCharacters(config, " \n\r\t=-+"); + RemoveCharacters(config, " \r\t=-+"); tempConfig := ShallowCopy(config); RemoveCharacters(tempConfig, "Ag$ntd1234567890"); - if tempConfig <> "" and key <> "f" then + 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 unexpected ", - "characters: ", - JoinStringsWithSeparator(tempConfig, ","), - ","); + "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 Int(config{[Pos]}) <> fail do + 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; @@ -1430,14 +1431,17 @@ function(config, key) if tempStr = "" then if key <> "f" then ErrorNoReturn("the format of the file given as the 2nd ", - "argument cannot be determined. ", key, - " is not followed by a value"); + "argument cannot be determined. '", key, + "' (line ", localNewlineCount, ")", + " is not followed by a value,"); else ErrorNoReturn("the partition cannot be determined.", - " 'f' is neither followed", - " by a single value nor by a list of values"); + " '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 @@ -1452,36 +1456,49 @@ function(config, key) end); BindGlobal("DIGRAPHS_LegalDreadnautEdge", -function(vertex, x, r) +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)"); + 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). ", - "Ensure 'd' is declared to include loops."); + 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) +function(inputString, r) local startPos, currentPos, segments, currentChar, nextChar, index, - partition; + 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; @@ -1490,14 +1507,18 @@ function(inputString) if currentChar = '$' and nextChar = '$' then Info(InfoWarning, 1, "Vertex indexing will start at 1"); - if ForAny(inputString{[currentPos + 2 .. Length(inputString)]}, - c -> c in ".:") or - inputString{ - [currentPos + 2 .. Minimum([currentPos + 2, - Length(inputString)])]} = "$" - then + temp := PositionProperty( + inputString{[currentPos + 2 .. Length(inputString)]}, + c -> c in ".:"); + if temp <> fail then ErrorNoReturn("Syntax error: unexpected characters", - " (including ':' or '.') after \"$$\""); + "(including '.' or ':')", + " after \"$$\" (line ", + localNewlineCount + Length( + PositionsProperty( + inputString{[currentPos + 2 .. temp]}, + c -> c in "\n")), + ")"); else Add(segments, inputString{[startPos .. currentPos - 1]}); Add(segments, "$$"); @@ -1508,9 +1529,11 @@ function(inputString) fi; if currentChar in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q" then - Info(InfoWarning, 1, "while parsing dreadnaut file config,", + ErrorNoReturn("while parsing dreadnaut file,", " found operation ", - currentChar, " which is not supported."); + currentChar, " on line ", localNewlineCount, + ", which is not supported."); + startPos := currentPos + 1; fi; if currentChar = 'f' then # partition @@ -1518,20 +1541,39 @@ function(inputString) if PositionSublist( inputString{[currentPos + 1 .. Length(inputString)]}, "[") = fail then - index := DIGRAPHS_ParseDreadnautConfig(inputString{[currentPos .. - Length(inputString)]}, - "f"); - partition := [1 .. r.nValue]; - Remove(partition, index); - - Add(segments, Concatenation( - Concatenation( - Concatenation("f", String(index)), - " | "), JoinStringsWithSeparator(partition, " "))); - - startPos := PositionSublist( + 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)]}, - String(index)) + currentPos + 1; + c -> not c in + Concatenation( + "$ \nferRjstTvfFiIOlw+campyGS*kKVu?&Px@b=[]", + "z#oMh<>q0123456789;")), + ","), + "), "); + fi; else repeat @@ -1549,23 +1591,25 @@ function(inputString) if ForAll(inputString{[currentPos + 1 .. Length(inputString)]}, c -> c in Concatenation("$ \nferRjstTvFiIOlw+campyGS*kKVu?&Px@b", - "z#oMh<>q0123456789")) then + "z#oMh<>q0123456789;f[]=")) then Add(segments, Concatenation("f", inputString{[startPos .. currentPos - 1]})); startPos := currentPos + 1; else ErrorNoReturn( - "Syntax error: unexpected characters after \"]\" (", + "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"), + "z#oMh<>q0123456789;f[]=")), ","), - "), ")); + "), "); fi; fi; fi; @@ -1574,16 +1618,20 @@ function(inputString) if currentChar = ':' then repeat # backtrack to find the start of the vertex currentPos := currentPos - 1; - if inputString[currentPos] <> ' ' and + if (inputString[currentPos] in " \n") <> true and not IsDigitChar(inputString[currentPos]) then - ErrorNoReturn("Syntax error: unexpected character (", + 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]); + until currentPos <= 1 or (not IsDigitChar(inputString[currentPos])); if startPos < currentPos then Add(segments, inputString{[startPos .. currentPos - 1]}); fi; @@ -1594,8 +1642,19 @@ function(inputString) od; if ForAny(inputString{[startPos .. Length(inputString)]}, + # change this to looping over i c -> c in "erRjstTvFiIOlw+campyGS*kKVu?&Px@bz#oMh<>q") then - Info(InfoWarning, 1, "Ignoring unsupported operation."); + 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; @@ -1606,12 +1665,13 @@ BindGlobal("DIGRAPHS_ParseDreadnautGraph", function(graphData, r) local edgeList, part, parts, subparts, vertex, connectedTo, adjacencyPart, pparts, partition, i, j, num, iter, - pos; + pos, char, localNewlineCount, failure, temp; edgeList := List([1 .. r.nValue], x -> []); - NormalizeWhitespace(graphData); - parts := DIGRAPHS_SplitDreadnautLines(graphData); + RemoveCharacters(graphData, "\r\t"); + parts := DIGRAPHS_SplitDreadnautLines(graphData, r); iter := 0; + localNewlineCount := r.newlineCount; for part in parts do iter := iter + 1; @@ -1624,36 +1684,35 @@ function(graphData, r) x -> not IsDigitChar(x))); RemoveCharacters(part, "."); if ForAny(parts{[iter + 1 .. Length(parts)]}, - c -> ':' in c) then + c -> (':' in c or '.' in c)) then ErrorNoReturn("Syntax error: unexpected characters (including ':'", - ")after \".\"", + " or '.') after \".\"", "(note that edges cannot be declared after \".\")"); fi; fi; - if part = "" or part = ' ' or part = " " then + 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 \".\")"); + "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.dollarValue := DIGRAPHS_ParseDreadnautConfig(part, "$", r); fi; fi; if part[1] = 'f' then if Length(part) = 1 then # empty partition continue; - # elif not '[' in part then - # DIGRAPHS_ParseDreadnautConfig(part, "f"); fi; pparts := SplitString(part{[2 .. Length(part)]}, "|"); @@ -1687,21 +1746,41 @@ function(graphData, r) if - 1 in partition then ErrorNoReturn("partition is incomplete. The following vertices ", PositionsProperty(partition, x -> x = -1), - " do not feature in any part."); + "(1-indexed) do not feature in any part."); else r.partition := partition; fi; + continue; fi; subparts := SplitString(part, ":"); - if Length(subparts) = 0 or Length(subparts) = 1 then + if Length(subparts) = 0 then continue; + elif Length(subparts) = 1 then + if PositionSublist(" $$;", subparts[1]) <> fail then + continue; + else + ErrorNoReturn("formatting error ('", part, "'),"); + fi; else vertex := subparts[1]; - RemoveCharacters(vertex, " "); + for char in vertex do + if char = '\n' then + localNewlineCount := localNewlineCount + 1; + elif char = ' ' then + continue; + else + if not IsDigitChar(char) then + ErrorNoReturn("formatting error (", part, ") on line ", + localNewlineCount); + fi; + fi; + od; + RemoveCharacters(vertex, " \n"); vertex := Int(vertex); + r.newlineCount := localNewlineCount; adjacencyPart := subparts[2]; fi; @@ -1713,17 +1792,47 @@ function(graphData, r) continue; fi; - NormalizeWhitespace(adjacencyPart); # Remove extra spaces + # NormalizeWhitespace(adjacencyPart); # Remove extra spaces RemoveCharacters(adjacencyPart, ",;"); - connectedTo := List(SplitString(adjacencyPart, " "), Int); + # connectedTo := List(SplitString(adjacencyPart, " "), Int); + 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 fail in connectedTo then - ErrorNoReturn("Formatting error (", part, ")"); + 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); connectedTo := Filtered(connectedTo, - x -> DIGRAPHS_LegalDreadnautEdge(vertex, x, r)); + x -> DIGRAPHS_LegalDreadnautEdge(vertex, + x, r, part)); Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); @@ -1781,10 +1890,15 @@ function(name) fi; until IsEmpty(line); - r := rec(dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$"), - nValue := DIGRAPHS_ParseDreadnautConfig(config, "n"), - dExists := PositionSublist(config, "d") <> fail, - partition := fail); + file := IO_CompressedFile(UserHomeExpand(name), "r"); + + r := rec(dExists := PositionSublist(config, "d") <> fail, + partition := fail, + original := IO_ReadUntilEOF(file), + newlineCount := 1 + Length(PositionsProperty(config, x -> x = '\n'))); + + r.dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$", r); + r.nValue := DIGRAPHS_ParseDreadnautConfig(config, "n", r); if r.dollarValue <> 1 then Info(InfoWarning, 1, @@ -1799,7 +1913,6 @@ function(name) if r.partition <> fail then SetDigraphVertexLabels(D, r.partition); fi; - return D; else Info(InfoWarning, 1, "The graph is undirected and so will be symmetrised."); @@ -1807,8 +1920,8 @@ function(name) if r.partition <> fail then SetDigraphVertexLabels(D, r.partition); fi; - return D; fi; + return D; end); ################################################################################ From 88c6167c5fb7386c989b18c428b5dc2aa80bbe84 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:44:57 +0100 Subject: [PATCH 54/55] passing tst, added support for multiple vertex declaration of the form 1 2 : 3 4 --- gap/io.gi | 71 +++++++++++++++++++++++++++------------------ tst/standard/io.tst | 5 ++-- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/gap/io.gi b/gap/io.gi index 1f7019c4b..7972a640b 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1665,7 +1665,8 @@ 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; + pos, char, localNewlineCount, failure, temp, vertices, + components, p; edgeList := List([1 .. r.nValue], x -> []); RemoveCharacters(graphData, "\r\t"); @@ -1760,41 +1761,48 @@ function(graphData, r) 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; else ErrorNoReturn("formatting error ('", part, "'),"); fi; - else - vertex := subparts[1]; - for char in vertex do - if char = '\n' then + 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; - elif char = ' ' then - continue; - else - if not IsDigitChar(char) then - ErrorNoReturn("formatting error (", part, ") on line ", - localNewlineCount); - fi; - fi; od; - RemoveCharacters(vertex, " \n"); - vertex := Int(vertex); r.newlineCount := localNewlineCount; adjacencyPart := subparts[2]; fi; - vertex := vertex - r.dollarValue + 1; + for vertex in vertices do - if vertex > r.nValue or vertex < 1 then - Info(InfoWarning, 1, "Ignoring illegal vertex ", vertex, - " (original indexing)"); - continue; - fi; + 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; - # NormalizeWhitespace(adjacencyPart); # Remove extra spaces RemoveCharacters(adjacencyPart, ",;"); - # connectedTo := List(SplitString(adjacencyPart, " "), Int); connectedTo := []; temp := ""; @@ -1820,6 +1828,9 @@ function(graphData, r) fi; fi; od; + if temp <> "" then + Add(connectedTo, Int(temp)); + fi; failure := PositionProperty(connectedTo, x -> x = fail); if failure <> fail then @@ -1830,12 +1841,15 @@ function(graphData, r) fi; connectedTo := List(connectedTo, x -> x - r.dollarValue + 1); - connectedTo := Filtered(connectedTo, - x -> DIGRAPHS_LegalDreadnautEdge(vertex, - x, r, part)); - Append(edgeList[vertex], connectedTo); - edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); + 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; od; return edgeList; @@ -1894,7 +1908,6 @@ function(name) r := rec(dExists := PositionSublist(config, "d") <> fail, partition := fail, - original := IO_ReadUntilEOF(file), newlineCount := 1 + Length(PositionsProperty(config, x -> x = '\n'))); r.dollarValue := DIGRAPHS_ParseDreadnautConfig(config, "$", r); diff --git a/tst/standard/io.tst b/tst/standard/io.tst index e2117aa9b..a1c5ddadc 100644 --- a/tst/standard/io.tst +++ b/tst/standard/io.tst @@ -966,7 +966,7 @@ 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;q");; +gap> IO_WriteLine(file, " 3 : 2;");; gap> IO_Close(file);; gap> ReadDreadnautGraph(filename); @@ -978,8 +978,7 @@ 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 unexpected characters: 's','i','l','l','y','e','x','f','o\ -','r','e','s','i', +mined as it contains an unexpected character: 's' on line 1 # DIGRAPHS_UnbindVariables gap> Unbind(D); From ec209e9a7324c0afb44abdcaa07f11d8400fd054 Mon Sep 17 00:00:00 2001 From: Pramoth Ragavan <107881923+pramothragavan@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:50:19 +0000 Subject: [PATCH 55/55] support for lines w/out colons --- gap/io.gi | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gap/io.gi b/gap/io.gi index 7972a640b..c45bbfd02 100644 --- a/gap/io.gi +++ b/gap/io.gi @@ -1666,13 +1666,15 @@ 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; + 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; @@ -1765,6 +1767,12 @@ function(graphData, r) 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; @@ -1802,6 +1810,10 @@ function(graphData, r) od; + if PositionSublist(adjacencyPart, ";") <> fail then + runningSemi := true; + fi; + RemoveCharacters(adjacencyPart, ",;"); connectedTo := []; temp := ""; @@ -1850,6 +1862,7 @@ function(graphData, r) Append(edgeList[vertex], connectedTo); edgeList[vertex] := DuplicateFreeList(edgeList[vertex]); od; + lastVertex := vertex; od; return edgeList; @@ -1910,6 +1923,7 @@ function(name) 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);