Example #1
0
        public static void coarsen1(vtx_data **graph,    /* array of vtx data for graph */
                                    int nvtxs,           /* number of vertices in graph */
                                    int nedges,          /* number of edges in graph */
                                    vtx_data ***pcgraph, /* coarsened version of graph */
                                    int *pcnvtxs,        /* number of vtxs in coarsened graph */
                                    int *pcnedges,       /* number of edges in coarsened graph */
                                    int **pv2cv,         /* pointer to v2cv */
                                    int igeom,           /* dimension for geometric information */
                                    float **coords,      /* coordinates for vertices */
                                    float **ccoords,     /* coordinates for coarsened vertices */
                                    bool useEdgeWeights  /* are edge weights being used? */
                                    )
        {
            double time;    /* time routine is entered */
            int *  v2cv;    /* maps from vtxs to cvtxs */
            int *  mflag;   /* flag indicating vtx matched or not */
            int    cnvtxs;  /* number of vtxs in coarse graph */
            int    nmerged; /* number of edges contracted */

            time = seconds();

            /* Allocate and initialize space. */
            v2cv  = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));
            mflag = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));

            /* Find a maximal matching in the graph. */
            nmerged     = maxmatch(graph, nvtxs, nedges, mflag, useEdgeWeights, igeom, coords);
            match_time += seconds() - time;

            /* Now construct coarser graph by contracting along matching edges. */
            /* Pairs of values in mflag array indicate matched vertices. */
            /* A zero value indicates that vertex is unmatched. */

            /*
             *  makecgraph(graph, nvtxs, pcgraph, pcnvtxs, pcnedges, mflag, *pv2cv, nmerged, useEdgeWeights, igeom, coords, ccoords);
             *  makecgraph2(graph, nvtxs, nedges, pcgraph, pcnvtxs, pcnedges, mflag, *pv2cv, nmerged, useEdgeWeights, igeom, coords, ccoords);
             */

            makev2cv(mflag, nvtxs, v2cv);

            Marshal.FreeHGlobal((IntPtr)mflag);

            cnvtxs = nvtxs - nmerged;
            makefgraph(graph, nvtxs, nedges, pcgraph, cnvtxs, pcnedges, v2cv, useEdgeWeights, igeom, coords,
                       ccoords);

            *pcnvtxs = cnvtxs;
            *pv2cv   = v2cv;
            coarsen_time += seconds() - time;
        }
Example #2
0
        public static bool flatten(vtx_data **graph,    /* array of vtx data for graph */
                                   int nvtxs,           /* number of vertices in graph */
                                   int nedges,          /* number of edges in graph */
                                   vtx_data ***pcgraph, /* coarsened version of graph */
                                   int *pcnvtxs,        /* number of vtxs in coarsened graph */
                                   int *pcnedges,       /* number of edges in coarsened graph */
                                   int **pv2cv,         /* pointer to v2cv */
                                   bool useEdgeWeights, /* are edge weights being used? */
                                   int igeom,           /* dimensions of geometric data */
                                   float **coords,      /* coordinates for vertices */
                                   float **ccoords      /* coordinates for coarsened vertices */
                                   )
        {
            double Thresh; /* minimal acceptable size reduction */
            int *  v2cv;   /* map from vtxs to coarse vtxs */
            int    cnvtxs; /* number of vertices in flattened graph */

            Thresh = .9;

            v2cv = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));

            find_flat(graph, nvtxs, &cnvtxs, v2cv);

            if (cnvtxs <= Thresh * nvtxs) /* Sufficient shrinkage? */
            {
                makefgraph(graph, nvtxs, nedges, pcgraph, cnvtxs, pcnedges, v2cv, useEdgeWeights, igeom, coords,
                           ccoords);

                *pcnvtxs = cnvtxs;
                *pv2cv   = v2cv;
                return(true);
            }

            /* Not worth bothering */
            Marshal.FreeHGlobal((IntPtr)v2cv);
            return(false);
        }
