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

Adds MaximalCommonSubdigraph and MinimalCommonSupergraph #334

Closed
wants to merge 7 commits into from

Conversation

le27
Copy link
Collaborator

@le27 le27 commented Aug 19, 2020

The function MaximalCommonSubdigraph takes as input 2 digraphs and returns as output a digraph of maximum size which embeds into both of them as an induced subdigraph, as well embeddings of it into the given digraphs. The embeddings are given as transformations.

The function MinimalCommonSuperdigraph takes as input 2 digraphs and returns as output a digraph of minimum size which embeds into both into which they both embed as induced subdigraphs, as well embeddings of the given digraphs into it. The embeddings are again given as transformations.

@le27
Copy link
Collaborator Author

le27 commented Aug 19, 2020

don't merge, something weird is happening with the commits

@le27 le27 force-pushed the minmax branch 3 times, most recently from 3751e56 to 0507ff4 Compare August 19, 2020 17:10
@le27
Copy link
Collaborator Author

le27 commented Aug 19, 2020

I think I fixed the problem I mentioned in my previous message

Copy link
Contributor

@tomcontileslie tomcontileslie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid I got lost trying to figure out the mathematical details of the implementation, but from what I can see this looks great, and it works really well! I have asked two questions in my review, apologies if they are a bit naive, I may have overlooked the reasons you chose to do things otherwise.

Also, I don't know whether you wanted to maybe add some documentation for these two new functions; looks like they'd fit quite well in either section 3.3, or maybe 7.2 or 7.3.

gap/grahom.gi Outdated
Clqus := DigraphMaximalCliquesReps(B);

if Clqus = [] then
return [Digraph([]), [], []];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would there potentially be an interest in getting the second and third list elements to be transformations in this case? I'm not sure what you think of returning IdentityTransformation rather than [] if the maximal common subdigraph has no vertices; but that way we can guarantee that this function will always output a list which has transformations as second and third elements. For example,

gap> comm := MaximalCommonSubdigraph(D1, D2);;
gap> 2 ^ comm[2];

will never return any errors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I'll fix this this thanks.

gap> MaximalCommonSubdigraph(CompleteDigraph(100), CompleteDigraph(100));
[ <immutable digraph with 100 vertices, 9900 edges>, IdentityTransformation,
IdentityTransformation ]
gap> MinimalCommonSuperdigraph(CompleteDigraph(100), CompleteDigraph(100));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be even more certain that these functions continue working in the future, perhaps there should be some tests that check not only equality of display, but also equality of objects, here? For example:

gap> comm := MinimalCommonSuperdigraph(CompleteDigraph(100), CompleteDigraph(100));;
gap> comm[1] = CompleteDigraph(100);
true

I'm not sure to what extent this is implemented in other test files, it may be overkill :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea

Copy link
Member

@james-d-mitchell james-d-mitchell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve the efficiency!

gap/grahom.gi Outdated
out1 := OutNeighbours(D1);
out2 := OutNeighbours(D2);

adj := function(pair)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure that we've discussed this already, but I think you could improve the performance here, by:

  1. Not using Cartesian but instead doing:
L := List([1 .. Size(out1) * Size(out2)], x -> []);
for i in [1 .. Size(out1)] do
  for j in [1 .. Size(out2)] do
    if isadj(i, j) then
       Add(L[i], j); 
    fi;
  od;
od;

Also the function isadj could be improved, by to run through the out neighbours of D1 and D2 once by using the adjacency matrix of D1 and D2

@james-d-mitchell james-d-mitchell added the new-feature A label for new features. label Oct 15, 2020
Copy link
Member

@james-d-mitchell james-d-mitchell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@le27 this is awesome, but you still need to write the documentation please!

edges := List([1 .. n * m], x -> []);
for i in [0 .. (n * m * n * m - 1)] do
t := intto4tuple(i);
# not that we are only concerned with cliques so we can ignore edges
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# not that we are only concerned with cliques so we can ignore edges
# note that we are only concerned with cliques so we can ignore edges

end;

# As we are only concerned with cliques we don't need to consider the isolated
# vertices of MPG so we constrict it without them
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# vertices of MPG so we constrict it without them
# vertices of MPG so we construct it without them

if vertices = [] then
for i in DigraphVertices(D1) do
for j in DigraphVertices(D2) do
if AdjacencyMatrix(D1)[i][i] = AdjacencyMatrix(D2)[j][j] then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You assign the variables A1 and A2 to AdjacencyMatrix(D1) and AdjacencyMatrix(D2) above, so why not use these variables again here?

# we represent an element of V(D1)xV(D2)xV(D1)xV(D2) as an element of
# [0 .. (n x m x n x m) - 1]
intto4tuple := function(i)
local t, tempi;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be more compact as:

  intto4tuple := i -> [RemInt(i, n),
                              QuoInt(RemInt(i, n * m), n),
                              QuoInt(RemInt(i, n * m * n), n * m),
                              QuoInt(i, n * m * n)];

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But with things properly aligned...

D1 := DigraphImmutableCopy(A);
D2 := DigraphImmutableCopy(B);

# If the digraphs are isomorphic then we return the first one as the answer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the isomorphism check be done before A and B are copied? After all what's the point of copying them if it's not necessary.

@james-d-mitchell
Copy link
Member

Superseded by #361

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new-feature A label for new features.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants