ans = sparseg_adjl_is_planar(V, n, A, c,
&dfs_tree, &back_edges, &mult_edges,
&embed_graph, &edge_pos, &v, &w);
if (!ans)
{
embedg_obstruction(V, A, dfs_tree, back_edges,
embed_graph, n, &edge_pos,
v, w, VR, AR, nbr_e_obs);
} else
{
embedg_embedding(V, A, embed_graph, n, e, *c, edge_pos, mult_edges,
VR, ER);
}
int *
sparseg_adjl_footprint (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, int v) /* returnv'sfootprint: anarrayfpofsizenwherefp[i]=indexof(directed) edge[v,i]inA
*/
{ /* notethatwewon'tinitialisethearray: itssubsequentusagedoesn'trequireit
*/ int *fp, e;
fp = (int *) mem_malloc(sizeof(int) * n);
if (V[v].first_edge == NIL) /* donothing
*/ return fp;
e = V[v].first_edge; while (e != NIL)
{
fp[A[e].end_vertex] = e;
e = A[e].next;
}
return fp;
}
void
sparseg_adjl_print (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, boolean user_level)
{ int v;
for (v = 0; v < n; v++)
{ int next;
if (user_level)
fprintf(stdout, "%d:\t", v + 1); else
fprintf(stdout, "%d:\t", v);
next = V[v].first_edge; while (next != NIL)
{ if (user_level)
fprintf(stdout, "%d ", A[next].end_vertex + 1); else
fprintf(stdout, "%d ", A[next].end_vertex);
next = A[next].next;
}
fprintf(stdout, "\n");
}
}
void
sparseg_adjl_embed_print (t_ver_sparse_rep *V_e, int n,
t_adjl_sparse_rep *A, t_embed_sparse_rep *E, boolean user_level) /* printtheembeddinggivenbyE, edgesarereferredtobytheirindexinA
graph *
sparseg_adjl_to_nauty_graph (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A) /* writethesparsegraphasanautygraph
*/
{ int m, v, e, i;
graph *g;
m = (n + WORDSIZE - 1) / WORDSIZE;
g = (graph *) mem_malloc(n * m * sizeof(graph)); for (i = (long) m * n; --i >= 0;)
g[i] = 0;
/* wefirstcopyVandA'sinformationintog
*/ for (v = 0; v < n; v++)
{
e = V[v].first_edge; while (e != NIL) /* A[e].end_vertexisthenextneighbourinthelist, A[e].nextpointstothenextedgeinthelist
*/
{ if (A[e].end_vertex != v) /* no loops */
{
ADDELEMENT(GRAPHROW(g, v, m), A[e].end_vertex);
}
e = A[e].next;
}
}
return g;
}
#if0
t_edge_sparse_rep *
sparseg_adjl_edges (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, int e, boolean digraph) /* eisthenumberofedges
*/
{
t_edge_sparse_rep *edges; int m, u, v, pos_e;
graph *g;
m = (n + WORDSIZE - 1) / WORDSIZE;
g = sparseg_adjl_to_nauty_graph(V, n, A);
pos_e = 0; for (u = 0; u < n; u++)
{
v = digraph == TRUE ? 0 : u + 1; for (; v < n; v++)
{ if (ISELEMENT(GRAPHROW(g, u, m), v))
{
t_edge_sparse_rep edge;
t_edge_sparse_rep *
sparseg_adjl_edges (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int e, boolean digraph) /* eisthenumberofedges
*/
{ #if0
t_edge_sparse_rep *edges; int u, v, pos_e, *loops, *foot_print;
graph *g;
loops = (int *) mem_malloc(sizeof(int) * n); for (v = 0; v < n; v++)
{
loops[v] = 0;
}
boolean
sparseg_adjl_add_edge (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep **A, int *size_A, int *pos, int u, int v, boolean CHECK) /* addtheUNDIRECTEDedgetothesparsegraph(V,n,A) -posrecordswheretoaddthenextedgeinA -ifpos+1==size_A,wemustextendA
sparseg_adjl_add_dir_edge(V, n, A, size_A, pos, u, v, FALSE);
sparseg_adjl_add_dir_edge(V, n, A, size_A, pos, v, u, FALSE);
returnTRUE;
}
boolean
sparseg_adjl_add_edge_no_extend (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, int size_A, int *pos, int u, int v, boolean CHECK) /* likesparseg_adjl_add_edgebuthereweareguaranteed thatpos+1<size_A (unlessthatforsomereasonweattempttoadd anedgewhichisalreadythere) thisfeatureisrequiredwhenAispartofaMagmablock: wedonotwanttoreallocateAhere (wouldbedoneatahigherlevel) wecheckiftheedgeisalreadyinthegraphiffCHECKtrue
edge_added =
sparseg_adjl_add_dir_edge_no_extend(V, n, A, size_A, pos, u, v,
CHECK);
if (edge_added)
sparseg_adjl_add_dir_edge_no_extend(V, n, A, size_A, pos, v, u, FALSE);
return edge_added;
}
boolean
sparseg_adjl_add_dir_edge (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep **A, int *size_A, int *pos, int u, int v,
boolean CHECK) /* addtheDIRECTEDedgetothesparsegraph(V,n,A) -posrecordswheretoaddthenextedgeinA -ifpos>=size_A,wemustextendA wecheckiftheedgeisalreadyinthegraphiffCHECKtrue
*/
{
boolean edge_exists;
edge_exists = FALSE; if (CHECK)
{
edge_exists = sparseg_adjl_dir_edge_exists(V, n, *A, u, v);
sparseg_adjl_add_dir_edge_no_extend(V, n, *A, *size_A, pos, u, v, FALSE);
returnTRUE;
}
boolean
sparseg_adjl_add_dir_edge_no_extend (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, int size_A, int *pos, int u, int v, boolean CHECK) /* addanedgewhereAisguaranteedtobebebigenough (unlessthatforsomereasonweattempttoadd anedgewhichisalreadythere)
boolean
sparseg_adjl_remove_edge_no_red (t_ver_sparse_rep *V, t_adjl_sparse_rep *A, int u, int v) /* removetheUNDIRECTEDedgefromsparsegraph(V,A) if(u,v)isnotanedgethennothingchanges(andreturnFALSE)
Awillbeleftwith"holes"
*/
{
sparseg_adjl_remove_dir_edge_no_red(V, A, u, v); return sparseg_adjl_remove_dir_edge_no_red(V, A, v, u);
}
boolean
sparseg_adjl_remove_dir_edge_no_red (t_ver_sparse_rep *V,
t_adjl_sparse_rep *A, int u, int v) /* removetheDIRECTEDedgefromthesparsegraph(V,n,A) if(u,v)isnotanedgethennothingchanges(andreturnFALSE)
int
sparseg_adjl_remove_all_dir_edge_no_red (t_ver_sparse_rep *V,
t_adjl_sparse_rep *A, int u, int v) /* removeallDIRECTEDedges[u,v]fromthenon-simple sparsegraph(V,n,A) if(u,v)isnotanedgethennothingchanges; wereturnthenumberofedgesremoved
Awillbeleftwith"holes"
*/
{ int cur_e, prev_e, e_removed;
if (V[u].first_edge == NIL) /* (u,v)isnotanedge
*/ return0;
void
sparseg_adjl_add_vertices (t_ver_sparse_rep **V, int n, int nmore) /* addnmorevertices Visassumedtohavelengthn
*/
{
*V = (t_ver_sparse_rep *)
mem_realloc(*V, sizeof(t_ver_sparse_rep) * (n + nmore));
sparseg_adjl_add_vertices_no_extend(*V, n, nmore);
}
void
sparseg_adjl_add_vertices_no_extend (t_ver_sparse_rep *V, int n, int nmore) /* addnmorevertices, hereVisassumedtohavelengthn+nmore(ieVhasalready beenmadebigger)
*/
{ int v;
for (v = n; v < n + nmore; v++)
{
V[v].first_edge = NIL;
}
}
void
sparseg_adjl_remove_vertex (t_ver_sparse_rep **V, int n,
t_adjl_sparse_rep *A, int pos_A, int w, int *e) /* Visassumedtohavelengthn:wewillreallocate VsothatVwillhavelengthn-1
void
sparseg_adjl_remove_vertex_no_red (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, int w, int *e) /* hereVhasalreadysizen-1andhasbeeninitialised, allwhatremainstodoistoremovetheedgesincident fromwinA
Awillbeleftwithholes
*/
{ int v, nbr_e_removed;
nbr_e_removed = 0; for (v = 0; v < n - 1; v++)
{
nbr_e_removed += sparseg_adjl_remove_all_dir_edge_no_red(V, A, v, w);
}
*e= *e - nbr_e_removed;
}
void
sparseg_adjl_relabel_vertex (t_adjl_sparse_rep *A, int pos, int u) /* relabelallverticesv>uasv-1 (requiredwhenremovingavertex)
*/
{ int i;
for (i = 0; i < pos; i++)
{
A[i].end_vertex = A[i].end_vertex > u ?
A[i].end_vertex - 1 : A[i].end_vertex;
}
}
boolean
sparseg_adjl_dir_edge_exists (t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, int u, int v) /* doesthedirectededge[u,v]alreadyexistinthegraph
*/
{ int cur_e, prev_e;
cur_e = V[u].first_edge; if (cur_e == NIL) returnFALSE;
boolean
sparseg_adjl_u_adj_v (t_ver_sparse_rep *V, int n, t_adjl_sparse_rep *A, int u, int v) /* isuadj.tov
*/
{ return sparseg_adjl_dir_edge_exists(V, n, A, u, v);
}
boolean
sparseg_adjl_sub (t_ver_sparse_rep *V1, int n1, t_adjl_sparse_rep *A1,
t_ver_sparse_rep *V2, int n2, t_adjl_sparse_rep *A2) /* testifthe(V1,n1,A1)sparsegraphisasubgraphof the(V2,n2,A2)graph
*/
{ int v, *fp, n, bign, i;
n = n1 > n2 ? n2 : n1;
bign = n1 > n2 ? n1 : 0;
fp = (int *) mem_malloc(sizeof(int) * n); for (i = 0; i < n; i++)
fp[i] = NIL;
for (v = n; v < bign; v++) /* thoseverticesmustnotbeendpointsofedges: thischcekisonlynecessaryinthedigraphcase
*/
{ if (V1[v].first_edge != NIL) returnFALSE;
}
returnTRUE;
}
boolean
sparseg_adjl_eq (t_ver_sparse_rep *V1, int n1, t_adjl_sparse_rep *A1,
t_ver_sparse_rep *V2, int n2, t_adjl_sparse_rep *A2) /* comparethetwosparsegraphs(V1,n1,A1)&(V2,n2,A2) wedon'tknowtheirnumberofedges
*/
{ if (n1 != n2) returnFALSE;
boolean
sparseg_dlcl_is_adjacent (t_dlcl **g, int n, int v, int u, t_dlcl **p) /* isuadjacenttov
*/
{
ASSERT(v >= 0 && v < n && u >= 0 && u < n); return sparseg_dlcl_is_present(g[v], u, p);
}
void
sparseg_dlcl_append_to_neigh_list (t_dlcl **g, int n, int v, int u, int in_adjl) /* appendutotheneighbourlistofv
*/
{
t_dlcl *u_rec;
seeembedg_planar_alg_initformore
*/
{ return i >= n && i < 2*n ? TRUE : FALSE;
}
boolean
embedg_VES_is_edge (int n, int i) /* isthisanedge (relativetothe"big"arrayofsize2n+2(3n-5))
*/
{ return i >= 2*n ? TRUE : FALSE;
}
boolean
embedg_VES_is_tree_edge (t_ver_edge *embed_graph, int n, int i) /* isthisstreeedge
*/
{ return embedg_VES_is_edge(n, i)
&& embed_graph[i].type == TE;
}
boolean
embedg_VES_is_back_edge (t_ver_edge *embed_graph, int n, int i) /* isthisabackedge
*/
{ return embedg_VES_is_edge(n, i)
&& embed_graph[i].type == BE;
}
boolean
embedg_VES_is_short_cut_edge (t_ver_edge *embed_graph, int n, int i) /* asthenameindicates...
*/
{ return embedg_VES_is_edge(n, i)
&& embed_graph[i].type == SCE;
}
void
embedg_VES_print_vertex (int n, int v)
{
ASSERT(embedg_VES_is_vertex(n, v));
fprintf(stdout, "%d ", v);
}
void
embedg_VES_print_virtual_vertex (t_ver_edge *embed_graph, int n, int v)
{ int c;
ASSERT(embedg_VES_is_virtual_vertex(n, v));
c = v - n;
fprintf(stdout, "%d^%d ", embed_graph[c].DFS_parent, c);
}
void
embedg_VES_print_any_vertex (t_ver_edge *embed_graph, int n, int v)
{ if (embedg_VES_is_vertex(n, v))
{
embedg_VES_print_vertex(n, v);
} else
{
embedg_VES_print_virtual_vertex(embed_graph, n, v);
}
}
void
embedg_VES_print_any_rec (t_ver_edge *embed_graph, int n, int r)
{ if (embedg_VES_is_edge(n, r))
{
embedg_VES_print_edge(embed_graph, n, r);
} else
{
embedg_VES_print_any_vertex(embed_graph, n, r);
}
}
void
embedg_VES_print_edge (t_ver_edge *embed_graph, int n, int e)
{ int v, prev, cur;
prev = e;
cur = v = embed_graph[e].link[0]; if (embedg_VES_is_vertex(n, v)
|| embedg_VES_is_virtual_vertex(n, v))
{
embedg_VES_print_any_vertex(embed_graph, n, v);
fprintf(stdout, ", ");
embedg_VES_print_any_vertex(embed_graph, n,
embed_graph[e].neighbour);
fprintf(stdout, "):0\n");
} elsewhile (!embedg_VES_is_vertex(n, v)
&& !embedg_VES_is_virtual_vertex(n, v))
{
v = embedg_VES_get_next_in_dlcl(embed_graph, n,
cur, prev);
if (embedg_VES_is_vertex(n, v)
|| embedg_VES_is_virtual_vertex(n, v))
{
embedg_VES_print_any_vertex(embed_graph, n, v);
fprintf(stdout, ", ");
embedg_VES_print_any_vertex(embed_graph, n,
embed_graph[e].neighbour);
fprintf(stdout, "):0\n");
} else
{
prev = cur;
cur = v;
}
}
}
void
embedg_VES_print_flipped_edges (t_ver_edge *embed_graph, int n, int edge_pos) /* printthoseedgesinthestructurewhosesignisCLOCKW, iewhichhavebeenflippedatsomestage
*/
{ int e;
for (e = 2*n; e <= edge_pos; e++)
{ if (!embedg_VES_is_short_cut_edge(embed_graph, n, e)) /* wedon'tcareabouttheshort-cutedges
*/
{ if (embed_graph[e].sign != CCLOCKW)
{
embedg_VES_print_edge(embed_graph, n, e);
}
}
}
}
#if0 int
embedg_VES_get_edge_from_ver (t_ver_edge *embed_graph, int n, int v) /* notusedanywhere;whyisthishere???
*/
{ int in, e;
v = embed_graph[e].link[in];
ASSERT(embedg_VES_is_vertex(n, v)
|| embedg_VES_is_virtual_vertex(n, v));
return v;
} #endif
int
embedg_VES_get_twin_edge (t_ver_edge *embed_graph, int n, int e) /* thetwinedgeisunderstoodasbeingtheinverseedge
*/
{ int twin;
ASSERT(embedg_VES_is_edge(n, e));
twin = e % 2 == 0 ? e + 1 : e - 1;
ASSERT(embedg_VES_is_edge(n, twin));
return twin;
}
int
embedg_VES_get_ver_from_virtual (t_ver_edge *embed_graph, int n, int vv) /* getvfromthevirtualvertexv^c
*/
{ int v;
ASSERT(embedg_VES_is_virtual_vertex(n, vv));
v = embed_graph[vv - n].DFS_parent;
return v;
}
int
embedg_VES_get_ver (t_ver_edge *embed_graph, int n, int v)
{ if (embedg_VES_is_virtual_vertex(n, v)) return embedg_VES_get_ver_from_virtual(embed_graph, n, v);
return v;
}
int
embedg_VES_get_next_in_dlcl (t_ver_edge *embed_graph, int n, int r, int prev) /* risa(virtual)vertexoredgerecordinembed_graph: getthenextinthelist(formedbythe.link[]fields) inthedoublylinkedcircularlist
aprioriweshouldgetthesameresulteitherway
*/
{ if (consistent)
{ int next;
embedg_VES_print_any_rec(embed_graph, n, r);
next = embed_graph[r].link[0]; while (next != r)
{
embedg_VES_print_any_rec(embed_graph, n, next);
next = embed_graph[next].link[0];
}
} else
{ int prev, cur, next;
embedg_VES_print_any_rec(embed_graph, n, r);
prev = r;
cur = embed_graph[r].link[0];
while (cur != r)
{
embedg_VES_print_any_rec(embed_graph, n, cur);
next = embedg_VES_get_next_in_dlcl(embed_graph, n,
cur, prev);
prev = cur;
cur = next;
}
}
}
boolean
embedg_VES_is_adj_list_consistent (t_ver_edge *embed_graph, int n, int r) /* checksthatr'sadjacencylistisconsistent: ie,thateithertraversingitusinglink[0]always ortraversingitusingembedg_VES_get_next_in_dlcl givestheSAMEresult
*/
{ int *list_link, *list_n_dldl, il, id, i;
boolean
embedg_VES_are_adj_lists_consistent (t_ver_edge *embed_graph, int n) /* checksthattheadjacencylistofeachvertexisconsistent inthemannerofembedg_VES_is_adj_list_consistent
*/
{ int i;
/* itisenoughtovisittheverticesandvirtualverticesonly (Idon'tthinkitisenoughtodotheverticesonly--??)
*/ for (i = 0; i < 2*n; i++) if (!embedg_VES_is_adj_list_consistent(embed_graph, n, i)) returnFALSE;
returnTRUE;
}
void
embedg_VES_remove_edge (t_ver_edge *embed_graph, int n, int e) /* removeedgeefromtheembedding
*/
{ int r1, r2, r1out, r2in, twin;
ASSERT(embedg_VES_is_edge(n, e));
IF_DEB_SCE(
fprintf(stdout, "removing an SCE, enter\n");
embedg_VES_print_edge(embed_graph, n, e);
)
ASSERT(embedg_VES_is_adj_list_consistent(embed_graph, n, r1));
}
void
embedg_VES_set_orientation (t_ver_edge *embed_graph, int n, int *ver_orient) /* usingthevertices'orientationasgiveninver_orient wesettheorientationforeachedgeintheadjacencylist foreachvertex
if (!embedg_dlcl_is_empty(p))
{
embedg_dlcl_rec_print(p);
p = embedg_dlcl_list_next(p); while (p != l)
{
embedg_dlcl_rec_print(p);
p = embedg_dlcl_list_next(p);
}
}
fprintf(stdout,"\n");
}
boolean
sparseg_adjl_is_planar (
t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, /* input sparse graph */ int *nbr_c, /* size of the graph, #components
*/
t_dlcl ***dfs_tree, /* a sparse graph rep. for the dfs tree --verticesareasDFIs --andchildrenareorderedwrt lowpointvalue
*/
t_dlcl ***back_edges, /* for each vertex v, a dlcl ofthebackedges[v,x]incidenttov wherexisaDESCENDANTofv (verticesaregivenasDFIs)
*/
t_dlcl ***mult_edges, /* for each vertex v, a dlcl ofthebackedges[v,x]incidenttov wherexisaDESCENDANTofv (verticesaregivenasDFIs)
*/
t_ver_edge **embed_graph, /* output graph embedding -- more on that later
*/ int *edge_pos, /* pos. in embed_graph for addition
of the next edge */ int *vr, int *wr /* if graph is non planar, return theunembeddededge (wherewrdescendantofvr)
*/
) /* asthenameindicates:isthegraphplanar?
*/
{ int v;
IF_CPU( float sttime; float time_to_now;
)
*embed_graph =
embedg_planar_alg_init(V, n, A, nbr_c,
edge_pos, dfs_tree, back_edges, mult_edges);
IF_CPU(
sttime = time_current_user();
)
for (v = n - 1; v >= 0; v--) /* visitallverticesindescendingDFIorder
*/
{
t_dlcl *be_l, *te_l, *p;
w = p->info;
IF_DEB(
fprintf(stdout, "top level, before walkup for w %d\n", w);
)
embedg_walkup(*embed_graph, n, v, p);
p = embedg_dlcl_list_next(p); while (p != be_l)
{
w = p->info;
IF_DEB(
fprintf(stdout, "top level, before walkup for w %d\n", w);
)
embedg_walkup(*embed_graph, n, v, p);
p = embedg_dlcl_list_next(p);
}
}
/* performawalkdownforeachtreeedge[v,c],cadescendantofv (ieattempttoembedallbackedgesonthepertinentbicomps)
*/
te_l = (*dfs_tree)[v];
p = te_l;
if (!embedg_dlcl_is_empty(p))
{ int c, vv;
t_merge_queue q;
c = p->info;
vv = c + n;
IF_DEB(
fprintf(stdout, "top level, before walkdown for c %d\n", c);
)
q = embedg_walkdown(*embed_graph, n, edge_pos, vv);
IF_DEB(
fprintf(stdout, "top level, after walkdown for c %d, state of edges'sign\n", c);
embedg_VES_print_flipped_edges(*embed_graph,
n, *edge_pos);
)
/* temponly
*/
embedg_merge_queue_delete(q);
p = embedg_dlcl_list_next(p); while (p != te_l)
{
c = p->info;
vv = c + n;
IF_DEB(
fprintf(stdout, "top level, before walkdown for c %d\n", c);
)
q = embedg_walkdown(*embed_graph, n, edge_pos, vv);
IF_DEB(
fprintf(stdout, "top level, after walkdown for c %d, state of edges'sign\n", c);
embedg_VES_print_flipped_edges(*embed_graph,
n, *edge_pos);
)
/* temponly
*/
embedg_merge_queue_delete(q);
p = embedg_dlcl_list_next(p);
}
}
/* checkthateachbackedge[w,v],wadescendantofv, hasbeenembedded
*/
be_l = (*back_edges)[v];
p = be_l;
if (!embedg_dlcl_is_empty(p))
{ int w;
w = p->info;
IF_DEB(
fprintf(stdout, "top level, before checking embedding for w %d\n",
w);
) if ((*embed_graph)[w].adjacent_to == v) /* thisedgehasn'tbeenembedded: thegraphisnon-planar
*/
{ /* beforereturningwereallywanttoensurethat thevertices'adjacencylistsareconsistent
*/
ASSERT(embedg_VES_are_adj_lists_consistent(
*embed_graph, n));
IF_CPU(
fprintf(stdout, "CPU for tester only %f\n",
(time_current_user() - sttime));
)
*vr = v;
*wr = w; returnFALSE;
}
p = embedg_dlcl_list_next(p); while (p != be_l)
{
w = p->info;
IF_DEB(
fprintf(stdout, "top level, before checking embedding for w %d\n",
w);
) if ((*embed_graph)[w].adjacent_to == v)
{ /* beforereturningwereallywanttoensurethat thevertices'adjacencylistsareconsistent
*/
ASSERT(embedg_VES_are_adj_lists_consistent(
*embed_graph, n));
IF_CPU(
fprintf(stdout, "CPU for tester only %f\n",
(time_current_user() - sttime));
)
*vr = v;
*wr = w; returnFALSE;
}
p = embedg_dlcl_list_next(p);
}
}
}
IF_DEB_EDGES(
fprintf(stdout, "top level, total number of edges in embedding %d\n",
*edge_pos - 2 * n + 1);
)
void
embedg_walkup (t_ver_edge *embed_graph, int n, int v, t_dlcl *p) /* walkupfromw=p->infotov:[w,v]isabackedgewherewisaDFS descendantofv
*/
{ int w, x, xin, y, yin;
w = p->info;
IF_DEB(
fprintf(stdout, "walkup from %d to %d, enter\n", w, v);
)
t_merge_queue
embedg_walkdown (t_ver_edge *embed_graph, int n, int *edge_pos, int vv) /* walkdownfromthevirtualvertex: embedanybackedgesincidenttovvifany andmergetheencounteredbicompswhilewalkingdown (veryinformativeisn'tit?:))
...andreturnthemergequeue:willbeusefulwhen isolatingtheKuratowskisubgraphs
*/
{
t_merge_queue q; int v, c, vvout;
ASSERT(embedg_VES_is_virtual_vertex(n, vv));
/* findvandcsuchthatv^c=vv
*/
c = vv - n;
v = embed_graph[c].DFS_parent;
IF_DEB(
fprintf(stdout, "walkdown from %d^%d, enter\n", v, c);
)
IF_DEB_EMBED(
fprintf(stdout, "walkdown, embedding at start\n");
embedg_VES_print_bigcomps(embed_graph, n);
)
if (embedg_VES_is_ver_int_active(embed_graph, n,
v, x)) /* xisinternallyactive
*/
{
IF_DEB(
fprintf(stdout, "walkdown, x is int. active\n");
)
s = x;
sin = xin;
} elseif (embedg_VES_is_ver_int_active(
embed_graph, n,
v, y)) /* yisinternallyactive
*/
{
IF_DEB(
fprintf(stdout, "walkdown, y is int. active\n");
)
s = y;
sin = yin;
} elseif (embedg_VES_is_ver_pertinent(
embed_graph, n,
v, x)) /* xispertinent
*/
{
IF_DEB(
fprintf(stdout, "walkdown, x is pertinent\n");
)
s = x;
sin = xin;
} else /* toughluck:ymaybeexternallyactive
*/
{
IF_DEB(
fprintf(stdout, "walkdown, tough luck\n");
)
s = y;
sin = yin;
}
IF_DEB(
fprintf(stdout, "walkdown, succ. on pertinent bicomp is %d:%d\n", s, sin);
)
/* setvwouttorespectconsistencyoftraversal
*/
vwout = s == x ? 0 : 1;
void
embedg_merge_queue_print (t_merge_queue q)
{ int i;
for (i = q.start; i < q.end; i++)
{
fprintf(stdout, "%d:%d ", q.b[i], q.b[i+1]);
++i;
}
fprintf(stdout, "\n");
}
void
embedg_merge_queue_append (t_merge_queue *q, t_ver_edge *embed_graph, int n, int v, int vin, int vv, int vvout) /* appendthe4-tuple(v,vin,vv,vvout) wherevisavertexandvvisitsvirtualcounterpart
IF_DEB(
fprintf(stdout, "merge_queue_append_virtual_vertex, after, end is %d\n",
(*q).end);
)
}
void
embedg_merge_queue_get (t_merge_queue *q, int *v, int *vin, int *vv, int *vvout) /* pullingouta4-tuplefromthebeginningoftheFIFOqueue
*/
{
ASSERT(!embedg_merge_queue_empty((*q)));
void
embedg_merge_queue_prune (t_merge_queue *q, int *v, int *vin, int *vv, int *vvout) /* pullingouta4-tuplefromtheendoftheFIFOqueue
*/
{
ASSERT(!embedg_merge_queue_empty((*q)));
boolean
embedg_VES_is_ver_pertinent (t_ver_edge *embed_graph, int n, int v, int w) /* iswpertinent(wrtv) -thefieldadjacent_to=v:meansthereisabackedge[w,v] -orwhasanonemptypertinent_bicomp_list
*/
{
boolean ans;
ans = embed_graph[w].adjacent_to == v ? TRUE : FALSE;
boolean
embedg_VES_is_ver_ext_active (t_ver_edge *embed_graph, int n, int v, int w) /* iswexternallyactive(wrtv) thisisthecasewheneitherw'sleast_ancestor<v orthefirstmemberofw'sseparated_DFS_child_listhaslowpoint<v (theverticesinseparated_DFS_child_listareorderedbylowpoint)
ans = embed_graph[w].least_ancestor < v ? TRUE : FALSE;
if (ans) returnTRUE; else
{ if (embedg_dlcl_is_empty(embed_graph[w].separated_DFS_child_list))
{ returnFALSE;
} else
{ int c;
c = (embed_graph[w].separated_DFS_child_list)->info; return embed_graph[c].lowpoint < v ? TRUE : FALSE;
}
}
}
boolean
embedg_VES_is_ver_int_active (t_ver_edge *embed_graph, int n, int v, int w) /* iswinternallyactive(wrtv): thishappenswhenwispertinentbutNOTexternallyactive
*/
{ return embedg_VES_is_ver_pertinent(embed_graph, n, v, w)
&& !embedg_VES_is_ver_ext_active(embed_graph, n, v, w);
}
boolean
embedg_VES_is_ver_inactive (t_ver_edge *embed_graph, int n, int v, int w) /* iswinactive(wrtv),thatiswnorpertinentnorexternallyactiv
*/
{ return !embedg_VES_is_ver_pertinent(embed_graph, n, v, w)
&& !embedg_VES_is_ver_ext_active(embed_graph, n, v, w);
}
void
embedg_VES_merge_simple_bicomps (t_ver_edge *embed_graph, int n, int vv, int vvout, int v, int vin) /* mergethebicomprootedatvv(vvavirtualvertex)with itscounterpartvsothattheresultingadjacencylistforv isconsistentandistheunionoftheadjacencylistsforvvandv
wetreatthecasethatthebicompmaybeflipped(vvout==vin) here
*/
{ int c, edge, twin, root_edge, cur, prev; int vout, vvin, e1, e2, e3, e4, e1out, e3out, e4in;
root_edge = NIL;
edge = embed_graph[vv].link[vvout];
ASSERT(embedg_VES_is_edge(n, edge)); if (embed_graph[edge].neighbour == c
&& embedg_VES_is_tree_edge(embed_graph, n, edge))
{
root_edge = edge;
}
if (vin == vvout) /* invertthelinks
*/
{ int in, out;
in = embed_graph[edge].link[0];
out = embed_graph[edge].link[1];
embed_graph[edge].link[0] = out;
embed_graph[edge].link[1] = in;
} /* getthetwinandsettheneighbourtheretov(wasvvoriginally)
*/
twin = embedg_VES_get_twin_edge(embed_graph, n, edge);
ASSERT(embed_graph[twin].neighbour == vv);
embed_graph[twin].neighbour = v;
prev = vv;
cur = edge; while (edge != vv)
{
edge =
embedg_VES_get_next_in_dlcl(embed_graph, n,
cur, prev);
if (embedg_VES_is_edge(n, edge)) /* getthetwinagain(andinvertthelinksifneedbe)
*/
{ if (embed_graph[edge].neighbour == c
&& embedg_VES_is_tree_edge(embed_graph, n, edge))
{
root_edge = edge;
}
if (vin == vvout)
{ int in, out;
in = embed_graph[edge].link[0];
out = embed_graph[edge].link[1];
embed_graph[edge].link[0] = out;
embed_graph[edge].link[1] = in;
}
IF_DEB(
fprintf(stdout, "merge_simple_bicomp, before union of lists, e1\n");
embedg_VES_print_edge(embed_graph, n, e1);
fprintf(stdout, "merge_simple_bicomp, e3\n");
embedg_VES_print_edge(embed_graph, n, e3);
fprintf(stdout, "merge_simple_bicomp, e4\n");
embedg_VES_print_edge(embed_graph, n, e4);
)
IF_DEB(
fprintf(stdout, "merge_simple_bicomp, after union of lists, e1\n");
embedg_VES_print_edge(embed_graph, n, e1);
fprintf(stdout, "merge_simple_bicomp, e3\n");
embedg_VES_print_edge(embed_graph, n, e3);
fprintf(stdout, "merge_simple_bicomp, e4\n");
embedg_VES_print_edge(embed_graph, n, e4);
)
IF_DEB_ADJL(
fprintf(stdout, "merge_simple_bicomp, adj. list for %d (after)\n", vv);
embedg_VES_print_adj_list(embed_graph, n, vv, TRUE);
fprintf(stdout, "\n");
embedg_VES_print_adj_list(embed_graph, n, vv, FALSE);
fprintf(stdout, "\n");
fprintf(stdout, "merge_simple_bicomp, adj. list for %d (after)\n", v);
embedg_VES_print_adj_list(embed_graph, n, v, TRUE);
fprintf(stdout, "\n");
embedg_VES_print_adj_list(embed_graph, n, v, FALSE);
)
ASSERT(embedg_VES_is_adj_list_consistent(embed_graph, n, v));
/* finally,giveanorientationtothe(formerly)rootedge[vv,c] tokeeptraversalconsistent(whenrecoveringembedding)
*/ if (vin == vvout) /* flip:setthesignoftherootedgetoclockwise
IF_VERB(
fprintf(stdout, "merge_simple_bicomp, flip for %d, sign is now %d for %d of type %d\n",
c, embed_graph[root_edge].sign, root_edge, embed_graph[root_edge].type);
embedg_VES_print_edge(embed_graph, n, root_edge);
)
}
}
void
embedg_VES_merge_pertinent_bicomps (t_ver_edge *embed_graph, int n, int vv, int vvout, int v, int vin) /* thebicompstobemergedarepertinent:ontop(andbefore) performingasimplemerge,thereareseveralthingstodo relatedtothemergingtopertinentbicomps
*/
{ /* anoteofcaution: itis(very)likelythatafterabicompmergetheresulting bicompisnotbiconnected(andhencetraversaloftheexternalface ofthebicompviaembedg_VES_get_succ_on_ext_faceisnon-sensical)
void
embedg_VES_embed_edge (t_ver_edge *embed_graph, int n, int *edge_pos, int edge_type, int vv, int vvout, int w, int win) /* embedtheedge(vv,w)(vvavirtualvertex,wavertex)between vvandtheedgevvout andtheedgewinandw
sothataftertheembedding,oneexitsvvvia(vv,w)and enterswviathetwin(w,vv)
*/
{ int temp, tempin, tempout;
void
embedg_VES_add_edge (t_ver_edge *embed_graph, int n, int *edge_pos, int v, int w, boolean MARK, int mark) /* addtheedge(v,w):thisisDIFFERENTfrom embedg_VES_embed_edgeinthesense thatthepresentfunctionwillonlybeused whenbuildingtheKuratowskihomeomorphs:
e = embed_graph[v].link[out]; while (embedg_VES_is_short_cut_edge(embed_graph, n, e))
{
e = embed_graph[e].link[out];
}
ASSERT(embedg_VES_is_edge(n, e)
&& !embedg_VES_is_short_cut_edge(embed_graph, n, e)); /* strictlyspeakingthereshouldbenoSCEsleftatthisstage... ifthereareSCEsinv'slist,itmustbethecasethat thelistalsocontainstreeorbackedges...
*/
(*vertices)[v_l].first_edge = index_embed;
IF_DEB_EMBED(
fprintf(stdout, "recov. embed. DFI %d vertex %d at %d (edges) and %d (embedding)\n",
v, v_l, index_e, (*vertices)[v_l].first_edge);
)
cur_e = e; while (TRUE)
{
next_e = embed_graph[cur_e].link[out]; while (embedg_VES_is_short_cut_edge(embed_graph, n, next_e))
{
next_e = embed_graph[next_e].link[out];
}
ASSERT(!embedg_VES_is_short_cut_edge(embed_graph, n, next_e));
if (next_e == v) /* endofadjacencylist
*/
{ break;
}
ASSERT(embedg_VES_is_edge(n, next_e));
(*embedding)[index_embed].in_adjl = embed_graph[cur_e].in_adjl;
(*embedding)[index_embed].next = index_embed + 1; /* next in adj.
list */
(*embedding)[index_embed].mark = NIL; /* mark */
staticvoid
embedg_recover_embedding_embed_mult (t_dlcl **mult_edges,
t_embed_sparse_rep *embedding, int nbr_e, int v, int w, int mult, int *index_embed, boolean *set_next, int *first_edge) /* seeifthedirectededge[v,w]ismultiple:ifsoembedit inembedding
void
embedg_recov_embed_walk_proper_face (int n, int e, t_adjl_sparse_rep *A,
t_embed_sparse_rep *embedding, boolean MARK, int mark) /* doaproperfacewalkintherecoveredembeddingstarting atindexeintheembedding
*/
{ int cur, next;
boolean
embedg_check_recov_embedding (int n, int nbr_e, int nbr_comp,
t_ver_sparse_rep *vertices, t_adjl_sparse_rep *A,
t_embed_sparse_rep *embedding) /* checkiftherecoveredembeddingisavalidembedding SHOULDONLYbeuseaftercreation,thatis,afterhaving recoveredtheembeddingfromtheVESstructure (becauseofthemarkMIN_EMBED_MARKweuse)
*/
{ int v, e, f;
f = 0; /* doalltheedgesinembedding: careful:wehave2*nbr_etovisit(theedgeanditsinverse!)
*/ for (e = 0; e < 2 * nbr_e; e++)
{ /* wecheckifthecurrentedgeismarked:ifnot,we traverseaproperfaceborderedbythisedge
*/ if (embedding[e].mark != MIN_EMBED_MARK) /* we--hopefully--performthischeckonlyaftercreation wheremark==NIL
*/
{
embedg_recov_embed_walk_proper_face(n, e, A, embedding, TRUE, MIN_EMBED_MARK);
f++;
}
}
/* mustalsocountafaceforeachisolatedvertex
*/ for (v = 0; v < n; v++)
{ if (vertices[v].first_edge == NIL)
f++;
}
return f == 2 * nbr_comp + nbr_e - n ? TRUE : FALSE;
}
t_dlcl **
embedg_recover_obstruction (t_ver_edge *embed_graph, int n, minor m, int *nbr_e) /* recovertheobstructionasat_dlcl*structure: andreturnthenumberofedges:letssayweagreeonreturning thenumberofundirectededges --Idon'tknowyetwhichwaytodo,directedorundirected???
static boolean
embedg_is_red_obs_K5 (t_dlcl **reduced, int n) /* checkifthe(reduced)obstructionisindeedK5
*/
{ int v, order;
/* checkthatorder==5andthattheobstructionisquadric
*/
order = 0; for (v = 0; v < n; v++)
{ if (!embedg_dlcl_is_empty(reduced[v]))
{ if (order == 5)
{ returnFALSE;
}
order++;
if (embedg_dlcl_length(reduced[v]) != 4)
{ returnFALSE;
}
}
}
returnTRUE;
}
boolean
embedg_check_recov_obs (t_dlcl **obs, int n, minor m) /* checkiftherecoveredobstructionisoneofK33orK5
*/
{
t_dlcl **reduced;
boolean ans;
reduced = embedg_get_reduced_obs(obs, n); if (m != MINOR_E5)
{
ans = embedg_is_red_obs_K33(reduced, n);
} else
{
ans = embedg_is_red_obs_K5(reduced, n);
}
void
embedg_obstruction (
t_ver_sparse_rep *V,
t_adjl_sparse_rep *A, /* the input graph as a sparse graph */
t_dlcl **dfs_tree, /* a sparse graph rep. for the dfs tree --verticesareasDFIs --andchildrenareorderedwrt lowpointvalue
*/
t_dlcl **back_edges, /* for each vertex v, a dlcl ofthebackedges[v,x]incidenttov wherexisaDESCENDANTofv (verticesaregivenasDFIs)
*/
t_ver_edge *embed_graph, /* output of tester */ int n, /* size of the graph */ int *edge_pos, /* pos. in embed_graph for addition
of the next edge */ int v, int w_in, /* the unembedded directed back edge [w_in,v]
*/
t_ver_sparse_rep **OV, /* the obstruction as an adjacency list */
t_adjl_sparse_rep **OA, int *nbr_e_obs /* obstruction's #edges */
)
/* thegraphisnonplanar:wemustmark&recovertheK33orK5 homeomorph
*/
{ int *ver_orient;
minor m;
t_dlcl **obs;
minor
embedg_mark_obstruction (
t_dlcl **dfs_tree, /* a sparse graph rep. for the dfs tree --verticesareasDFIs --andchildrenareorderedwrt lowpointvalue
*/
t_dlcl **back_edges, /* for each vertex v, a dlcl ofthebackedges[v,x]incidenttov wherexisaDESCENDANTofv (verticesaregivenasDFIs)
*/
t_ver_edge *embed_graph, /* output of tester */ int n, /* size of the graph */ int *edge_pos, /* pos. in embed_graph for addition
of the next edge */ int v, int w_in /* the unembedded directed back edge [w_in,v]
*/
) /* thegraphisnonplanar:wemustmark&recovertheK33orK5 homeomorph
*/
{ int c, vr, x, y, w; int *path_v, *path_e, nbr_v, entry_in_path_e;
boolean px_attached_high, py_attached_high, is_minor_D;
minor m;
IF_CPU( float sttime; float time_to_now;
sttime = time_current_user();
)
/* findcsuchthatv^cistherootofthebiconnected componentonwhichthewalkdownfailed
*/
c = embedg_iso_get_c_of_v(embed_graph, n, v, w_in);
/* now:decidewhichminorwearedealingwithandmarkthe appropriateone(vertices/edgesmarkedasMARK_MINOR(n) inembed_graph)
*/ if (embedg_iso_is_minor_A(embed_graph, n, edge_pos, v, c, &vr))
{
embedg_mark_minor_A(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, c, vr);
u = embed_graph[w].DFS_parent; while (embed_graph[u].DFS_parent != v)
{
u = embed_graph[u].DFS_parent;
} /* thisisguaranteedtosucceedgiventhestructureoftheDFStree andthefactthatthereexistsabackedge[w,v]
*/
return u;
}
boolean
embedg_iso_is_minor_A (t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int *vr) /* determinesiftheobstructionisaminorA
*/
{ /* todothisweagaincallthewalkdownroutinewithv^casinput, thewalkdownroutinewillfail(sincetherewillbean un-embeddedbackedgeincidenttovandtoavertex inthesubtreerootedbyv^c)
theobstructionisaminorAifthemergequeuereturnedbythe walkdownisnon-empty,ifthisisthecasewereturn thebicomplastappendedtothequeue
*/ int vv;
t_merge_queue q;
vv = c + n;
q = embedg_walkdown(embed_graph, n, edge_pos, vv); /* weMUSTremovetheSCEshere:thisistheonlyplacewhereit willbedonewhenlookingforandrecoveringanobstruction
thisissafesincethisveryfunctionappliestoALLcases!
*/
embedg_remove_SCE(embed_graph, n, *edge_pos);
if (!embedg_merge_queue_empty(q)) /* thebicompofinterestisthelastinthequeue
*/
{ int r, rin, vrout;
void
embedg_iso_get_x_y_w (t_ver_edge *embed_graph, int n, int v, int r, int c, int mark, int mark_l, int mark_r, int *x, int *y, int *w) /* theobstructionisoneofminorB,C,D,E. gettheexternallyactiveverticesx&yalongthe externalfacepathsstartingatr^c
externalactivityandpertinencearewrtv alltheverticesontheexternalfacer^c...x...w andr^c...y...wwillbemarked(thevisitedfield)
*/
{ int vr, vrin, x_y[4]; int s, sin, cur, curin;
Notethewaytheexternalfaceismarked(neededwhenrecovering thehighestx-ypath): mark_lforthepathv^c...x...w mark_rforthepathv^c...y markforthelowerexternalfacey...w
*/
cur = x_y[1];
curin = x_y[3];
s = n; while (s != *w)
{
embedg_VES_get_succ_pertinent_on_ext_face(embed_graph, n, v,
cur, curin, TRUE, mark, &s, &sin);
cur = s;
curin = sin;
}
IF_DEB(
fprintf(stdout, "get x, y & w: the external face\n");
fprintf(stdout, "%d\t", vr);
cur = vr;
curin = 0; while (s != vr)
{
embedg_VES_get_succ_on_ext_face(embed_graph, n,
cur, curin, FALSE, 0, &s, &sin);
cur = s;
curin = sin;
fprintf(stdout, "%d\t", s);
}
fprintf(stdout, "\n");
)
}
boolean
embedg_iso_is_minor_B (t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int *x, int *y, int *w) /* determinesiftheobstructionisaminorBandreturnx,y (ext.active)andw(pertinent)
*/
{ /* getx&ytheext.activeverticesonthe(externalface) pathoutofv^c, andwthepertinentvertexonthelowerexternalfacex-y
PLUSmarkthewholeexternalfacewithMARK_EXT_FACE(n)
*/
embedg_iso_get_x_y_w(embed_graph, n, v, v, c,
MARK_EXT_FACE(n),
MARK_EXT_FACE_L(n), MARK_EXT_FACE_R(n),
x, y, w);
if (embedg_dlcl_is_empty(embed_graph[*w].pertinent_bicomp_list)) /* whasnopertinentchildbicomp:notaminorB
*/ returnFALSE; else
{
t_dlcl *pert_l; int l;
pert_l = embed_graph[*w].pertinent_bicomp_list;
l = embedg_dlcl_list_last(pert_l)->info; /* ifwhasanext.activepertinentchildbicompthenminorB
PLUS:lisactuallyaVIRTUALvertex:tocheckitslowpoint ImusttakeitsDFSchildl-n!!!!!!!!
*/
ASSERT(embedg_VES_is_virtual_vertex(n, l));
l = l - n; return embed_graph[l].lowpoint < v ? TRUE : FALSE;
}
}
void
embedg_iso_get_highest_x_y_path (
t_ver_edge *embed_graph, int n, int mark, int mark_l, int mark_r, int v, int c, int x, int y, int w, int **path_v, /* stack of vertices in x-y path */ int **path_e, /* stack of egdes in x-y path */ int *nbr_v, /* number of vertices in path_v */ int *entry_in_path_e, /* the in direction for the FIRST edge in path_e:neededlateron*sigh*
*/
boolean *px_attached_high,
boolean *py_attached_high,
boolean *is_minor_D
) /* theobstructionisoneofminorC,D,E.
int vv, s, sin, p_x, p_y, cur_v, cur_vin; int e, ein, s_e, s_ein;
boolean avoid_vv;
/* muststartthewalkatedgeembed_graph[v^c].link[1^0], (vvin=0isindirectionofx,seeembedg_iso_get_x_y_w)
*/
vv = c + n;
e = embed_graph[vv].link[1];
ein = 0; /* because of adjacency list consistency */
t_ver_edge *
embedg_planar_alg_init (
t_ver_sparse_rep *V, int n,
t_adjl_sparse_rep *A, /* input sparse graph */ int *nbr_c, /* size of the graph, #components*/ int *edge_pos, /* pos in the struct where the last edge hasbeeninserted
*/
t_dlcl ***dfs_tree, /* a sparse graph rep. for the dfs tree --verticesareasDFIs
*/
t_dlcl ***back_edges, /* for each vertex v, a dlcl ofthebackedges[v,x]incidenttov wherexisaDESCENDANTofv --verticesareasDFIs
*/
t_dlcl ***mult_edges /* for each vertex v, a dlcl ofthebackedges[v,x]incidenttov wherexisaDESCENDANTofv --verticesareasDFIs
*/
) /* initialisingembed_graph,thefundamentaldatastructure underpinningthetesterandobstructionisolator
fromthereon,avertexisexclusivelyreferredtobyitsDFI!! --soforgetaboutlabels
*/
{ int *dfs_nbr; /* dfs numbering for each vertex */ int *dfs_order; /* vertices in dfs order */ int *lowpoint; /* lowpoint value for each DFI */ int *dfs_parent; /* for each DFI, its DFS ancestor asaDFI(DFSindex)
*/ int *least_a; /* for each DFI, its least ancestor's DFI (viaabackedgeexclusively)
*/
t_ver_edge *embed_graph; int i;
IF_CPU( float sttime; float time_to_now;
sttime = time_current_user();
)
ASSERT(n >= 1);
/* DFSandlowpointcalculations+ordering
*/
sparseg_adjl_dfs_preprocessing(V, n, A, nbr_c,
&dfs_nbr, &dfs_order, &lowpoint,
dfs_tree, back_edges,
&dfs_parent, &least_a, mult_edges);
IF_CPU(
fprintf(stdout, "CPU for DFS only %f\n",
(time_current_user() - sttime));
sttime = time_current_user();
)
IF_DEB_DFS(
fprintf(stdout, "DFS indices\n"); for (i = 0; i < n; i++)
fprintf(stdout, "%d ", dfs_nbr[i]);
fprintf(stdout, "\n");
fprintf(stdout, "DFS order\n"); for (i = 0; i < n; i++)
fprintf(stdout, "%d ", dfs_order[i]);
fprintf(stdout, "\n");
fprintf(stdout, "lowpoint values\n"); for (i = 0; i < n; i++)
fprintf(stdout, "%d ", lowpoint[i]);
fprintf(stdout, "\n");
);
IF_VERB(
fprintf(stdout, "DFS parent\n"); for (i = 0; i < n; i++)
fprintf(stdout, "%d ", dfs_parent[i]);
fprintf(stdout, "\n");
);
IF_VERB(
fprintf(stdout, "least ancestors\n"); for (i = 0; i < n; i++)
fprintf(stdout, "%d ", least_a[i]);
fprintf(stdout, "\n");
);
IF_VERB( for (i = 0; i < n; i++)
{
fprintf(stdout, "the list of children ordered by lowpoint for %d\n",
i);
embedg_dlcl_print((*dfs_tree)[i]);
}
);
IF_DEB_DFS(
fprintf(stdout, "the tree edges\n");
sparseg_dlcl_print(*dfs_tree, n);
fprintf(stdout, "the back edges\n");
sparseg_dlcl_print(*back_edges, n);
CAREFUL:whentalkingaboutvertexvsay, wemeanthevertexwithDFIv,andNOTthevertexwithlabelv **************************************************************
*/
*edge_pos = 2*n - 1; /* edge_poswilltelluswheretoinsertthenextedgeinembed_graph[]
*/ for (i = 0; i < n; i++)
{
t_dlcl *te_l, *p;
te_l = (*dfs_tree)[i];
p = te_l;
if (!embedg_dlcl_is_empty(p))
{ /* thetestbelowisabitstupid...well...
*/
ASSERT(embed_graph[p->info].DFS_parent == i);
embedg_init_insert_TE(embed_graph, n, edge_pos, p);
p = embedg_dlcl_list_next(p); while (p != te_l)
{
ASSERT(embed_graph[p->info].DFS_parent == i);
embedg_init_insert_TE(embed_graph, n, edge_pos, p);
IF_CPU(
fprintf(stdout, "CPU for remainder of initialisation %f\n",
(time_current_user() - sttime));
)
return embed_graph;
}
staticvoid
embedg_init_insert_TE (t_ver_edge *embed_graph, int n, int *edge_pos, t_dlcl *p) /* initandinsertatreeedgeinembedgraph: thetreeedgewillformasingletonbicomponent(v^c,c) wherecisp->infoandvisc.DFS_parent
*/
{ int c, v;
c = p->info;
v = embed_graph[c].DFS_parent;
ASSERT(v >= 0 && v < n);
void
sparseg_adjl_dfs_preprocessing (
t_ver_sparse_rep *V, int n, /* size of the graph */
t_adjl_sparse_rep *A, /* input sparse graph */ int *c, /* nbr of components */ int **dfs_nbr, /* dfs numbering for each vertex */ int **dfs_order, /* vertices in dfs order */ int **lowpoint, /* lowpoint value for each DFI */
t_dlcl ***dfs_tree, /* a sparse graph rep. for the dfs tree: foreachDFI,alistofitschildren's DFIorderedwrttheirlowpointvalues
*/
t_dlcl ***back_edges, /* for each DFI v, a dlcl ofthebackedges[v,x]incidenttov
where x is a DESCENDANT of v */ int **dfs_parent, /* for each DFI its DFS ancestor */ int **least_a, /* for each DFI, its least ancestor's DFI
via a back edge exclusively */
t_dlcl ***mult_edges /* for each DFI v, a dlcl ofthemultipledirected edgesNOTincluded ineitherdfs_treeorback_edges
*/
)
cur_e = A[cur_e].next; /* next in cur's adjacency list */
} elseif (sparseg_dlcl_is_adjacent(*dfs_tree, n,
(*dfs_nbr)[next],
(*dfs_nbr)[cur],
&existing_e)) /* [next,cur]isatreeedge: thatis,[cur,next]is[next,cur]'stwin/inverse:
void
embedg_embedding (t_ver_sparse_rep *V, t_adjl_sparse_rep *A,
t_ver_edge *embed_graph, int n, int e, int nbr_c, int edge_pos, t_dlcl **mult_edges, t_ver_sparse_rep **vertices,
t_embed_sparse_rep **embedding) /* recoveringtheembeddingforthe(planar)graph
/* 5.recovertheembeddinginpreparationfortheMagmatype, andcheckitaswell
*/
embedg_recover_embedding(V, A, embed_graph, n, e,
mult_edges, vertices, embedding); if (!embedg_check_recov_embedding(n, e, nbr_comp,
*vertices, A, *embedding))
{
mem_free(*vertices);
mem_free(*embedding);
IF_DEB_EMBED(
fprintf(stdout, "embedding, original graph and embedding\n");
sparseg_adjl_print(V, n, A, FALSE);
fprintf(stdout, "\n");
sparseg_adjl_embed_print(*vertices, n, A, *embedding, FALSE);
)
void
embedg_remove_SCE (t_ver_edge *embed_graph, int n, int edge_pos) /* removealltheshort-cutedgesfromtheembedding
*/
{ int i, c;
c = 0; for (i = 2*n; i <= edge_pos; i += 2) /* andedgeanditstwinoccupyconsecutivepositionsinembed_graph: needonlytoexamineoneoutoftwo (removinganedgealsoentailsremovingitstwinofcourse
*/
{ if (embedg_VES_is_short_cut_edge(embed_graph, n, i))
{
IF_DEB_SCE(
fprintf(stdout, "remove SCE\n");
embedg_VES_print_edge(embed_graph, n, i);
)
embedg_VES_remove_edge(embed_graph, n, i);
c++;
}
}
int *
embedg_vertices_orientation (t_ver_edge *embed_graph, int n) /* foreachvertexreturnitsorientationfromthe bicompsinembed_graph: performaDFSofeachbicomp
*/
{ int i, vv, prod_sign; int *stack, *ver_orient, to_prev;
int
embedg_nbr_faces (t_ver_edge *embed_graph, int n, int edge_pos, int *ver_orient, int *nbr_e_embed) /* countthenumberoffacesandthenumberofedgesoftheembedding
*/
{ int v, e, f, total_e;
IF_DEB_FACES( int v;
fprintf(stdout, "nbr of faces, the vertices' adj. lists\n"); for (v = 0; v < n; v++)
embedg_VES_print_adj_list(embed_graph, n,
v, TRUE);
)
/* thefollowingisnomorethanaquickcheck--certainly notveryuseful--orcouldbedoneelsewhere
*/
total_e = 0; for (e = 2*n; e <= edge_pos; e++)
{ if (!embedg_VES_is_short_cut_edge(embed_graph, n, e))
{
total_e++;
}
}
ASSERT(total_e % 2 == 0);
*nbr_e_embed = total_e / 2;
/* Inowseteachedge'sorientation
QUESTION:doIreallyneedtodothis??? sofar,whendoingaproperfacetraversal,thewayinwhich theadjacencylistofanedgemustbetraversedisgiven bythevertex's(inthatlist)orientation... Sothisseemssensibletomehuh?
*/
embedg_VES_set_orientation(embed_graph, n, ver_orient);
soherewesetittoMARK_EMBED(n)
*/
f = 0; for (e = 2*n; e <= edge_pos; e++)
{ if (!embedg_VES_is_short_cut_edge(embed_graph, n, e) /* arrghh!!!ImustalsoskiptheSCE!!!
*/
&& embed_graph[e].visited != MARK_EMBED(n))
{ int ein;
IF_DEB_FACES(
fprintf(stdout, "nbr of faces, edges not visited\n");
embedg_VES_print_edge(embed_graph, n, e);
)
ein = embed_graph[e].sign == CCLOCKW ? 0 : 1; /* thewayIentereindependentonitssign: alltheproperfacetraversalmustobviouslybedone withthesameorientation!
*/
embedg_VES_walk_proper_face(embed_graph, n, e,
ein, TRUE,
MARK_EMBED(n));
f++;
}
}
weonlyneedtocheckwhichverticesrefertoself,iewith noincidentedges
*/ for (v = 0; v < n; v++)
{ if (embed_graph[v].link[0] == v)
{
ASSERT(embed_graph[v].link[1] == v);
f++;
}
}
return f;
}
boolean
embedg_is_embed_valid (t_ver_edge *embed_graph, int n, int nbr_comp, int edge_pos, int *ver_orient, int *nbr_e_embed) /* useEuler'sformulatoassertainthattheembeddingisavalid embedding:
f=2*nbr_comp+nbr_e_embed-n
*/
{ int v, f;
f = embedg_nbr_faces(embed_graph, n, edge_pos, ver_orient, nbr_e_embed);
void
embedg_VES_get_succ_on_ext_face (t_ver_edge *embed_graph, int n, int v, int vin, boolean MARK, int mark, int *s, int *sin) /* findthesuccessorsofv(enteredviavin)ontheexternalface --alsoreturnthedirectioninwhichshasbeenentered
ifMARKtruemarkthesucc.vertexandtheedgestraversed withmark(thevisitedfield)
*/
{ int e, twin; int vout, ein, eout, tout;
void
embedg_VES_get_succ_active_on_ext_face (t_ver_edge *embed_graph, int n, int v, int w, int win, boolean MARK, int mark, int *s, int *sin) /* findtheACTIVE(wrtv)successorsofw(enteredviawin) ontheexternalface --alsoreturnthedirectioninwhichshasbeenentered ifMARKtruemarkthesucc.vertex(andtheedge) withmark(thevisitedfield)
*/
{ /* simplyrepeatedlycallsembedg_VES_get_succ_on_ext_face untilanactivevertexisfound
*/
ASSERT(embedg_VES_is_vertex(n, w)
|| embedg_VES_is_virtual_vertex(n, w));
embedg_VES_get_succ_on_ext_face(embed_graph, n,
w, win, MARK, mark, s, sin); while (embedg_VES_is_ver_inactive(embed_graph, n, v, *s))
{
embedg_VES_get_succ_on_ext_face(embed_graph, n,
*s, *sin, MARK, mark, s, sin);
}
ASSERT(!embedg_VES_is_ver_inactive(embed_graph, n, v, *s));
}
void
embedg_VES_get_succ_ext_active_on_ext_face (t_ver_edge *embed_graph, int n, int v, int w, int win, boolean MARK, int mark, int *s, int *sin) /* findtheexternallyactive(wrtv)successorsofw(enteredviawin) ontheexternalface --alsoreturnthedirectioninwhichshasbeenentered ifMARKtruemarkthesucc.vertex(andtheedge) withmark(thevisitedfield)
*/
{
ASSERT(embedg_VES_is_vertex(n, w)
|| embedg_VES_is_virtual_vertex(n, w));
embedg_VES_get_succ_on_ext_face(embed_graph, n,
w, win, MARK, mark, s, sin); while (!embedg_VES_is_ver_ext_active(embed_graph, n, v, *s))
{
embedg_VES_get_succ_on_ext_face(embed_graph, n,
*s, *sin, MARK, mark, s, sin);
}
ASSERT(embedg_VES_is_ver_ext_active(embed_graph, n, v, *s));
}
void
embedg_VES_get_succ_pertinent_on_ext_face (t_ver_edge *embed_graph, int n, int v, int w, int win, boolean MARK, int mark, int *s, int *sin) /* findthepertinent(wrtv)successorsofw(enteredviawin) ontheexternalface --alsoreturnthedirectioninwhichshasbeenentered ifMARKtruemarkthesucc.vertex(andtheedge) withmark(thevisitedfield)
*/
{
ASSERT(embedg_VES_is_vertex(n, w)
|| embedg_VES_is_virtual_vertex(n, w));
embedg_VES_get_succ_on_ext_face(embed_graph, n,
w, win, MARK, mark, s, sin); while (!embedg_VES_is_ver_pertinent(embed_graph, n, v, *s))
{
embedg_VES_get_succ_on_ext_face(embed_graph, n,
*s, *sin, MARK, mark, s, sin);
}
ASSERT(embedg_VES_is_ver_pertinent(embed_graph, n, v, *s));
}
staticvoid
embedg_VES_walk_mark_part_ext_face (t_ver_edge *embed_graph, int n, int v, int vin, int from, int to, int mark) /* walk&marktheexternalface: walkinthedirectionvin->v->voutandmark<from><to>
*/
{ int cur, curin, next, nextin;
staticvoid
embedg_VES_walk_mark_ext_face (t_ver_edge *embed_graph, int n, int v, int mark) /* walk&marktheexternalface,starting&endingatvertexv
*/
{
embedg_VES_walk_mark_part_ext_face(embed_graph, n, v, 0, v, v,
mark);
}
staticvoid
embedg_VES_walk_mark_part_proper_face (t_ver_edge *embed_graph, int n, int from_e, int from_ein, int to, int mark) /* walk&markaproperfacestartingatEDGEfrom_eandending atVERTEXto
walkinthedirectionfrom_ein->from_e->toandmark everythinginbetween
*/
{ int s, cur_e, cur_ein, next_e, next_ein;
next_e = s = n; /* this is an invalid value for an edge/vertex */
cur_e = from_e;
cur_ein = from_ein; while (s != to)
{
ASSERT(embedg_VES_is_edge(n, cur_e));
ASSERT(!embedg_VES_is_short_cut_edge(embed_graph,
n, cur_e));
static boolean
embedg_VES_is_part_ext_face_marked (t_ver_edge *embed_graph, int n, int v, int vin, int from, int to, int mark) /* simplechecktoseeifalltheverticesontheexternal facewalkstartingatvin->v->vout<from><to>aremarked (withmark)
*/
{ int cur, curin, next, nextin;
if (embed_graph[from].visited != mark || embed_graph[to].visited != mark) returnFALSE;
cur = v;
curin = vin;
next = n; while (next != from)
{
embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &next, &nextin);
cur = next;
curin = nextin;
} while (next != to)
{
embedg_VES_get_succ_on_ext_face(embed_graph, n, cur, curin, FALSE, 0, &next, &nextin); if (embed_graph[next].visited != mark) returnFALSE;
cur = next;
curin = nextin;
}
returnTRUE;
}
boolean
embedg_VES_is_ext_face_marked (t_ver_edge *embed_graph, int n, int v, int mark) /* simplechecktoseeifalltheverticesontheexternal facewalkstarting/endingatvaremarked(withmark)
*/
{ return embedg_VES_is_part_ext_face_marked(embed_graph, n, v, 0,
v, v, mark);
}
staticvoid
embedg_get_u_x (t_ver_edge *embed_graph, int n, int v, int x, int *u_x) /* xisanexternallyactivevertex(wrtv): wewantu_x,thelowestpointof"attachement"for theunembeddeddirectededge[x,u_x]
*/
{ int c;
t_dlcl *child_list;
ASSERT(embedg_VES_is_ver_ext_active(embed_graph, n, v, x)); if (embed_graph[x].least_ancestor < v) /* thenthereisasingleunembeddedbackedge(u_x,x), u_xanancestorofv
*/
{
*u_x = embed_graph[x].least_ancestor; return;
}
staticint
embedg_get_least_neigh (t_dlcl **dfs_tree, t_dlcl **back_edges, int n, int v, int c) /* gettheleastneighbourofv>=c,ieavertexinthesubtree rootedbyc
somehowthismustalwayssucceed
*/
{ int least_n;
t_dlcl *tree_l, *back_l, *p;
staticvoid
embedg_add_mark_u_x (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int x, int *u_x, int mark) /* markingaKuratowskihomeomorph: markingandaddingtheunembeddeddottededge(u,x), xanext.activevertexwrtv
*/
{ int c, d_x;
t_dlcl *child_list;
/* marktheDFStreepathfromd_xtox
*/
embedg_mark_tree_path(embed_graph, n, d_x, x, mark); /* addtheunembedded(u_x,d_x)edge
*/
embedg_VES_add_edge(embed_graph, n, edge_pos, *u_x, d_x, TRUE, mark);
}
staticvoid
embedg_mark_tree_path (t_ver_edge *embed_graph, int n, int d_x, int x, int mark) /* markingtheDFStreepathd_x...xwherexisanancestorofd_x
*/
{ int cur_v, te, twe;
ASSERT(d_x >= x);
cur_v = d_x;
while (cur_v != x)
{
embed_graph[cur_v].visited = mark;
te = embed_graph[cur_v].link[0];
ASSERT(embedg_VES_is_edge(n, te)); while (!embedg_VES_is_tree_edge(embed_graph, n, te)
|| (embed_graph[te].neighbour > cur_v
&& embed_graph[te].neighbour != cur_v + n)) /* wanttofindatreeedgeincidenttoanancestorofd_x: giventhatd_x..xisatreepath,weMUSTfindsuchanedge!
staticvoid
embedg_add_mark_v_w (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int w, int mark) /* markingaKuratowskihomeomorph: markingandaddingtheunembeddeddottededge(v,w), wispertinentwrtv
*/
{ int vw, c, d_w;
t_dlcl *bicomp_list;
/* marktheDFStreepathfromd_wtow
*/
embedg_mark_tree_path(embed_graph, n, d_w, w, mark); /* addtheunembedded(d_w,v)edge
*/
embedg_VES_add_edge(embed_graph, n, edge_pos, d_w, v, TRUE, mark);
}
staticvoid
embedg_add_mark_v_w_for_B (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int w, int *u_z, int mark) /* markingaKuratowskihomeomorph: markingandaddingtheunembeddeddottededge(v,w)forminorB: wispertinentwrtv
*/
{ int vz, z, d_z, d_w;
t_dlcl *bicomp_list;
(note:path_vandpath_econtainnbr_v+1elts!)
*/
embed_graph[path_v[0]].visited = mark; for (i = 1; i <= nbr_v; i++)
{ int e, twin;
embed_graph[path_v[i]].visited = mark;
e = path_e[i];
twin = embedg_VES_get_twin_edge(embed_graph, n, e);
embed_graph[e].visited =
embed_graph[twin].visited = mark;
}
}
void
embedg_mark_minor_A (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int vr)
{ int r, r_c, x, y, w, u_x, u_y, u;
ASSERT(embedg_VES_is_virtual_vertex(n, vr));
r_c = vr - n;
r = embed_graph[r_c].DFS_parent;
/* marktheedges(u,x),(u,y),(v,w)
*/
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, x, &u_x,
MARK_MINORS(n));
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, y, &u_y,
MARK_MINORS(n));
embedg_add_mark_v_w(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, w,
MARK_MINORS(n));
/* markthetreepathfromrtomin(u_x,u_y)
*/
u = u_x <= u_y ? u_x : u_y;
embedg_mark_tree_path(embed_graph, n, r, u, MARK_MINORS(n));
IF_DEB(
fprintf(stdout, "mark minor A\n");
fprintf(stdout, "v %d\t c %d\t r %d\t r_c %d\t x %d\t y %d\t w %d\t u_x %d\t u_y %d\n",
v, c, r, r_c, x, y, w, u_x, u_y);
)
}
void
embedg_mark_minor_B (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w)
{ int vv, u_x, u_y, vz, u_z, u_max, u_min;
vv = c + n;
/* marktheexternalfaceofthebicomprootedbyv^c
*/
embedg_VES_walk_mark_ext_face(embed_graph, n, vv, MARK_MINORS(n));
ASSERT(embedg_VES_is_ext_face_marked(embed_graph, n, vv,
MARK_MINORS(n)));
/* marktheedges(u,x),(u,y)
*/
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, x, &u_x,
MARK_MINORS(n));
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, y, &u_y,
MARK_MINORS(n));
IF_DEB(
fprintf(stdout, "mark minor B\n");
fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t u_x %d\t u_y %d\t u_z %d\n",
v, c, x, y, w, u_x, u_y, u_z);
)
}
void
embedg_mark_minor_C (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w, int *path_v, int *path_e, int nbr_v, boolean px_attached_high, boolean py_attached_high)
{ int vv, p_x, p_y, u_x, u_y, u;
if (px_attached_high) /* marktheexternalface: -fromv^ctop_yifpy_attached_high -fromv^ctoyif!py_attached_high
nottoosureaboutthatone....
fromv^ctop_y:sovvin=0, inx'sdirection
*/
{ if (py_attached_high)
embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0,
vv, p_y, MARK_MINORS(n)); else
embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 0,
vv, y, MARK_MINORS(n));
} else /* symmetriccase: marktheexternalfacefromv^ctop_x:sovvin=1, iny'sdirection
*/
{ if (px_attached_high)
embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1,
vv, p_x, MARK_MINORS(n)); else
embedg_VES_walk_mark_part_ext_face(embed_graph, n, vv, 1,
vv, x, MARK_MINORS(n));
}
/* marktheedges(u,x),(u,y),(v,w)
*/
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, x, &u_x,
MARK_MINORS(n));
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, y, &u_y,
MARK_MINORS(n));
embedg_add_mark_v_w(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, w,
MARK_MINORS(n));
/* markthetreepathfromvtomin(u_x,u_y)
*/
u = u_x <= u_y ? u_x : u_y;
embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n));
/* finally,markthex-ypath,ietheverticesinpath_v andtheedgesinpath_e
*/
embedg_mark_x_y_path(embed_graph, n, path_v, path_e, nbr_v,
MARK_MINORS(n));
IF_DEB(
fprintf(stdout, "mark minor C p_x high %d\t p_y high %d\n",
px_attached_high, py_attached_high);
fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\n",
v, c, x, y, w, p_x, p_y, u_x, u_y);
)
}
void
embedg_mark_minor_D (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w, int *path_v, int *path_e, int nbr_v, int entry_in_path_e)
{ int i, vv, p_x, p_y, u_x, u_y, u;
BUTawalkthatsaystartsatp_xandendsatvv, thatis,awalkstartingatpath_e[1]enteredfromentry_in_path_e (recallthatpath_e[0]isadummy)
*/
embedg_VES_walk_mark_part_proper_face(embed_graph, n,
path_e[1], entry_in_path_e,
vv, MARK_MINORS(n));
/* anoteofcautionhere: ALWAYSmarkexternal/internalfacesbeforeaddinganyotheredges: sinceaddingedgesdestroysthefaces'consistency (addingedgesmakesnosenseoffacesinceweareinanon-planar situation)
*/ /* marktheedges(u,x),(u,y),(v,w)
*/
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, x, &u_x,
MARK_MINORS(n));
embedg_add_mark_u_x(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, y, &u_y,
MARK_MINORS(n));
embedg_add_mark_v_w(dfs_tree, back_edges,
embed_graph, n, edge_pos, v, w,
MARK_MINORS(n));
/* markthetreepathfromvtomin(u_x,u_y)
*/
u = u_x <= u_y ? u_x : u_y;
embedg_mark_tree_path(embed_graph, n, v, u, MARK_MINORS(n));
/* markthex-ypath,ietheverticesinpath_v andtheedgesinpath_e
*/
embedg_mark_x_y_path(embed_graph, n, path_v, path_e, nbr_v,
MARK_MINORS(n));
IF_DEB(
fprintf(stdout, "mark minor D\n");
fprintf(stdout, "v %d\t c %d\t x %d\t y %d\t w %d\t p_x %d\t p_y %d\t u_x %d\t u_y %d\n",
v, c, x, y, w, p_x, p_y, u_x, u_y);
)
}
minor
embedg_mark_minor_E (t_dlcl **dfs_tree, t_dlcl **back_edges,
t_ver_edge *embed_graph, int n, int *edge_pos, int v, int c, int x, int y, int w, int *path_v, int *path_e, int nbr_v) /* whilemarkingminorEreturnwhichoftheminorswearedealingwith
*/
{ int vv, p_x, p_y, u_x, u_y, u_w, u, u_max, u_min;
if (!embedg_VES_is_ver_ext_active(embed_graph, n, v, w)) /* minorE1case:wemustfindanext.activez,distinctfromw, ontheexternalfacep_x..w..p_y
*/
{ int s, sin, cur, curin, z, u_z, u_xy;
s = n; /* startsearchingatvventeredfrom0(inx'sdirection) --weMUSTreachp_x-hopefully!:)
*/
cur = vv;
curin = 0; while (s != p_x) /* firstadvancetop_x:wearesureofreachingit
*/
{
embedg_VES_get_succ_on_ext_face(embed_graph, n,
cur, curin, FALSE, 0, &s, &sin);
cur = s;
curin = sin;
}
boolean
embedg_VES_get_succ_on_proper_face_with_avoidance (t_ver_edge *embed_graph, int n, int e, int ein, int a, boolean MARK, int mark, int *s, int *next_e, int *next_ein) /* findthesuccessorsofembed_graph[e].neighbour (enteredviaein)onaproperfacetraversal whichavoids(thevertex)aifa!=n
(whenwemarkwhencountingthefaces,weMUSTonly marktheedgeandNOTitstwin)
*/ if (mark == MARK_MINORS(n))
{
twin =
embedg_VES_get_twin_edge(embed_graph, n, *next_e);
embed_graph[twin].visited = mark;
}
}
return avoid_a;
}
void
embedg_VES_get_succ_on_proper_face (t_ver_edge *embed_graph, int n, int e, int ein, int MARK, int mark, int *s, int *next_e, int *next_ein) /* sameasabovebutwithoutavoidance
*/
{
boolean avoid;
avoid =
embedg_VES_get_succ_on_proper_face_with_avoidance(
embed_graph, n,
e, ein, n,
MARK, mark,
s, next_e, next_ein);
ASSERT(avoid == FALSE);
}
void
embedg_VES_walk_proper_face (t_ver_edge *embed_graph, int n, int e, int ein, boolean MARK, int mark) /* traversingaproperfacestartingatedgeewhichhasbeenentered viaein
--wemarkthevisitededgeswithmarkifsorequested
assumesthatshort-cutedgeshavebeenremovedandthateach edge/vertexhasbeengivenitsorientation
*/
{ int s, cur_e, cur_ein, next_e, next_ein;
next_e = n; /* this is an invalid value for an edge */
IF_DEB_PROPER_FACE(
fprintf(stdout, "proper face traversal\n");
)
cur_e = e;
cur_ein = ein; while (next_e != e)
{
ASSERT(embedg_VES_is_edge(n, cur_e));
ASSERT(!embedg_VES_is_short_cut_edge(embed_graph,
n, cur_e));
IF_DEB_PROPER_FACE(
embedg_VES_print_edge(embed_graph, n, cur_e);
)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.