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

Clarify homomorphisms finder with specified image #700

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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
/doc/*.css
/doc/*.js
Makefile
_*.xml
aclocal.m4
autom4te.*
bin/
Expand All @@ -54,9 +55,9 @@ digraphs-lib
doc/_*.xml
gen/
gh-pages/
main.xml
manual.lab
missing
src/pkgconfig.h.in
tags
tst/out/
_*.xml
47 changes: 39 additions & 8 deletions doc/grahom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,20 @@
This argument should be a subset of the vertices of the graph <A>D2</A>.
<C>HomomorphismDigraphsFinder</C> only finds homomorphisms from
<A>D1</A> to the subgraph of <A>D2</A> induced by the vertices
<A>image</A>.
<A>image</A>.<P/>

The returned homomorphisms (if any) are still "up to the action" of the
group specified by <A>aut_grp</A> (which is the entire automorphism
group by default). This might generate unexpected results. For example,
if <A>D1</A> has automorphism group where one orbit consists of, say,
<C>1</C> and <C>2</C>, then <C>HomomorphismDigraphsFinder</C> will only
attempt to find homomorphisms mapping <C>1</C> to <C>1</C>, and if
there are no such homomorphisms with image set equal to <A>image</A>,
then no homomorphisms will be returned (even if there is a homomorphism
from <A>D1</A> to <A>D2</A> mapping <C>1</C> to <C>2</C>). To ensure that
that <B>all</B> homomorphisms with image set equal to <A>image</A> are
considered it is necessary for the last argument <A>aut_grp</A> to be
the trivial permutation group.
</Item>

<Mark><A>partial_map</A></Mark>
Expand Down Expand Up @@ -133,6 +146,7 @@
idea for this to be the <Ref Attr="DigraphWelshPowellOrder"/>, i.e.
vertices ordered from highest to lowest degree.
</Item>
<Mark><A>aut_grp</A></Mark>
<Item>
The optional argument <A>aut_grp</A> should be a subgroup of the
automorphism group of <A>D2</A>. This function returns unique
Expand All @@ -149,6 +163,10 @@ gap> D := DigraphSymmetricClosure(D);
<immutable symmetric digraph with 10 vertices, 18 edges>
gap> HomomorphismDigraphsFinder(D, D, fail, [], infinity, 2, 0,
> [3, 4], [], fail, fail);
#I WARNING you are trying to find homomorphisms by specifying a subset
of the vertices of the target digraph. This might lead to unexpected
results! If this happens, try passing Group(()) as the last argument.
Please see the documentation of HomomorphismDigraphsFinder for details.
[ Transformation( [ 3, 4, 3, 4, 3, 4, 3, 4, 3, 4 ] ),
Transformation( [ 4, 3, 4, 3, 4, 3, 4, 3, 4, 3 ] ) ]
gap> D2 := CompleteDigraph(6);;
Expand Down Expand Up @@ -648,14 +666,27 @@ gap> EmbeddingsDigraphs(D1, D2);
A permutation or transformation <A>x</A> is a <E>homomorphism</E> from a
digraph <A>src</A> to a digraph <A>ran</A> if the following hold:
<List>
<Item>
<C>[u ^ <A>x</A>, v ^ <A>x</A>]</C> is an edge of
<A>ran</A> whenever <C>[u, v]</C> is an
edge of <A>src</A>; and </Item>
<Item>
<A>x</A> fixes every <C>i</C> which is not a vertex of <A>src</A>.
</Item>
<Item>
<C>[u ^ <A>x</A>, v ^
<A>x</A>]</C> is an edge of <A>ran</A> whenever <C>[u, v]</C> is an edge of
<A>src</A>; and
</Item>
<Item>
<A>x</A> maps the vertices of <A>src</A> to a subset of the vertices of
<A>ran</A>, i.e. <C>IsSubset(DigraphVertices(<A>ran</A>),
OnSets(DigraphVertices(<A>src</A>), <A>x</A>))</C> is <K>true</K>.
</Item>
</List>

Note that if <C>i</C> is any integer greater than
<C>DigraphNrVertice(<A>src</A>)</C>, then the action of <A>x</A> on
<C>i</C> is ignored by this function. One consequence of this is that
distinct transformations or permutations might represent the same
homomorphism. For example, if <A>src</A> and <A>ran</A> are
<C>CycleDigraph(2)</C>, then both the permutations <C>(1, 2)</C> and <C>(1,
2)(3, 4)</C> represent the same automorphism of <A>src</A>.
<P/>

See also <Ref Func="GeneratorsOfEndomorphismMonoid"/>.<P/>


Expand Down
2 changes: 1 addition & 1 deletion doc/isomorph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ true
gap> IsDigraphAutomorphism(src, (2, 3), [2, 2, 1]);
false
gap> IsDigraphAutomorphism(src, (2, 3)(4, 5));
false
true
gap> IsDigraphAutomorphism(src, (1, 4));
false
gap> IsDigraphAutomorphism(src, ());
Expand Down
5 changes: 3 additions & 2 deletions gap/grahom.gi
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ function(H, G)
[], # partial_map
fail, # colors1
fail, # colors2
DigraphWelshPowellOrder(H));
DigraphWelshPowellOrder(H),
Group(()));
if Length(map) <> 0 then
Add(result, map[1]);
fi;
Expand Down Expand Up @@ -576,7 +577,7 @@ function(src, ran, x)
if IsMultiDigraph(src) or IsMultiDigraph(ran) then
ErrorNoReturn("the 1st and 2nd arguments <src> and <ran> must be digraphs",
" with no multiple edges,");
elif LargestMovedPoint(x) > DigraphNrVertices(src) then
elif not IsSubset(DigraphVertices(ran), OnSets(DigraphVertices(src), x)) then
return false;
fi;
for i in DigraphVertices(src) do
Expand Down
5 changes: 3 additions & 2 deletions src/bitarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
////////////////////////////////////////////////////////////////////////

bool LOOKUPS_INITIALISED = false;
size_t* NR_BLOCKS_LOOKUP = NULL;
size_t* NR_BLOCKS_LOOKUP = NULL;
size_t* QUOTIENT_LOOKUP = NULL;
size_t* REMAINDER_LOOKUP = NULL;
Block* MASK_LOOKUP = NULL;
Expand Down Expand Up @@ -113,7 +113,7 @@ BitArray* new_bit_array(uint16_t const nr_bits) {
bit_array->nr_bits = nr_bits;
bit_array->nr_blocks =
((nr_bits % NR_BITS_PER_BLOCK) == 0 ? nr_bits / NR_BITS_PER_BLOCK
: nr_bits / NR_BITS_PER_BLOCK + 1);
: nr_bits / NR_BITS_PER_BLOCK + 1);
bit_array->blocks = safe_calloc(bit_array->nr_blocks, NR_BITS_PER_BLOCK);

return bit_array;
Expand Down Expand Up @@ -141,6 +141,7 @@ void set_bit_array_from_gap_list(BitArray* const bit_array, Obj list_obj) {
return;
}
init_bit_array(bit_array, false, bit_array->nr_bits);
// TODO assert that bit_array->nr_bits > LEN_LIST(list_obj)?
for (int i = 1; i <= LEN_LIST(list_obj); i++) {
if (ISB_LIST(list_obj, i)) {
set_bit_array_from_gap_int(bit_array, ELM_LIST(list_obj, i));
Expand Down
1 change: 1 addition & 0 deletions src/bitarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,5 @@ void set_bit_array_from_gap_int(BitArray* const bit_array, Obj o);
//! plain or dense).
void set_bit_array_from_gap_list(BitArray* const bit_array, Obj list_obj);

// void print_bit_array(BitArray const* const bit_array);
#endif // DIGRAPHS_SRC_BITARRAY_H_
2 changes: 2 additions & 0 deletions src/digraphs.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Obj IsSubset;
Obj OnTuples;
Obj Group;
Obj ClosureGroup;
Obj InfoWarning;

static inline bool IsAttributeStoringRep(Obj o) {
return (CALL_1ARGS(IsAttributeStoringRepObj, o) == True ? true : false);
Expand Down Expand Up @@ -2195,6 +2196,7 @@ static Int InitKernel(StructInitInfo* module) {
ImportGVarFromLibrary("OnTuples", &OnTuples);
ImportGVarFromLibrary("Group", &Group);
ImportGVarFromLibrary("ClosureGroup", &ClosureGroup);
ImportGVarFromLibrary("InfoWarning", &InfoWarning);
/* return success */
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/digraphs.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ extern Obj GeneratorsOfGroup;
extern Obj IsDigraph;
extern Obj IsMultiDigraph;
extern Obj IsDigraphEdge;
extern Obj InfoWarning;

#endif // DIGRAPHS_SRC_DIGRAPHS_H_
45 changes: 38 additions & 7 deletions src/homos.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@
// 1. Try other bit hacks for iterating through set bits

#include "homos.h"

// C headers
#include <setjmp.h> // for longjmp, setjmp, jmp_buf
#include <stdbool.h> // for true, false, bool
#include <stddef.h> // for NULL
#include <stdint.h> // for uint16_t, uint64_t
#include <stdlib.h> // for malloc, NULL
#ifdef DIGRAPHS_ENABLE_STATS
#include <time.h> // for time
#endif

// GAP headers
#include "gap-includes.h"
Expand All @@ -50,6 +48,12 @@
#include "safemalloc.h" // for safe_mallov
#include "schreier-sims.h" // for PermColl, . . .

#ifdef DIGRAPHS_ENABLE_STATS
// This include has to come after digraphs-config.h since that's where
// DIGRAPHS_ENABLE_STATS is defined
#include <time.h> // for time
#endif

////////////////////////////////////////////////////////////////////////////////
// 1. Macros
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -135,6 +139,7 @@ extern Obj AutomorphismGroup;
extern Obj IsPermGroup;
extern Obj IsDigraphAutomorphism;
extern Obj LargestMovedPointPerms;
extern Obj InfoWarning;