Example #3
0
        /* Change from a FORTRAN graph style to our graph data structure. */

        public static bool reformat(int *start,        /* start of edge list for each vertex */
                                    int *adjacency,    /* edge list data */
                                    int nvtxs,         /* number of vertices in graph */
                                    int *pnedges,      /* ptr to number of edges in graph */
                                    int *vwgts,        /* weights for all vertices */
                                    float *ewgts,      /* weights for all edges */
                                    vtx_data ***pgraph /* ptr to array of vtx data for graph */
                                    )
        {
            Trace.WriteLine($"<Entering {nameof(reformat)}>");

            vtx_data **graph     = null;          /* array of vtx data for graph */
            vtx_data * links     = null;          /* space for data for all vtxs */
            int *      edges     = null;          /* space for all adjacency lists */
            float *    eweights  = null;          /* space for all edge weights */
            int *      eptr      = null;          /* steps through adjacency list */
            int *      eptr_save = null;          /* saved index into adjacency list */
            float *    wptr      = null;          /* steps through edge weights list */
            int        self_edge;                 /* number of self loops detected */
            int        size;                      /* length of all edge lists */
            double     sum;                       /* sum of edge weights for a vtx */
            int        i, j;                      /* loop counters */

            var useEdgeWeights = (ewgts != null); /* are edge weights being used? */
            var using_vwgts    = (vwgts != null); /* are vertex weights being used? */

            graph = (vtx_data **)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(vtx_data *));
            *pgraph = graph;
            if (graph == null)
            {
                return(true);
            }

            graph[1] = null;

            /* Set up all the basic data structure for the vertices. */
            /* Replace many small mallocs by a few large ones. */
            links = (vtx_data *)Marshal.AllocHGlobal((nvtxs) * sizeof(vtx_data));
            if (links == null)
            {
                return(true);
            }

            for (i = 1; i <= nvtxs; i++)
            {
                graph[i] = links++;
            }

            graph[1]->edges = null;
            graph[1]->ewgts = null;

            /* Now fill in all the data fields. */
            if (start != null)
            {
                *pnedges = start[nvtxs] / 2;
            }
            else
            {
                *pnedges = 0;
            }

            size  = 2 * (*pnedges) + nvtxs;
            edges = (int *)Marshal.AllocHGlobal(size * sizeof(int));
            if (edges == null)
            {
                return(true);
            }

            if (useEdgeWeights)
            {
                eweights = (float *)Marshal.AllocHGlobal(size * sizeof(float));
                if (eweights == null)
                {
                    return(true);
                }
            }

            if (start != null)
            {
                eptr = adjacency + start[0];
                wptr = ewgts;
            }

            self_edge = 0;

            for (i = 1; i <= nvtxs; i++)
            {
                if (using_vwgts)
                {
                    graph[i]->vwgt = *(vwgts++);
                }
                else
                {
                    graph[i]->vwgt = 1;
                }

                if (start != null)
                {
                    size = start[i] - start[i - 1];
                }
                else
                {
                    size = 0;
                }

                graph[i]->nedges = size + 1;
                graph[i]->edges  = edges;
                *edges++ = i;
                eptr_save = eptr;
                for (j = size; j != 0; j--)
                {
                    if (*eptr != i)
                    {
                        *edges++ = *eptr++;
                    }
                    else
                    {
                        /* Self edge, skip it. */
                        //if (self_edge == 0)
                        {
                            Trace.WriteLine($"WARNING: Self edge ({i:d},{i:d}) being ignored");
                        }

                        ++self_edge;
                        eptr++;
                        --(graph[i]->nedges);
                        --(*pnedges);
                    }
                }

                if (useEdgeWeights)
                {
                    graph[i]->ewgts = eweights;
                    eweights++;
                    sum = 0;
                    for (j = size; j != 0; j--)
                    {
                        if (*eptr_save++ != i)
                        {
                            sum += *wptr;
                            *eweights++ = *wptr++;
                        }
                        else
                        {
                            wptr++;
                        }
                    }

                    graph[i]->ewgts[0] = (float)-sum;
                }
                else
                {
                    graph[i]->ewgts = null;
                }
            }

            if (self_edge > 1)
            {
                Trace.WriteLine($"WARNING: {self_edge:d} self edges were detected and ignored");
            }

            return(false);
        }
