Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added method AllUndirectedSimpleCircuits #689

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions doc/attr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,46 @@ gap> DigraphLongestSimpleCircuit(D);
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAllUndirectedSimpleCircuits">
<ManSection>
<Attr Name="DigraphAllUndirectedSimpleCircuits" Arg="digraph"/>
<Returns>A list of lists of vertices.</Returns>
<Description>
If <A>digraph</A> is a digraph, then <C>DigraphAllUndirectedSimpleCircuits</C>
returns a list of the <E> undirected simple circuits</E> in <A>digraph</A>. <P/>

See Section <Ref Subsect="Definitions" Style="Number" /> for the definition
of a simple circuit, and related notions. Note that a loop is a simple
circuit. A simple circuit is undirected if the orientation of the edges
in the circuit does not matter.<P/>

The attribute <C>DigraphAllUndirectedSimpleCircuitss</C> ignores
multiple edges, and identifies a undirected simple circuit using only its subsequence
of vertices.
See Section <Ref Subsect="DigraphAllSimpleCircuits" Style="Number" /> for more details
on simple circuits.<P/>

<Example><![CDATA[
gap> D := ChainDigraph(10);;
gap> DigraphAllUndirectedSimpleCircuits(D);
[ ]
gap> D := Digraph([[1, 1]]);
<immutable multidigraph with 1 vertex, 2 edges>
gap> DigraphAllUndirectedSimpleCircuits(D);
[ [ 1 ] ]
gap> D := CycleDigraph(IsMutableDigraph, 3);
<mutable digraph with 3 vertices, 3 edges>
gap> DigraphAllUndirectedSimpleCircuits(D);
[ [ 1, 2, 3 ] ]
gap> D := DigraphSymmetricClosure(CycleDigraph(IsMutableDigraph, 3));
<mutable digraph with 3 vertices, 6 edges>
gap> DigraphAllUndirectedSimpleCircuits(D);
[ [ 1, 2, 3 ] ]
]]></Example>
</Description>
</ManSection>
<#/GAPDoc>

<#GAPDoc Label="DigraphAllChordlessCycles">
<ManSection>
<Attr Name="DigraphAllChordlessCycles" Arg="digraph"/>
Expand Down
1 change: 1 addition & 0 deletions doc/z-chap4.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<#Include Label="IteratorOfPaths">
<#Include Label="DigraphAllSimpleCircuits">
<#Include Label="DigraphLongestSimpleCircuit">
<#Include Label="DigraphAllUndirectedSimpleCircuits">
<#Include Label="DigraphAllChordlessCycles">
<#Include Label="DigraphLayers">
<#Include Label="DigraphDegeneracy">
Expand Down
1 change: 1 addition & 0 deletions gap/attr.gd
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ DeclareAttribute("DigraphAbsorptionExpectedSteps", IsDigraph);

DeclareAttribute("DigraphAllSimpleCircuits", IsDigraph);
DeclareAttribute("DigraphLongestSimpleCircuit", IsDigraph);
DeclareAttribute("DigraphAllUndirectedSimpleCircuits", IsDigraph);
DeclareAttribute("DigraphAllChordlessCycles", IsDigraph);
DeclareAttribute("HamiltonianPath", IsDigraph);
DeclareAttribute("DigraphPeriod", IsDigraph);
Expand Down
20 changes: 20 additions & 0 deletions gap/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,26 @@ function(D)
return Concatenation(loops, out);
end);

# Compute all undirected simple circuits by filtering the output
# of DigraphAllSimpleCircuits
InstallMethod(DigraphAllUndirectedSimpleCircuits, "for a digraph", [IsDigraph],
function(D)
local digraph, cycles, keep, cycle, cycleRev;
digraph := DigraphSymmetricClosure(
DigraphRemoveAllMultipleEdges(DigraphMutableCopyIfMutable(D)));
cycles := Filtered(DigraphAllSimpleCircuits(digraph),
c -> Length(c) > 2 or Length(c) = 1);
keep := HashSet();
for cycle in cycles do
cycleRev := [cycle[1]];
Append(cycleRev, Reversed(cycle{[2 .. Length(cycle)]}));
if (not cycle in keep and not cycleRev in keep) or Length(cycle) = 1 then
AddSet(keep, cycle);
fi;
od;
return Set(keep);
end);

# Compute all chordless cycles for a given symmetric digraph
# Algorithm based on https://arxiv.org/pdf/1404.7610
InstallMethod(DigraphAllChordlessCycles, "for a digraph",
Expand Down
31 changes: 31 additions & 0 deletions tst/standard/attr.tst
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,37 @@ gap> gr := Digraph([[3, 6, 7], [3, 6, 8], [1, 2, 3, 6, 7, 8],
gap> Length(DigraphAllSimpleCircuits(gr));
259

# DigraphAllUndirectedSimpleCircuits
gap> gr := Digraph([]);;
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ ]
gap> gr := ChainDigraph(4);;
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ ]
gap> gr := CompleteDigraph(2);;
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ ]
gap> gr := CompleteDigraph(3);;
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ [ 1, 2, 3 ] ]
gap> gr := Digraph([[], [3], [2, 4], [5, 4], [4]]);
<immutable digraph with 5 vertices, 6 edges>
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ [ 4 ] ]
gap> gr := Digraph([[1, 2], [2, 1]]);
<immutable digraph with 2 vertices, 4 edges>
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ [ 1 ], [ 2 ] ]
gap> gr := Digraph([[4], [1, 3], [1, 2], [2, 3]]);;
gap> DigraphAllUndirectedSimpleCircuits(gr);
[ [ 1, 2, 3 ], [ 1, 2, 3, 4 ], [ 1, 2, 4 ], [ 1, 2, 4, 3 ], [ 1, 3, 2, 4 ],
[ 1, 3, 4 ], [ 2, 3, 4 ] ]
gap> gr := Digraph([[3, 6, 7], [3, 6, 8], [1, 2, 3, 6, 7, 8],
> [2, 3, 4, 8], [2, 3, 4, 5, 6, 7], [1, 3, 4, 5, 7], [2, 3, 6, 8],
> [1, 2, 3, 8]]);;
gap> Length(DigraphAllUndirectedSimpleCircuits(gr));
1330

# DigraphAllChordlessCycles
gap> gr := Digraph([]);;
gap> DigraphAllChordlessCycles(gr);
Expand Down
Loading