////////////////////////////////////////////////////////////////////////////////
// 3. Global variables
Expand All @@ -147,7 +152,6 @@ static Obj (*HOOK)(void*, // HOOK function applied to every homo found
const uint16_t*);
static void* USER_PARAM; // a USER_PARAM for the hook

// Values in MAP are restricted to those positions in IMAGE_RESTRICT
static jmp_buf OUTOFHERE; // so we can jump out of the deepest

static bool ORDERED; // true if the vertices of the domain/source digraph
Expand Down Expand Up @@ -680,6 +684,7 @@ static void find_graph_homos(uint16_t depth,
}
}
DIGRAPHS_ASSERT(get_bit_array(MAP_UNDEFINED[depth], next));
DIGRAPHS_ASSERT(next < GRAPH1->nr_vertices);

if (rank < hint) {
copy_bit_array(
Expand Down Expand Up @@ -1748,6 +1753,7 @@ static bool init_data_from_args(Obj digraph1_obj,
set_bit_array_from_gap_list(IMAGE_RESTRICT, image_obj);
if (INT_INTOBJ(injective_obj) > 0
&& size_bit_array(IMAGE_RESTRICT, nr1) < nr1) {
// TODO shouldn't the first nr1 be nr2?
// homomorphisms should be injective (by injective_obj) but are not since
// the image is too restricted.
return false;
Expand Down Expand Up @@ -1930,9 +1936,10 @@ static bool init_data_from_args(Obj digraph1_obj,
// group will be used.

Obj FuncHomomorphismDigraphsFinder(Obj self, Obj args) {
if (LEN_PLIST(args) != 11 && LEN_PLIST(args) != 12 && LEN_PLIST(args) != 13) {
ErrorQuit(
"there must be 11 or 12 arguments, found %d,", LEN_PLIST(args), 0L);
if (LEN_PLIST(args) < 11 || LEN_PLIST(args) > 13) {
ErrorQuit("there must be 11, 12, or 13 arguments, found %d,",
LEN_PLIST(args),
0L);
}
Obj digraph1_obj = ELM_PLIST(args, 1);
Obj digraph2_obj = ELM_PLIST(args, 2);
Expand Down Expand Up @@ -2184,6 +2191,30 @@ Obj FuncHomomorphismDigraphsFinder(Obj self, Obj args) {
}
}

if (image_obj != Fail
&& LEN_LIST(image_obj) != DigraphNrVertices(digraph2_obj)) {
bool warn = false;
if (aut_grp_obj == Fail) {
warn = true;
} else {
Obj gens = CALL_1ARGS(GeneratorsOfGroup, aut_grp_obj);
Int lmp = INT_INTOBJ(CALL_1ARGS(LargestMovedPointPerms, gens));
warn = lmp > 0;
}
if (warn) {
Obj msg = MakeImmString(
"WARNING you are trying to find homomorphisms by specifying a "
"subset of the vertices of the target digraph. This might lead "
"to unexpected results! If this happens, try passing Group(()) as "
"the last argument. Please see the documentation of "
"HomomorphismDigraphsFinder for details.");
Obj info_args = NEW_PLIST(T_PLIST, 1);
SET_ELM_PLIST(info_args, 1, msg);
SET_LEN_PLIST(info_args, 1);
InfoDoPrint(InfoWarning, INTOBJ_INT(0), info_args);
}
}

// Some conditions that immediately rule out there being any homomorphisms.
if (((INT_INTOBJ(injective_obj) == 1 || INT_INTOBJ(injective_obj) == 2)
&& ((hint_obj != Fail
Expand Down
25 changes: 10 additions & 15 deletions src/perms.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,29 @@ Perm new_perm(uint16_t const degree) {
}

Perm new_perm_from_gap(Obj gap_perm_obj, uint16_t const degree) {
UInt lmp = LargestMovedPointPerm(gap_perm_obj);
DIGRAPHS_ASSERT(lmp <= MAXVERTS);
if (lmp > MAXVERTS) {
ErrorQuit("expected permutations of degree at most %d, but got a "
"permutation of degree %d",
MAXVERTS,
lmp);
}

DIGRAPHS_ASSERT(lmp <= degree);

Perm p = new_perm(degree > 0 ? degree : 1);

size_t copy_up_to = degree;
size_t lmp = LargestMovedPointPerm(gap_perm_obj);
if (degree > lmp) {
copy_up_to = lmp;
}

if (IS_PERM2(gap_perm_obj)) {
UInt2* gap_perm_ptr = ADDR_PERM2(gap_perm_obj);
for (UInt i = 0; i < lmp; ++i) {
for (UInt i = 0; i < copy_up_to; ++i) {
p[i] = gap_perm_ptr[i];
}
for (UInt i = lmp; i < degree; ++i) {
for (UInt i = copy_up_to; i < degree; ++i) {
p[i] = i;
}
} else {
DIGRAPHS_ASSERT(IS_PERM4(gap_perm_obj));
UInt4* gap_perm_ptr = ADDR_PERM4(gap_perm_obj);
for (UInt i = 0; i < lmp; ++i) {
for (UInt i = 0; i < copy_up_to; ++i) {
p[i] = gap_perm_ptr[i];
}
for (UInt i = lmp; i < degree; ++i) {
for (UInt i = copy_up_to; i < degree; ++i) {
p[i] = i;
}
}
Expand Down
4 changes: 4 additions & 0 deletions tst/extreme/grahom.tst
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ gap> Size(Semigroup(gens));
105120
gap> HomomorphismDigraphsFinder(gr, gr, fail, [], infinity, fail, 0,
> [1, 14, 28, 39, 42], [], fail, fail);;
#I WARNING you are trying to find homomorphisms by specifying a subset of the vertices of the target digraph. This might lead to unexpected results! If this happens, try passing Group(()) as the last argument. Please see the documentation of HomomorphismDigraphsFinder for details.
gap> str := HomomorphismDigraphsFinder(gr, gr, fail, [], infinity, fail, 0,
> [1, 14, 28, 39, 42], [], fail, fail);;
#I WARNING you are trying to find homomorphisms by specifying a subset of the vertices of the target digraph. This might lead to unexpected results! If this happens, try passing Group(()) as the last argument. Please see the documentation of HomomorphismDigraphsFinder for details.
gap> Length(str);
192

Expand Down Expand Up @@ -424,12 +426,14 @@ gap> HomomorphismDigraphsFinder(gr1, gr2, fail, [], 1, 25, 0, [1 .. 40],
37, 38 ] ) ]
gap> t := HomomorphismDigraphsFinder(gr1, gr2, fail, [], 1, 23, 0,
> [4 .. 37], [], fail, fail, DigraphWelshPowellOrder(gr1))[1];
#I WARNING you are trying to find homomorphisms by specifying a subset of the vertices of the target digraph. This might lead to unexpected results! If this happens, try passing Group(()) as the last argument. Please see the documentation of HomomorphismDigraphsFinder for details.
Transformation( [ 15, 11, 4, 7, 4, 9, 6, 17, 11, 31, 10, 7, 25, 9, 26, 22, 29,
8, 21, 27, 25, 25, 30, 19, 18, 13, 16, 8, 5, 32, 31, 32 ] )
gap> ForAll(DigraphEdges(gr1), e -> IsDigraphEdge(gr2, [e[1] ^ t, e[2] ^ t]));
true
gap> t := HomomorphismDigraphsFinder(gr1, gr2, fail, [], 1, 23, 0,
> [6 .. 37], [], fail, fail, DigraphWelshPowellOrder(gr1))[1];
#I WARNING you are trying to find homomorphisms by specifying a subset of the vertices of the target digraph. This might lead to unexpected results! If this happens, try passing Group(()) as the last argument. Please see the documentation of HomomorphismDigraphsFinder for details.
Transformation( [ 13, 20, 6, 30, 25, 24, 6, 23, 17, 30, 14, 9, 29, 11, 19, 28,
13, 34, 32, 7, 9, 10, 18, 15, 12, 21, 7, 11, 37, 19, 31, 32, 33, 34, 35, 36,
37 ] )
Expand Down
Loading
Loading