Example #4
0
        /* Construct a weighted quotient graph representing the inter-set communication. */
        public static bool make_comm_graph(vtx_data ***pcomm_graph, /* graph for communication requirements */
                                           vtx_data **graph,        /* graph data structure */
                                           int nvtxs,               /* number of vertices in graph */
                                           bool useEdgeWeights,     /* are edge weights being used? */
                                           int *assign,             /* current assignment */
                                           int nsets_tot            /* total number of sets */
                                           )
        {
            float  ewgt;               /* edge weight in graph */
            int ** edges_list = null;  /* lists of edges */
            int ** ewgts_list = null;  /* lists of edge weights */
            int *  edges = null;       /* edges in communication graph */
            int *  ewgts = null;       /* edge weights in communication graph */
            float *float_ewgts = null; /* edge weights in floating point */
            int *  adj_sets = null;    /* weights connecting sets */
            int *  order = null;       /* ordering of vertices by set */
            int *  sizes = null;       /* sizes of different sets */
            int *  start = null;       /* pointers into adjacency data */
            int *  adjacency = null;   /* array with all the edge info */
            int *  eptr = null;        /* loops through edges in graph */
            int *  ewptr = null;       /* loop through edge weights */
            int    set, set2;          /* sets two vertices belong to */
            int    vertex;             /* vertex in graph */
            int    ncomm_edges;        /* number of edges in communication graph */
            bool   error;              /* out of space? */
            int    i, j;               /* loop counters */

            error = true;
            *pcomm_graph = null;

            /* First construct some mappings to ease later manipulations. */
            sizes = (int *)Marshal.AllocHGlobal(nsets_tot * sizeof(int));
            if (sizes == null)
            {
                goto skip;
            }

            for (i = 0; i < nsets_tot; i++)
            {
                sizes[i] = 0;
            }
            for (i = 1; i <= nvtxs; i++)
            {
                ++(sizes[assign[i]]);
            }

            /* Now make sizes reflect the start index for each set. */
            for (i = 1; i < nsets_tot - 1; i++)
            {
                sizes[i] += sizes[i - 1];
            }
            for (i = nsets_tot - 1; i != 0; i--)
            {
                sizes[i] = sizes[i - 1];
            }
            sizes[0] = 0;

            /* Now construct list of all vertices in set 0, all in set 1, etc. */
            order = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
            if (order == null)
            {
                goto skip;
            }
            for (i = 1; i <= nvtxs; i++)
            {
                set = assign[i];
                order[sizes[set]] = i;
                ++sizes[set];
            }

            /* For each set, find total weight to all neighbors. */
            adj_sets   = (int *)Marshal.AllocHGlobal(nsets_tot * sizeof(int));
            edges_list = (int **)Marshal.AllocHGlobal(nsets_tot * sizeof(int *));
            ewgts_list = (int **)Marshal.AllocHGlobal(nsets_tot * sizeof(int *));
            start      = (int *)Marshal.AllocHGlobal((nsets_tot + 1) * sizeof(int));
            if (adj_sets == null || edges_list == null || ewgts_list == null || start == null)
            {
                goto skip;
            }

            start[0]    = 0;
            ewgt        = 1;
            ncomm_edges = 0;

            for (set = 0; set < nsets_tot; set++)
            {
                edges_list[set] = null;
                ewgts_list[set] = null;
            }

            for (set = 0; set < nsets_tot; set++)
            {
                for (i = 0; i < nsets_tot; i++)
                {
                    adj_sets[i] = 0;
                }
                for (i = (set != 0 ? sizes[set - 1] : 0); i < sizes[set]; i++)
                {
                    vertex = order[i];
                    for (j = 1; j < graph[vertex]->nedges; j++)
                    {
                        set2 = assign[graph[vertex]->edges[j]];
                        if (set2 != set)
                        {
                            if (useEdgeWeights)
                            {
                                ewgt = graph[vertex]->ewgts[j];
                            }
                            adj_sets[set2] += (int)ewgt;
                        }
                    }
                }

                /* Now save adj_sets data to later construct graph. */
                j = 0;
                for (i = 0; i < nsets_tot; i++)
                {
                    if (adj_sets[i] != 0)
                    {
                        j++;
                    }
                }
                ncomm_edges   += j;
                start[set + 1] = ncomm_edges;
                if (j != 0)
                {
                    edges_list[set] = edges = (int *)Marshal.AllocHGlobal(j * sizeof(int));
                    ewgts_list[set] = ewgts = (int *)Marshal.AllocHGlobal(j * sizeof(int));
                    if (edges == null || ewgts == null)
                    {
                        goto skip;
                    }
                }
                j = 0;
                for (i = 0; i < nsets_tot; i++)
                {
                    if (adj_sets[i] != 0)
                    {
                        edges[j] = i + 1;
                        ewgts[j] = adj_sets[i];
                        j++;
                    }
                }
            }

            Marshal.FreeHGlobal((IntPtr)adj_sets);
            Marshal.FreeHGlobal((IntPtr)order);
            Marshal.FreeHGlobal((IntPtr)sizes);
            adj_sets = order = sizes = null;

            /* I now need to pack the edge and weight data into single arrays. */
            adjacency   = (int *)Marshal.AllocHGlobal((ncomm_edges + 1) * sizeof(int));
            float_ewgts = (float *)Marshal.AllocHGlobal((ncomm_edges + 1) * sizeof(float));
            if (adjacency == null || float_ewgts == null)
            {
                goto skip;
            }

            for (set = 0; set < nsets_tot; set++)
            {
                j     = start[set];
                eptr  = edges_list[set];
                ewptr = ewgts_list[set];
                for (i = start[set]; i < start[set + 1]; i++)
                {
                    adjacency[i]   = eptr[i - j];
                    float_ewgts[i] = ewptr[i - j];
                }
                if (start[set] != start[set + 1])
                {
                    Marshal.FreeHGlobal((IntPtr)edges_list[set]);
                    Marshal.FreeHGlobal((IntPtr)ewgts_list[set]);
                }
            }
            Marshal.FreeHGlobal((IntPtr)edges_list);
            Marshal.FreeHGlobal((IntPtr)ewgts_list);
            edges_list = ewgts_list = null;

            error =
                reformat(start, adjacency, nsets_tot, &ncomm_edges, (int *)null, float_ewgts, pcomm_graph);

skip:
            Marshal.FreeHGlobal((IntPtr)adj_sets);
            Marshal.FreeHGlobal((IntPtr)order);
            Marshal.FreeHGlobal((IntPtr)sizes);
            if (edges_list != null)
            {
                for (set = nsets_tot - 1; set >= 0; set--)
                {
                    if (edges_list[set] != null)
                    {
                        Marshal.FreeHGlobal((IntPtr)edges_list[set]);
                    }
                }
                Marshal.FreeHGlobal((IntPtr)edges_list);
            }

            if (ewgts_list != null)
            {
                for (set = nsets_tot - 1; set >= 0; set--)
                {
                    if (ewgts_list[set] != null)
                    {
                        Marshal.FreeHGlobal((IntPtr)ewgts_list[set]);
                    }
                }
                Marshal.FreeHGlobal((IntPtr)ewgts_list);
            }

            Marshal.FreeHGlobal((IntPtr)float_ewgts);
            Marshal.FreeHGlobal((IntPtr)adjacency);
            Marshal.FreeHGlobal((IntPtr)start);

            return(error);
        }
Example #5
0
        public static void makefgraph(vtx_data **graph,    /* array of vtx data for graph */
                                      int nvtxs,           /* number of vertices in graph */
                                      int nedges,          /* number of edges in graph */
                                      vtx_data ***pcgraph, /* coarsened version of graph */
                                      int cnvtxs,          /* number of vtxs in coarsened graph */
                                      int *pcnedges,       /* number of edges in coarsened graph */
                                      int *v2cv,           /* mapping from vtxs to coarsened vtxs */
                                      bool useEdgeWeights, /* are edge weights being used? */
                                      int igeom,           /* dimensions of geometric data */
                                      float **coords,      /* coordinates for vertices */
                                      float **ccoords      /* coordinates for coarsened vertices */
                                      )
        {
            vtx_data **cgraph    = null; /* coarsened version of graph */
            vtx_data * links     = null; /* space for all the vertex data */
            vtx_data **gptr      = null; /* loops through cgraph */
            vtx_data * cgptr     = null; /* loops through cgraph */
            int *      iptr      = null; /* loops through integer arrays */
            int *      seenflag  = null; /* flags for vtxs already put in edge list */
            int *      sptr      = null; /* loops through seenflags */
            int *      cv2v_vals = null; /* vtxs corresponding to each cvtx */
            int *      cv2v_ptrs = null; /* indices into cv2v_vals */
            float *    eweights  = null; /* space for edge weights in coarsened graph */
            float *    ewptr     = null; /* loops through eweights */
            float *    fptr      = null; /* loops through eweights */
            float      ewgt;             /* edge weight */
            double     ewgt_sum;         /* sum of edge weights */
            double     time;             /* timing parameters */
            int        nseen;            /* number of edges of coarse graph seen so far */
            int        vtx;              /* vertex in original graph */
            int        cvtx;             /* vertex in coarse graph */
            int        cnedges;          /* twice number of edges in coarsened graph */
            int        neighbor;         /* neighboring vertex */
            int        size;             /* space needed for coarsened graph */
            int *      edges = null;     /* space for edges in coarsened graph */
            int *      eptr  = null;     /* loops through edges data structure */
            int        cneighbor;        /* neighboring vertex number in coarsened graph */
            int        i, j;             /* loop counters */

            /* Compute the number of vertices and edges in the coarsened graph, */
            /* and construct start pointers into coarsened edge array. */
            time = seconds();

            /* Construct mapping from original graph vtxs to coarsened graph vtxs. */
            cv2v_vals = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
            cv2v_ptrs = (int *)Marshal.AllocHGlobal((cnvtxs + 2) * sizeof(int));
            makecv2v(nvtxs, cnvtxs, v2cv, cv2v_vals, cv2v_ptrs);

            /* Compute an upper bound on the number of coarse graph edges. */
            cnedges = nedges - (nvtxs - cnvtxs);

            /* Now allocate space for the new graph.  Overallocate and realloc later. */
            *pcgraph = cgraph = (vtx_data **)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(vtx_data *));
            links = (vtx_data *)Marshal.AllocHGlobal(cnvtxs * sizeof(vtx_data));

            size  = 2 * cnedges + cnvtxs;
            edges = (int *)Marshal.AllocHGlobal(size * sizeof(int));
            if (COARSEN_EWGTS)
            {
                ewptr = eweights = (float *)Marshal.AllocHGlobal(size * sizeof(float));
            }

            /* Zero all the seen flags. */
            seenflag = (int *)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(int));
            sptr     = seenflag;
            for (i = cnvtxs; i != 0; i--)
            {
                *(++sptr) = 0;
            }

            /* Use the renumbering to fill in the edge lists for the new graph. */
            cnedges = 0;
            eptr    = edges;
            ewgt    = 1;

            sptr = cv2v_vals;
            for (cvtx = 1; cvtx <= cnvtxs; cvtx++)
            {
                nseen = 1;

                cgptr = cgraph[cvtx] = links++;

                if (COARSEN_VWGTS)
                {
                    cgptr->vwgt = 0;
                }
                else
                {
                    cgptr->vwgt = 1;
                }

                eptr[0]      = cvtx;
                cgptr->edges = eptr;
                if (COARSEN_EWGTS)
                {
                    cgptr->ewgts = ewptr;
                }
                else
                {
                    cgptr->ewgts = null;
                }

                ewgt_sum = 0;
                for (i = cv2v_ptrs[cvtx + 1] - cv2v_ptrs[cvtx]; i != 0; i--)
                {
                    vtx = *sptr++;

                    iptr = graph[vtx]->edges;
                    if (useEdgeWeights)
                    {
                        fptr = graph[vtx]->ewgts;
                    }

                    for (j = graph[vtx]->nedges - 1; j != 0; j--)
                    {
                        neighbor  = *(++iptr);
                        cneighbor = v2cv[neighbor];
                        if (cneighbor != cvtx)
                        {
                            if (useEdgeWeights)
                            {
                                ewgt = *(++fptr);
                            }

                            ewgt_sum += ewgt;

                            /* Seenflags being used as map from cvtx to index. */
                            if (seenflag[cneighbor] == 0)
                            {
                                /* New neighbor. */
                                cgptr->edges[nseen] = cneighbor;
                                if (COARSEN_EWGTS)
                                {
                                    cgptr->ewgts[nseen] = ewgt;
                                }

                                seenflag[cneighbor] = nseen++;
                            }
                            else
                            {
                                /* Already seen neighbor. */
                                if (COARSEN_EWGTS)
                                {
                                    cgptr->ewgts[seenflag[cneighbor]] += ewgt;
                                }
                            }
                        }
                        else if (useEdgeWeights)
                        {
                            ++fptr;
                        }
                    }
                }

                /* Now clear the seenflag values. */
                iptr = cgptr->edges;
                for (j = nseen - 1; j != 0; j--)
                {
                    seenflag[*(++iptr)] = 0;
                }

                if (COARSEN_EWGTS)
                {
                    cgptr->ewgts[0] = (float)-ewgt_sum;
                }

                /* Increment pointers into edges list. */
                cgptr->nedges = nseen;
                eptr         += nseen;
                if (COARSEN_EWGTS)
                {
                    ewptr += nseen;
                }

                cnedges += nseen - 1;
            }

            Marshal.FreeHGlobal((IntPtr)seenflag);

            /* Form new vertex weights by adding those from contracted edges. */
            if (COARSEN_VWGTS)
            {
                gptr = graph;
                for (i = 1; i <= nvtxs; i++)
                {
                    cgraph[v2cv[i]]->vwgt += (*(++gptr))->vwgt;
                }
            }

            /* Reduce arrays to actual sizes */
            cnedges /= 2;
            size     = 2 * cnedges + cnvtxs;
            eptr     = edges;
            edges    = (int *)Marshal.ReAllocHGlobal((IntPtr)edges, (IntPtr)(size * sizeof(int)));
            if (eptr != edges)
            {
                /* Need to reset pointers in graph. */
                for (i = 1; i <= cnvtxs; i++)
                {
                    cgraph[i]->edges = edges;
                    edges           += cgraph[i]->nedges;
                }
            }

            if (COARSEN_EWGTS)
            {
                ewptr    = eweights;
                eweights = (float *)Marshal.ReAllocHGlobal((IntPtr)eweights, (IntPtr)(size * sizeof(float)));
                if (ewptr != eweights)
                {
                    /* Need to reset pointers in graph. */
                    for (i = 1; i <= cnvtxs; i++)
                    {
                        cgraph[i]->ewgts = eweights;
                        eweights        += cgraph[i]->nedges;
                    }
                }
            }

            /* If desired, make new vtx coordinates = center-of-mass of their parents. */
            if (coords != null && ccoords != null && igeom > 0)
            {
                makeccoords(graph, cnvtxs, cv2v_ptrs, cv2v_vals, igeom, coords, ccoords);
            }

            *pcnedges = cnedges;

            Marshal.FreeHGlobal((IntPtr)cv2v_ptrs);
            Marshal.FreeHGlobal((IntPtr)cv2v_vals);

            if (DEBUG_COARSEN)
            {
                Trace.WriteLine($" Coarse graph has {cnvtxs:D} vertices and {cnedges:D} edges");
            }

            make_cgraph_time += seconds() - time;
        }