Exemplo n.º 1
0
/* Once, or iteratively? */

        public static void coarsen_klv(
            /* Coarsen until nvtxs < vmax, compute and uncoarsen. */
            vtx_data **graph,              /* array of vtx data for graph */
            int nvtxs,                     /* number of vertices in graph */
            int nedges,                    /* number of edges in graph */
            bool using_vwgts,              /* are vertices weights being used? */
            bool useEdgeWeights,           /* are edge weights being used? */
            float *[]           term_wgts, /* weights for terminal propagation */
            int igeom,                     /* dimension for geometric information */
            float **coords,                /* coordinates for vertices */
            int vwgt_max,                  /* largest vertex weight */
            int *assignment,               /* processor each vertex gets assigned to */
            double []          goal,       /* desired set sizes */
            int architecture,              /* 0 => hypercube, d => d-dimensional mesh */
            int [][] hops,                 /* cost of edge between sets */
            LanczosType solver_flag,       /* which eigensolver to use */
            int ndims,                     /* number of eigenvectors to calculate */
            int nsets,                     /* number of sets being divided into */
            int vmax,                      /* largest subgraph to stop coarsening */
            MappingType mediantype,        /* flag for different assignment strategies */
            bool mkconnected,              /* enforce connectivity before eigensolve? */
            double eigtol,                 /* tolerance in eigen calculation */
            int nstep,                     /* number of coarsenings between RQI steps */
            int step,                      /* current step number */
            int **pbndy_list,              /* pointer to returned boundary list */
            double[] weights,              /* weights of vertices in each set */
            bool give_up                   /* has coarsening bogged down? */
            )
        {
            vtx_data **cgraph = null;                       /* array of vtx data for coarsened graph */

            double[]  new_goal = new double[MAXSETS];       /* new goal if not using vertex weights */
            double [] real_goal;                            /* chooses between goal and new_goal */
            double    total_weight;                         /* total weight of vertices */
            double    goal_weight;                          /* total weight of vertices in goal */

            float *[] cterm_wgts    = new float *[MAXSETS]; /* terminal weights for coarse graph */
            float *[] new_term_wgts = new float *[MAXSETS]; /* modified for Bui's method */
            float *[] real_term_wgts;                       /* which of previous two to use */
            float     ewgt_max;                             /* largest edge weight in graph */
            float *   twptr      = null;                    /* loops through term_wgts */
            float *   twptr_save = null;                    /* copy of twptr */
            float *   ctwptr;                               /* loops through cterm_wgts */
            float **  ccoords;                              /* coarse graph coordinates */
            int *     v2cv = null;                          /* mapping from vtxs to coarse vtxs */
            bool *    flag;                                 /* scatter array for coarse bndy vtxs */
            int *     bndy_list;                            /* list of vertices on boundary */
            int *     cbndy_list = null;                    /* list of vertices of coarse graph on boundary */
            int *     cassignment;                          /* set assignments for coarsened vertices */
            bool      flattened;                            /* was this graph flattened? */
            int       list_length;                          /* length of boundary vtx list */
            int       cnvtxs  = 0;                          /* number of vertices in coarsened graph */
            int       cnedges = 0;                          /* number of edges in coarsened graph */
            int       cvwgt_max;                            /* largest vertex weight in coarsened graph */
            int       nextstep;                             /* next step in RQI test */
            int       max_dev;                              /* largest allowed deviation from balance */
            int       i, j;                                 /* loop counters */

            if (DEBUG_COARSEN || DEBUG_TRACE)
            {
                Trace.WriteLine($"<Entering coarsen_kl, {nameof(step)}={step:d}, {nameof(nvtxs)}={nvtxs:d}, {nameof(nedges)}={nedges:d}, {nameof(vmax)}={vmax:d}>\n");
            }

            /* Is problem small enough to solve? */
            if (nvtxs <= vmax || give_up)
            {
                real_goal = goal;

                simple_part(graph, nvtxs, assignment, nsets, MappingType.MinCost, real_goal);
                list_length = find_bndy(graph, nvtxs, assignment, 2, &bndy_list);

                count_weights(graph, nvtxs, assignment, nsets + 1, weights, true);

                max_dev      = (step == 0) ? vwgt_max : 5 * vwgt_max;
                total_weight = 0;
                for (i = 0; i < nsets; i++)
                {
                    total_weight += real_goal[i];
                }

                if (max_dev > total_weight)
                {
                    max_dev = vwgt_max;
                }
                goal_weight = total_weight * KL_IMBALANCE / nsets;
                if (goal_weight > max_dev)
                {
                    max_dev = (int)goal_weight;
                }

                if (COARSE_KLV)
                {
                    klvspiff(graph, nvtxs, assignment, real_goal, max_dev, &bndy_list, weights);
                }
                if (COARSE_BPM)
                {
                    bpm_improve(graph, assignment, real_goal, max_dev, &bndy_list, weights, using_vwgts);
                }
                *pbndy_list = bndy_list;
                return;
            }

            /* Otherwise I have to coarsen. */
            flattened = false;
            if (coords != null)
            {
                ccoords = (float **)Marshal.AllocHGlobal(igeom * sizeof(float *));
            }
            else
            {
                ccoords = null;
            }
            if (FLATTEN && step == 0)
            {
                flattened = flatten(graph, nvtxs, nedges, &cgraph, &cnvtxs, &cnedges, &v2cv,
                                    useEdgeWeights && COARSEN_EWGTS, igeom, coords, ccoords);
            }
            if (!flattened)
            {
                coarsen1(graph, nvtxs, nedges, &cgraph, &cnvtxs, &cnedges, &v2cv, igeom, coords, ccoords,
                         useEdgeWeights && COARSEN_EWGTS);
            }

            if (term_wgts[1] != null)
            {
                twptr      = (float *)Marshal.AllocHGlobal((cnvtxs + 1) * (nsets - 1) * sizeof(float));
                twptr_save = twptr;
                for (i = (cnvtxs + 1) * (nsets - 1); i != 0; i--)
                {
                    *twptr++ = 0;
                }
                twptr = twptr_save;
                for (j = 1; j < nsets; j++)
                {
                    cterm_wgts[j] = twptr;
                    twptr        += cnvtxs + 1;
                }
                for (j = 1; j < nsets; j++)
                {
                    ctwptr = cterm_wgts[j];
                    twptr  = term_wgts[j];
                    for (i = 1; i < nvtxs; i++)
                    {
                        ctwptr[v2cv[i]] += twptr[i];
                    }
                }
            }

            else
            {
                cterm_wgts[1] = null;
            }

            /* If coarsening isn't working very well, give up and partition. */
            give_up = false;
            if (nvtxs * COARSEN_RATIO_MIN < cnvtxs && cnvtxs > vmax && !flattened)
            {
                Trace.WriteLine($"WARNING: Coarsening not making enough progress, {nameof(nvtxs)} = {nvtxs:d}, {nameof(cnvtxs)} = {cnvtxs:d}.");
                Trace.WriteLine("         Recursive coarsening being stopped prematurely.");
                give_up = true;
            }

            /* Now recurse on coarse subgraph. */
            if (COARSEN_VWGTS)
            {
                cvwgt_max = 0;
                for (i = 1; i <= cnvtxs; i++)
                {
                    if (cgraph[i]->vwgt > cvwgt_max)
                    {
                        cvwgt_max = cgraph[i]->vwgt;
                    }
                }
            }

            else
            {
                cvwgt_max = 1;
            }

            cassignment = (int *)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(int));
            if (flattened)
            {
                nextstep = step;
            }
            else
            {
                nextstep = step + 1;
            }
            coarsen_klv(cgraph, cnvtxs, cnedges, COARSEN_VWGTS, COARSEN_EWGTS, cterm_wgts, igeom, ccoords,
                        cvwgt_max, cassignment, goal, architecture, hops, solver_flag, ndims, nsets, vmax,
                        mediantype, mkconnected, eigtol, nstep, nextstep, &cbndy_list, weights, give_up);

            /* Interpolate assignment back to fine graph. */
            for (i = 1; i <= nvtxs; i++)
            {
                assignment[i] = cassignment[v2cv[i]];
            }

            /* Construct boundary list from coarse boundary list. */
            flag = (bool *)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(bool));
            for (i = 1; i <= cnvtxs; i++)
            {
                flag[i] = false;
            }
            for (i = 0; cbndy_list[i] != 0; i++)
            {
                flag[cbndy_list[i]] = true;
            }

            list_length = 0;
            for (i = 1; i <= nvtxs; i++)
            {
                if (flag[v2cv[i]])
                {
                    ++list_length;
                }
            }

            bndy_list = (int *)Marshal.AllocHGlobal((list_length + 1) * sizeof(int));

            list_length = 0;
            for (i = 1; i <= nvtxs; i++)
            {
                if (flag[v2cv[i]])
                {
                    bndy_list[list_length++] = i;
                }
            }
            bndy_list[list_length] = 0;

            Marshal.FreeHGlobal((IntPtr)flag);
            Marshal.FreeHGlobal((IntPtr)cbndy_list);

            /* Free the space that was allocated. */
            Marshal.FreeHGlobal((IntPtr)cassignment);
            if (twptr_save != null)
            {
                Marshal.FreeHGlobal((IntPtr)twptr_save);
                twptr_save = null;
            }
            free_graph(cgraph);
            Marshal.FreeHGlobal((IntPtr)v2cv);

            /* Smooth using KL or BPM every nstep steps. */
            if ((step % nstep) == 0 && !flattened)
            {
                if (!COARSEN_VWGTS && step != 0) /* Construct new goal */
                {
                    goal_weight = 0;
                    for (i = 0; i < nsets; i++)
                    {
                        goal_weight += goal[i];
                    }
                    for (i = 0; i < nsets; i++)
                    {
                        new_goal[i] = goal[i] * (nvtxs / goal_weight);
                    }
                    real_goal = new_goal;
                }
                else
                {
                    real_goal = goal;
                }

                if (LIMIT_KL_EWGTS)
                {
                    find_maxdeg(graph, nvtxs, useEdgeWeights, &ewgt_max);
                    compress_ewgts(graph, nvtxs, nedges, ewgt_max, useEdgeWeights);
                }

                /* If not coarsening ewgts, then need care with term_wgts. */
                if (!useEdgeWeights && term_wgts[1] != null && step != 0)
                {
                    twptr      = (float *)Marshal.AllocHGlobal((nvtxs + 1) * (nsets - 1) * sizeof(float));
                    twptr_save = twptr;
                    for (j = 1; j < nsets; j++)
                    {
                        new_term_wgts[j] = twptr;
                        twptr           += nvtxs + 1;
                    }

                    for (j = 1; j < nsets; j++)
                    {
                        twptr  = term_wgts[j];
                        ctwptr = new_term_wgts[j];
                        for (i = 1; i <= nvtxs; i++)
                        {
                            if (twptr[i] > .5)
                            {
                                ctwptr[i] = 1;
                            }
                            else if (twptr[i] < -.5)
                            {
                                ctwptr[i] = -1;
                            }
                            else
                            {
                                ctwptr[i] = 0;
                            }
                        }
                    }
                    real_term_wgts = new_term_wgts;
                }
                else
                {
                    real_term_wgts   = term_wgts;
                    new_term_wgts[1] = null;
                }

                max_dev      = (step == 0) ? vwgt_max : 5 * vwgt_max;
                total_weight = 0;
                for (i = 0; i < nsets; i++)
                {
                    total_weight += real_goal[i];
                }
                if (max_dev > total_weight)
                {
                    max_dev = vwgt_max;
                }
                goal_weight = total_weight * KL_IMBALANCE / nsets;
                if (goal_weight > max_dev)
                {
                    max_dev = (int)goal_weight;
                }

                if (!COARSEN_VWGTS)
                {
                    count_weights(graph, nvtxs, assignment, nsets + 1, weights, (vwgt_max != 1));
                }

                if (COARSE_KLV)
                {
                    klvspiff(graph, nvtxs, assignment, real_goal, max_dev, &bndy_list, weights);
                }
                if (COARSE_BPM)
                {
                    bpm_improve(graph, assignment, real_goal, max_dev, &bndy_list, weights, using_vwgts);
                }

                if (real_term_wgts != term_wgts && new_term_wgts[1] != null)
                {
                    Marshal.FreeHGlobal((IntPtr)real_term_wgts[1]);
                }

                if (LIMIT_KL_EWGTS)
                {
                    restore_ewgts(graph, nvtxs);
                }
            }

            *pbndy_list = bndy_list;

            if (twptr_save != null)
            {
                Marshal.FreeHGlobal((IntPtr)twptr_save);
            }

            /* Free the space that was allocated. */
            if (ccoords != null)
            {
                for (i = 0; i < igeom; i++)
                {
                    Marshal.FreeHGlobal((IntPtr)ccoords[i]);
                }
                Marshal.FreeHGlobal((IntPtr)ccoords);
            }

            if (DEBUG_COARSEN)
            {
                Trace.WriteLine($" Leaving coarsen_klv, {nameof(step)}={step:d}");
            }
        }
Exemplo n.º 2
0
        public static void coarsen(
            /* Coarsen until nvtxs <= vmax, compute and uncoarsen. */
            vtx_data **graph,        /* array of vtx data for graph */
            int nvtxs,               /* number of vertices in graph */
            int nedges,              /* number of edges in graph */
            bool using_vwgts,        /* are vertices weights being used? */
            bool useEdgeWeights,     /* are edge weights being used? */
            float *[] term_wgts,     /* terminal weights */
            int igeom,               /* dimension for geometric information */
            float **coords,          /* coordinates for vertices */
            double *[] yvecs,        /* eigenvectors returned */
            int ndims,               /* number of eigenvectors to calculate */
            LanczosType solver_flag, /* which eigensolver to use */
            int vmax,                /* largest subgraph to stop coarsening */
            double eigtol,           /* tolerance in eigen calculation */
            int nstep,               /* number of coarsenings between RQI steps */
            int step,                /* current step number */
            bool give_up             /* has coarsening bogged down? */
            )
        {
            vtx_data **cgraph;                              /* array of vtx data for coarsened graph */
            orthlink * orthlist;                            /* list of lower evecs to suppress */
            orthlink * newlink;                             /* lower evec to suppress */

            double *[] cyvecs = new double *[MAXDIMS + 1];  /* eigenvectors for subgraph */
            double[]   evals  = new double[MAXDIMS + 1];    /* eigenvalues returned */
            double[]   goal   = new double[MAXSETS];        /* needed for convergence mode = 1 */
            double *   r1;                                  /* space needed by symmlq/RQI */
            double *   r2;                                  /* space needed by symmlq/RQI */
            double *   work;                                /* space needed by symmlq/RQI */
            double *   v;                                   /* space needed by symmlq/RQI */
            double *   w;                                   /* space needed by symmlq/RQI */
            double *   x;                                   /* space needed by symmlq/RQI */
            double *   y;                                   /* space needed by symmlq/RQI */
            double *   gvec;                                /* rhs vector in extended eigenproblem */
            double     evalest;                             /* eigenvalue estimate returned by RQI */
            double     maxdeg;                              /* maximum weighted degree of a vertex */
            float **   ccoords;                             /* coordinates for coarsened graph */

            float *[] cterm_wgts    = new float *[MAXSETS]; /* coarse graph terminal weights */
            float *[] new_term_wgts = new float *[MAXSETS]; /* terminal weights for Bui's method*/
            float *[] real_term_wgts;                       /* one of the above */
            float *   twptr      = null;                    /* loops through term_wgts */
            float *   twptr_save = null;                    /* copy of twptr */
            float *   ctwptr;                               /* loops through cterm_wgts */
            double *  vwsqrt = null;                        /* square root of vertex weights */
            double    norm, alpha;                          /* values used for orthogonalization */
            double    initshift;                            /* initial shift for RQI */
            double    total_vwgt;                           /* sum of all the vertex weights */
            double    w1, w2;                               /* weights of two sets */
            double    term_tot;                             /* sum of all terminal weights */
            int *     space;                                /* room for assignment in Lanczos */
            int *     morespace;                            /* room for assignment in Lanczos */
            int *     v2cv;                                 /* mapping from vertices to coarse vtxs */
            int       vwgt_max;                             /* largest vertex weight */
            bool      oldperturb;                           /* saves PERTURB value */
            int       cnvtxs;                               /* number of vertices in coarsened graph */
            int       cnedges;                              /* number of edges in coarsened graph */
            int       nextstep;                             /* next step in RQI test */
            int       nsets;                                /* number of sets being created */
            int       i, j;                                 /* loop counters */
            double    time;                                 /* time marker */

            if (DEBUG_COARSEN)
            {
                Trace.WriteLine($"<Entering coarsen, {nameof(step)}={step:D}, {nameof(nvtxs)}={nvtxs:D}, {nameof(nedges)}={nedges:D}, {nameof(vmax)}={vmax:D}>\n");
            }

            nsets = 1 << ndims;

            /* Is problem small enough to solve? */
            if (nvtxs <= vmax || give_up)
            {
                if (using_vwgts)
                {
                    vwsqrt = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));
                    makevwsqrt(vwsqrt, graph, nvtxs);
                }
                else
                {
                    vwsqrt = null;
                }

                maxdeg = find_maxdeg(graph, nvtxs, useEdgeWeights, null);

                if (using_vwgts)
                {
                    vwgt_max   = 0;
                    total_vwgt = 0;
                    for (i = 1; i <= nvtxs; i++)
                    {
                        if (graph[i]->vwgt > vwgt_max)
                        {
                            vwgt_max = graph[i]->vwgt;
                        }

                        total_vwgt += graph[i]->vwgt;
                    }
                }
                else
                {
                    vwgt_max   = 1;
                    total_vwgt = nvtxs;
                }

                for (i = 0; i < nsets; i++)
                {
                    goal[i] = total_vwgt / nsets;
                }

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

                /* If not coarsening ewgts, then need care with term_wgts. */
                if (!useEdgeWeights && term_wgts[1] != null && step != 0)
                {
                    twptr      = (float *)Marshal.AllocHGlobal((nvtxs + 1) * (nsets - 1) * sizeof(float));
                    twptr_save = twptr;
                    for (j = 1; j < nsets; j++)
                    {
                        new_term_wgts[j] = twptr;
                        twptr           += nvtxs + 1;
                    }

                    for (j = 1; j < nsets; j++)
                    {
                        twptr  = term_wgts[j];
                        ctwptr = new_term_wgts[j];
                        for (i = 1; i <= nvtxs; i++)
                        {
                            if (twptr[i] > .5)
                            {
                                ctwptr[i] = 1;
                            }
                            else if (twptr[i] < -.5)
                            {
                                ctwptr[i] = -1;
                            }
                            else
                            {
                                ctwptr[i] = 0;
                            }
                        }
                    }

                    real_term_wgts = new_term_wgts;
                }
                else
                {
                    real_term_wgts   = term_wgts;
                    new_term_wgts[1] = null;
                }

                eigensolve(graph, nvtxs, nedges, maxdeg, vwgt_max, vwsqrt, using_vwgts, useEdgeWeights,
                           real_term_wgts, igeom, coords, yvecs, evals, false, space, goal, solver_flag, false, 0,
                           ndims, MappingType.IndependantMedians, eigtol);

                if (real_term_wgts != term_wgts && new_term_wgts[1] != null)
                {
                    Marshal.FreeHGlobal((IntPtr)real_term_wgts[1]);
                }

                Marshal.FreeHGlobal((IntPtr)space);
                space = null;
                Marshal.FreeHGlobal((IntPtr)vwsqrt);
                vwsqrt = null;
                Marshal.FreeHGlobal((IntPtr)twptr_save);
                twptr_save = null;
                return;
            }

            /* Otherwise I have to coarsen. */
            if (coords != null)
            {
                ccoords = (float **)Marshal.AllocHGlobal(igeom * sizeof(float *));
            }
            else
            {
                ccoords = null;
            }

            coarsen1(graph, nvtxs, nedges, &cgraph, &cnvtxs, &cnedges, &v2cv, igeom, coords, ccoords, useEdgeWeights);

            /* If coarsening isn't working very well, give up and partition. */
            give_up = false;
            if (nvtxs * COARSEN_RATIO_MIN < cnvtxs && cnvtxs > vmax)
            {
                Trace.WriteLine($"WARNING: Coarsening not making enough progress, {nameof(nvtxs)} = {nvtxs:d}, {nameof(cnvtxs)} = {cnvtxs:d}.");
                Trace.WriteLine("         Recursive coarsening being stopped prematurely.");
                give_up = true;
            }

            /* Create space for subgraph yvecs. */
            for (i = 1; i <= ndims; i++)
            {
                cyvecs[i] = (double *)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(double));
            }

            /* Make coarse version of terminal weights. */
            if (term_wgts[1] != null)
            {
                twptr      = (float *)Marshal.AllocHGlobal((cnvtxs + 1) * (nsets - 1) * sizeof(float));
                twptr_save = twptr;
                for (i = (cnvtxs + 1) * (nsets - 1); i != 0; i--)
                {
                    *twptr++ = 0;
                }

                twptr = twptr_save;
                for (j = 1; j < nsets; j++)
                {
                    cterm_wgts[j] = twptr;
                    twptr        += cnvtxs + 1;
                }

                for (j = 1; j < nsets; j++)
                {
                    ctwptr = cterm_wgts[j];
                    twptr  = term_wgts[j];
                    for (i = 1; i < nvtxs; i++)
                    {
                        ctwptr[v2cv[i]] += twptr[i];
                    }
                }
            }
            else
            {
                cterm_wgts[1] = null;
            }

            /* Now recurse on coarse subgraph. */
            nextstep = step + 1;
            coarsen(cgraph, cnvtxs, cnedges, COARSEN_VWGTS, COARSEN_EWGTS, cterm_wgts, igeom, ccoords, cyvecs,
                    ndims, solver_flag, vmax, eigtol, nstep, nextstep, give_up);

            ch_interpolate(yvecs, cyvecs, ndims, graph, nvtxs, v2cv, useEdgeWeights);

            Marshal.FreeHGlobal((IntPtr)twptr_save);
            twptr_save = null;
            Marshal.FreeHGlobal((IntPtr)v2cv);
            v2cv = null;

            /* I need to do Rayleigh Quotient Iteration each nstep stages. */
            time = seconds();
            if ((step % nstep) == 0)
            {
                oldperturb = PERTURB;
                PERTURB    = false;
                /* Should I do some orthogonalization here against vwsqrt? */
                if (using_vwgts)
                {
                    vwsqrt = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));
                    makevwsqrt(vwsqrt, graph, nvtxs);

                    for (i = 1; i <= ndims; i++)
                    {
                        orthogvec(yvecs[i], 1, nvtxs, vwsqrt);
                    }
                }
                else
                {
                    for (i = 1; i <= ndims; i++)
                    {
                        orthog1(yvecs[i], 1, nvtxs);
                    }
                }

                /* Allocate space that will be needed in RQI. */
                r1   = (double *)Marshal.AllocHGlobal(7 * (nvtxs + 1) * sizeof(double));
                r2   = &r1[nvtxs + 1];
                v    = &r1[2 * (nvtxs + 1)];
                w    = &r1[3 * (nvtxs + 1)];
                x    = &r1[4 * (nvtxs + 1)];
                y    = &r1[5 * (nvtxs + 1)];
                work = &r1[6 * (nvtxs + 1)];

                if (using_vwgts)
                {
                    vwgt_max   = 0;
                    total_vwgt = 0;
                    for (i = 1; i <= nvtxs; i++)
                    {
                        if (graph[i]->vwgt > vwgt_max)
                        {
                            vwgt_max = graph[i]->vwgt;
                        }

                        total_vwgt += graph[i]->vwgt;
                    }
                }
                else
                {
                    vwgt_max   = 1;
                    total_vwgt = nvtxs;
                }

                for (i = 0; i < nsets; i++)
                {
                    goal[i] = total_vwgt / nsets;
                }

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

                initshift = 0;
                orthlist  = null;
                for (i = 1; i < ndims; i++)
                {
                    ch_normalize(yvecs[i], 1, nvtxs);
                    rqi(graph, yvecs, i, nvtxs, r1, r2, v, w, x, y, work, eigtol, initshift, &evalest, vwsqrt,
                        orthlist, false, nsets, space, morespace, MappingType.IndependantMedians, goal, vwgt_max, ndims);

                    /* Now orthogonalize higher yvecs against this one. */
                    norm = dot(yvecs[i], 1, nvtxs, yvecs[i]);
                    for (j = i + 1; j <= ndims; j++)
                    {
                        alpha = -dot(yvecs[j], 1, nvtxs, yvecs[i]) / norm;
                        scadd(yvecs[j], 1, nvtxs, alpha, yvecs[i]);
                    }

                    /* Now prepare for next pass through loop. */
                    initshift     = evalest;
                    newlink       = makeorthlnk();
                    newlink->vec  = yvecs[i];
                    newlink->pntr = orthlist;
                    orthlist      = newlink;
                }

                ch_normalize(yvecs[ndims], 1, nvtxs);

                if (term_wgts[1] != null && ndims == 1)
                {
                    /* Solve extended eigen problem */

                    /* If not coarsening ewgts, then need care with term_wgts. */
                    if (!useEdgeWeights && term_wgts[1] != null && step != 0)
                    {
                        twptr      = (float *)Marshal.AllocHGlobal((nvtxs + 1) * (nsets - 1) * sizeof(float));
                        twptr_save = twptr;
                        for (j = 1; j < nsets; j++)
                        {
                            new_term_wgts[j] = twptr;
                            twptr           += nvtxs + 1;
                        }

                        for (j = 1; j < nsets; j++)
                        {
                            twptr  = term_wgts[j];
                            ctwptr = new_term_wgts[j];
                            for (i = 1; i <= nvtxs; i++)
                            {
                                if (twptr[i] > .5)
                                {
                                    ctwptr[i] = 1;
                                }
                                else if (twptr[i] < -.5)
                                {
                                    ctwptr[i] = -1;
                                }
                                else
                                {
                                    ctwptr[i] = 0;
                                }
                            }
                        }

                        real_term_wgts = new_term_wgts;
                    }
                    else
                    {
                        real_term_wgts   = term_wgts;
                        new_term_wgts[1] = null;
                    }

                    /* Following only works for bisection. */
                    w1       = goal[0];
                    w2       = goal[1];
                    gvec     = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));
                    term_tot = 0;
                    for (j = 1; j <= nvtxs; j++)
                    {
                        term_tot += (real_term_wgts[1])[j];
                    }

                    term_tot /= (w1 + w2);
                    if (using_vwgts)
                    {
                        for (j = 1; j <= nvtxs; j++)
                        {
                            gvec[j] = (real_term_wgts[1])[j] / graph[j]->vwgt - term_tot;
                        }
                    }
                    else
                    {
                        for (j = 1; j <= nvtxs; j++)
                        {
                            gvec[j] = (real_term_wgts[1])[j] - term_tot;
                        }
                    }

                    rqi_ext();

                    Marshal.FreeHGlobal((IntPtr)gvec);
                    gvec = null;
                    if (real_term_wgts != term_wgts && new_term_wgts[1] != null)
                    {
                        Marshal.FreeHGlobal((IntPtr)new_term_wgts[1]);
                        new_term_wgts[1] = null;
                    }
                }
                else
                {
                    rqi(graph, yvecs, ndims, nvtxs, r1, r2, v, w, x, y, work, eigtol, initshift, &evalest, vwsqrt,
                        orthlist, false, nsets, space, morespace, MappingType.IndependantMedians, goal, vwgt_max, ndims);
                }

                refine_time += seconds() - time;

                /* Free the space allocated for RQI. */
                Marshal.FreeHGlobal((IntPtr)morespace);
                Marshal.FreeHGlobal((IntPtr)space);
                while (orthlist != null)
                {
                    newlink = orthlist->pntr;
                    Marshal.FreeHGlobal((IntPtr)orthlist);
                    orthlist = newlink;
                }

                Marshal.FreeHGlobal((IntPtr)r1);
                Marshal.FreeHGlobal((IntPtr)vwsqrt);
                vwsqrt  = null;
                PERTURB = oldperturb;
            }

            if (DEBUG_COARSEN)
            {
                Trace.WriteLine($" Leaving coarsen, {nameof(step)}={step:d}");
            }

            Marshal.FreeHGlobal((IntPtr)twptr_save);
            twptr_save = null;

            /* Free the space that was allocated. */
            if (ccoords != null)
            {
                for (i = 0; i < igeom; i++)
                {
                    Marshal.FreeHGlobal((IntPtr)ccoords[i]);
                }

                Marshal.FreeHGlobal((IntPtr)ccoords);
            }

            for (i = ndims; i > 0; i--)
            {
                Marshal.FreeHGlobal((IntPtr)cyvecs[i]);
            }

            free_graph(cgraph);
        }
Exemplo n.º 3
0
        /* Invoke the eigenvector calculation */
        public static void eigensolve(vtx_data **graph,        /* graph data structure */
                                      int nvtxs,               /* number of vertices in graph */
                                      int nedges,              /* number of edges in graph */
                                      double maxdeg,           /* largest (weighted) degree of a vertex */
                                      int vwgt_max,            /* largest vertex weight */
                                      double *vwsqrt,          /* sqrt of vertex weights (length nvtxs+1) */
                                      bool using_vwgts,        /* are vertex weights being used? */
                                      bool useEdgeWeights,     /* are edge weights being used? */
                                      float *[] term_wgts,     /* terminal propagation weight vector */
                                      int igeom,               /* geometric dimensionality if given coords */
                                      float **coords,          /* coordinates of vertices */
                                      double *[] yvecs,        /* space for pointing to eigenvectors */
                                      double[] evals,          /* eigenvalues associated with eigenvectors */
                                      bool architecture,       /* 0 => hypercube, d => d-dimensional mesh */
                                      int *assignment,         /* set number of each vtx (length n+1) */
                                      double[] goal,           /* desired set sizes */
                                      LanczosType solver_flag, /* flag indicating which solver to use */
                                      bool rqi_flag,           /* use multi-level techniques? */
                                      int vmax,                /* if so, how many vtxs to coarsen down to? */
                                      int ndims,               /* number of eigenvectors (2^d sets) */
                                      MappingType mediantype,  /* which partitioning strategy to use */
                                      double eigtol            /* tolerance on eigenvectors */
                                      )
        {
            double[] bound = new double[MAXDIMS + 1]; /* ritz approx bounds to eigenpairs */
            double   time;                            /* time marker */

            float *[] dummy_twgt = new float *[2];    /* turns off terminal propagation */
            float *   twptr;                          /* terminal propagation weight vector */
            int *     active;                         /* space for nvtxs values */
            int       step;                           /* current step in RQI counting */
            int       nstep;                          /* number of uncoarsening levels between RQIs */
            int       version;                        /* which version of sel. orth. to use */
            int       nsets = 0;                      /* number of sets to divide into */
            double *  g;                              /* rhs n-vector in the extended eigenproblem */
            double *  ptr;                            /* loops through yvec */
            double    w1, w2;                         /* desired weights of two sets */
            double    term_tot;                       /* sum of terminal weights */
            double    sigma;                          /* norm constraint on extended eigenvector */
            int       i, j;                           /* loop counter */
            bool      normal;                         /* use normal or extended eigensolver? */
            bool      autoset_maxitns;                /* set LANCZOS_MAXITNS automatically? */
            int       prev_maxitns = 0;               /* LANCZOS_MAXITNS value above this routine */
            bool      autoset_srestol;                /* set SRESTOL automatically? */
            double    prev_srestol = 0;               /* SRESTOL value above this routine */

            if (DEBUG_TRACE)
            {
                Trace.WriteLine($"<Entering eigensolve, nvtxs = {nvtxs:d}, nedges ={nedges:d}>\n");
            }

            if (nvtxs <= ndims)
            {
                /* Pathological special case. */
                for (i = 1; i <= ndims; i++)
                {
                    for (j = 1; j <= nvtxs; j++)
                    {
                        yvecs[i][j] = 0;
                    }
                }

                return;
            }

            active = null;

            /* Autoset (if necessary) some parameters for the eigen calculation */
            autoset_maxitns = false;
            autoset_srestol = false;
            if (LANCZOS_MAXITNS < 0)
            {
                autoset_maxitns = true;
                prev_maxitns    = LANCZOS_MAXITNS;
                LANCZOS_MAXITNS = 2 * nvtxs;
            }

            if (SRESTOL < 0)
            {
                autoset_srestol = true;
                prev_srestol    = SRESTOL;
                SRESTOL         = eigtol * eigtol;
            }

            /* Note: When (if ever) rqi_ext is done, change precedence of eigensolvers. */

            if (term_wgts[1] != null && ndims == 1)
            {
                /* then use lanczos_ext */
                if (PERTURB)
                {
                    if (NPERTURB > 0 && PERTURB_MAX > 0.0)
                    {
                        perturb_init(nvtxs);
                        if (DEBUG_PERTURB)
                        {
                            Trace.WriteLine($"Matrix being perturbed with scale {PERTURB_MAX:E}\n");
                        }
                    }
                    else if (DEBUG_PERTURB)
                    {
                        Trace.WriteLine("Matrix not being perturbed\n");
                    }
                }

                version = 2;
                if (LANCZOS_CONVERGENCE_MODE == 1)
                {
                    active = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
                }

                w1    = goal[0];
                w2    = goal[1];
                sigma = Math.Sqrt(4 * w1 * w2 / (w1 + w2));
                g     = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));

                twptr    = term_wgts[1];
                term_tot = 0;
                for (i = 1; i <= nvtxs; i++)
                {
                    term_tot += twptr[i];
                }

                term_tot /= (w1 + w2);
                if (using_vwgts)
                {
                    for (i = 1; i <= nvtxs; i++)
                    {
                        g[i] = twptr[i] / graph[i]->vwgt - term_tot;
                    }
                }
                else
                {
                    for (i = 1; i <= nvtxs; i++)
                    {
                        g[i] = twptr[i] - term_tot;
                    }
                }

                time = seconds();

                if (LANCZOS_SO_PRECISION == 2)
                {
                    /* double precision */
                    normal = lanczos_ext(graph, nvtxs, ndims, yvecs, eigtol, vwsqrt, maxdeg, version, g, sigma);
                }
                else
                {
                    /* single precision */
                    normal = lanczos_ext_float(graph, nvtxs, ndims, yvecs, eigtol, vwsqrt, maxdeg, version, g, sigma);
                }

                Marshal.FreeHGlobal((IntPtr)g);
                if (active != null)
                {
                    Marshal.FreeHGlobal((IntPtr)(active));
                }

                active = null;

                if (normal)
                {
                    if (WARNING_EVECS > 2)
                    {
                        Trace.WriteLine("WARNING: Not an extended eigenproblem; switching to standard eigensolver.\n");
                    }
                }
                else
                {
                    if (w2 != w1)
                    {
                        if (using_vwgts)
                        {
                            y2x(yvecs, ndims, nvtxs, vwsqrt);
                        }

                        sigma = (w2 - w1) / (w2 + w1);
                        ptr   = yvecs[1];
                        for (i = nvtxs; i != 0; i--)
                        {
                            *(++ptr) += sigma;
                        }

                        /* Note: if assign() could skip scaling, next call unnecessary. */
                        if (using_vwgts)
                        {
                            x2y(yvecs, ndims, nvtxs, vwsqrt);
                        }
                    }
                }

                if (PERTURB && NPERTURB > 0 && PERTURB_MAX > 0.0)
                {
                    perturb_clear();
                }

                lanczos_time += seconds() - time;
            }
            else
            {
                normal = true;
            }

            if (normal)
            {
                if (rqi_flag)
                {
                    /* Solve using multi-level scheme RQI/Symmlq. */
                    time          = seconds();
                    nstep         = COARSE_NLEVEL_RQI;
                    step          = 0;
                    dummy_twgt[1] = null;
                    coarsen(graph, nvtxs, nedges, using_vwgts, useEdgeWeights, dummy_twgt, igeom, coords, yvecs,
                            ndims, solver_flag, vmax, eigtol, nstep, step, false);

                    rqi_symmlq_time += seconds() - time;
                }

                else
                {
                    /* Use standard Lanczos. */
                    if (PERTURB)
                    {
                        if (NPERTURB > 0 && PERTURB_MAX > 0.0)
                        {
                            perturb_init(nvtxs);
                            if (DEBUG_PERTURB)
                            {
                                Trace.WriteLine($"Matrix being perturbed with scale {PERTURB_MAX:E}\n");
                            }
                        }
                        else if (DEBUG_PERTURB)
                        {
                            Trace.WriteLine("Matrix not being perturbed\n");
                        }
                    }

                    if (solver_flag == LanczosType.FullOrthogonalization)
                    {
                        time    = seconds();
                        version = 1;
                        lanczos_FO(graph, nvtxs, ndims, yvecs, evals, bound, eigtol, vwsqrt, maxdeg, version);
                        lanczos_time += seconds() - time;
                    }

                    if (solver_flag == LanczosType.FullOrthogonalizationInverseOperator)
                    {
                        time    = seconds();
                        version = 2;
                        lanczos_FO(graph, nvtxs, ndims, yvecs, evals, bound, eigtol, vwsqrt, maxdeg, version);
                        lanczos_time += seconds() - time;
                    }
                    else if (solver_flag == LanczosType.SelectiveOrthogonalization)
                    {
                        version = 2; /* orthog. against left end only */
                        if (LANCZOS_CONVERGENCE_MODE == 1)
                        {
                            active = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
                        }

                        nsets = 1 << ndims;
                        time  = seconds();
                        if (LANCZOS_SO_PRECISION == 2)
                        {
                            /* double precision */
                            lanczos_SO(graph, nvtxs, ndims, yvecs, evals, bound, eigtol, vwsqrt, maxdeg, version,
                                       architecture, nsets, assignment, active, mediantype, goal, vwgt_max);
                        }
                        else
                        {
                            /* single precision */
                            lanczos_SO_float(graph, nvtxs, ndims, yvecs, evals, bound, eigtol, vwsqrt, maxdeg,
                                             version, architecture, nsets, assignment, active, mediantype, goal,
                                             vwgt_max);
                        }

                        lanczos_time += seconds() - time;
                    }
                    else if (solver_flag == LanczosType.SelectiveOrthogonalizationDoubleEnded)
                    {
                        if (EXPERT)
                        {
                            version = 1; /* orthog. against both ends */
                        }
                        else
                        {
                            /* this should have been caught earlier ... */
                            version = 2;
                        }

                        if (LANCZOS_CONVERGENCE_MODE == 1)
                        {
                            active = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
                        }

                        nsets = 1 << ndims;
                        time  = seconds();
                        if (LANCZOS_SO_PRECISION == 1)
                        {
                            /* Single precision */
                            lanczos_SO_float(graph, nvtxs, ndims, yvecs, evals, bound, eigtol, vwsqrt, maxdeg,
                                             version, architecture, nsets, assignment, active, mediantype, goal,
                                             vwgt_max);
                        }
                        else
                        {
                            /* Double precision */
                            lanczos_SO(graph, nvtxs, ndims, yvecs, evals, bound, eigtol, vwsqrt, maxdeg, version,
                                       architecture, nsets, assignment, active, mediantype, goal, vwgt_max);
                        }

                        lanczos_time += seconds() - time;
                    }
                }

                /*
                 * file = fopen("CHACO.EVECS", "w");
                 * for (i = 1; i <= nvtxs; i++) {
                 * for (j = 1; j <= ndims; j++) {
                 * fprintf(file, "%g ", (yvecs[j])[i]);
                 * }
                 * fprintf(file, "\n");
                 * }
                 * fclose(file);
                 */

                if (PERTURB && NPERTURB > 0 && PERTURB_MAX > 0.0)
                {
                    perturb_clear();
                }
            }

            /* This is an attempt to reduce some machine-to-machine
             * variance. If the first value in the eigenvector is negative,
             * reflect the eigenvector...  This may not be needed following
             * the addition of the standard random number generator in util/random.c
             */
            for (nstep = 1; nstep <= ndims; nstep++)
            {
                vecnorm(yvecs[nstep], 1, nvtxs);
            }

            if (DEBUG_EVECS > 4)
            {
                for (nstep = 1; nstep <= ndims; nstep++)
                {
                    vecout(yvecs[nstep], 1, nvtxs, "Eigenvector", null);
                }
            }

            /* Auto-reset (if necessary) some parameters for the eigen calculation */
            if (autoset_maxitns)
            {
                LANCZOS_MAXITNS = prev_maxitns;
            }

            if (autoset_srestol)
            {
                SRESTOL = prev_srestol;
            }

            if (active != null)
            {
                Marshal.FreeHGlobal((IntPtr)active);
            }

            if (DEBUG_TRACE)
            {
                Trace.WriteLine("<Leaving eigensolve>\n");
            }
        }
Exemplo n.º 4
0
/* JPS END */

        public static void sequence(
            vtx_data **graph,          /* graph data structure */
            int nvtxs,                 /* number of vertices in graph */
            int nedges,                /* number of edges in graph */
            bool useEdgeWeights,       /* are edge weights being used? */
            double *sqrtVertexWeights, /* sqrt of vertex weights (length nvtxs+1) */
            LanczosType solver_flag,   /* which eigensolver should I use? */
            bool rqi_flag,             /* use multilevel eigensolver? */
            int vmax,                  /* if so, how many vtxs to coarsen down to? */
            double eigtol              /* tolerance on eigenvectors */
            )
        {
            Trace.WriteLine($"<Entering {nameof(sequence)}>");

/* JPS
 *          extern char SEQ_FILENAME[];
 */
            vtx_data **subgraph = null;                                /* subgraph data structure */
            edgeslist *edgeslist;                                      /* edges added for connectivity */

            double *[] yvecs              = new double *[MAXDIMS + 1]; /* space for pointing to eigenvectors */
            double[]   evals              = new double[MAXDIMS + 1];   /* corresponding eigenvalues */
            double[]   goal               = new double[2];             /* needed for eigen convergence mode = 1 */
            float *[]  terminalWeights    = new float *[2];            /* dummy vector for terminal weights */
            int *      graphToSubgraphMap = null;                      /* maps graph vtxs to subgraph vtxs */
            int *      subtraphToGraphMap = null;                      /* maps subgraph vtxs to graph vtxs */
            int *      degree             = null;                      /* degrees of vertices in subgraph */
            var        useVertexWeights   = sqrtVertexWeights != null; /* are vertex weights being used? */

            /* Sort each connected component seperately. */
            // Stores the component number for each vertex.
            var vertexComponentMap = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));

/* JPS
 *          orderfile = fopen(SEQ_FILENAME, "w");
 */
            var space = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
            var connectedComponentCount = find_edges(graph, nvtxs, vertexComponentMap, space, &edgeslist);

            ++connectedComponentCount;

            Trace.WriteLine("Found connected components: " + connectedComponentCount);

            free_edgeslist(edgeslist);
            yvecs[1] = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));

            terminalWeights[1] = null;
            double *subvwsqrt = null; /* vwsqrt vector for subgraphs */

            if (RQI_CONVERGENCE_MODE != 0)
            {
                throw new InvalidOperationException(nameof(RQI_CONVERGENCE_MODE) + " should be 0 when using " + nameof(SEQUENCE) + " = true");
            }

            if (LANCZOS_CONVERGENCE_MODE != 0)
            {
                throw new InvalidOperationException(nameof(LANCZOS_CONVERGENCE_MODE) + " should be 0 when using " + nameof(SEQUENCE) + " = true");
            }

            var  largestConnectedComponentSize = nvtxs;
            int *setsize = null; /* size of each connected component */

            if (connectedComponentCount > 1)
            {
                /* Find size of largest set. */
                setsize = (int *)Marshal.AllocHGlobal(connectedComponentCount * sizeof(int));
                for (var comp = 0; comp < connectedComponentCount; comp++)
                {
                    setsize[comp] = 0;
                }

                for (var i = 1; i <= nvtxs; i++)
                {
                    ++setsize[vertexComponentMap[i]];
                }

                largestConnectedComponentSize = 0;
                for (var comp = 0; comp < connectedComponentCount; comp++)
                {
                    if (setsize[comp] > largestConnectedComponentSize)
                    {
                        largestConnectedComponentSize = setsize[comp];
                    }
                }

                graphToSubgraphMap = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));
                subtraphToGraphMap = (int *)Marshal.AllocHGlobal((largestConnectedComponentSize + 1) * sizeof(int));
                subgraph           = (vtx_data **)Marshal.AllocHGlobal((largestConnectedComponentSize + 1) * sizeof(vtx_data *));
                degree             = (int *)Marshal.AllocHGlobal((largestConnectedComponentSize + 1) * sizeof(int));
                if (useVertexWeights)
                {
                    subvwsqrt = (double *)Marshal.AllocHGlobal((largestConnectedComponentSize + 1) * sizeof(double));
                }
            }

            var indices = (int *)Marshal.AllocHGlobal(largestConnectedComponentSize * sizeof(int));

            for (var comp = 0; comp < connectedComponentCount; comp++)
            {
                int subgraphVertexCount; /* number of vertices in subgraph */
                int subgraphEdgeCount;   /* number of edges in subgraph */
                if (connectedComponentCount > 1)
                {
                    make_maps2(vertexComponentMap, nvtxs, comp, graphToSubgraphMap, subtraphToGraphMap);
                    subgraphVertexCount = setsize[comp];
                    make_subgraph(graph, subgraph, subgraphVertexCount, &subgraphEdgeCount, vertexComponentMap, comp, graphToSubgraphMap, subtraphToGraphMap, degree, useEdgeWeights);

                    if (useVertexWeights)
                    {
                        make_subvector(sqrtVertexWeights, subvwsqrt, subgraphVertexCount, subtraphToGraphMap);
                    }
                }
                else
                {
                    subgraph            = graph;
                    subgraphVertexCount = nvtxs;
                    subgraphEdgeCount   = nedges;
                    subvwsqrt           = sqrtVertexWeights;
                }

                var maxWeightedVertexDegree = find_maxdeg(subgraph, subgraphVertexCount, useEdgeWeights, (float *)null);
                Trace.WriteLine($"{nameof(maxWeightedVertexDegree)}: {maxWeightedVertexDegree}");

                double totalVertexWeight;        /* sum of all vertex weights */
                int    componentVertexWeightMax; /* largest vertex weight in component */
                if (useVertexWeights)
                {
                    componentVertexWeightMax = 0;
                    totalVertexWeight        = 0;
                    for (var i = 1; i <= subgraphVertexCount; i++)
                    {
                        componentVertexWeightMax = Math.Max(subgraph[i]->vwgt, componentVertexWeightMax);
                        totalVertexWeight       += subgraph[i]->vwgt;
                    }
                }
                else
                {
                    componentVertexWeightMax = 1;
                    totalVertexWeight        = subgraphVertexCount;
                }

                goal[0] = goal[1] = totalVertexWeight / 2;

                Trace.WriteLine($"{nameof(useVertexWeights)}: {useVertexWeights}");
                Trace.WriteLine($"{nameof(useEdgeWeights)}: {useEdgeWeights}");

                if (subgraphVertexCount == 1)
                {
                    yvecs[1][1] = 0;
                }
                else
                {
                    eigensolve(subgraph, subgraphVertexCount, subgraphEdgeCount, maxWeightedVertexDegree, componentVertexWeightMax, subvwsqrt, useVertexWeights, useEdgeWeights, terminalWeights, 0, null, yvecs, evals, false, space, goal, solver_flag, rqi_flag, vmax, 1, MappingType.IndependantMedians, eigtol);
                }

                if (connectedComponentCount > 1)
                {
                    remake_graph(subgraph, subgraphVertexCount, subtraphToGraphMap, degree, useEdgeWeights);
                }

                /* Sort values in eigenvector */
                if (useVertexWeights)
                {
                    y2x(yvecs, 1, subgraphVertexCount, subvwsqrt);
                }

                ch_mergesort(&(yvecs[1][1]), subgraphVertexCount, indices, space);

                /* Print out the order and the corresponding component of the eigenvector */
                if (connectedComponentCount == 1)
                {
                    for (var i = 0; i < subgraphVertexCount; i++)
                    {
/* JPS START */
                        jps_eigord[i] = indices[i] + 1;
                        jps_eigvec[i] = (float)yvecs[1][indices[i] + 1];
/* JPS END */

/* JPS
 *                      fprintf(orderfile, "%-7d   %9.6f\n", indices[i] + 1, yvecs[1][indices[i] + 1]);
 */
                    }
                }
                else
                {
                    for (var i = 0; i < subgraphVertexCount; i++)
                    {
/* JPS START */
                        jps_eigord[i] = subtraphToGraphMap[indices[i] + 1];
                        jps_eigvec[i] = (float)yvecs[1][indices[i] + 1];
/* JPS END */

/* JPS
 *              fprintf(orderfile, "%-7d   %9.6f\n", loc2glob[indices[i] + 1], yvecs[1][indices[i] + 1]);
 */
                    }
                }
            }

            if (connectedComponentCount > 1)
            {
                Marshal.FreeHGlobal((IntPtr)degree);
                Marshal.FreeHGlobal((IntPtr)subgraph);
                Marshal.FreeHGlobal((IntPtr)subtraphToGraphMap);
                Marshal.FreeHGlobal((IntPtr)graphToSubgraphMap);
                Marshal.FreeHGlobal((IntPtr)setsize);
                if (useVertexWeights)
                {
                    Marshal.FreeHGlobal((IntPtr)subvwsqrt);
                }
            }

            Marshal.FreeHGlobal((IntPtr)yvecs[1]);
            Marshal.FreeHGlobal((IntPtr)indices);
            Marshal.FreeHGlobal((IntPtr)space);
            Marshal.FreeHGlobal((IntPtr)vertexComponentMap);

            Trace.WriteLine($"{connectedComponentCount:D} connected components found.");
        }
Exemplo n.º 5
0
        public static void coarsen_kl(
            /* Coarsen until nvtxs < vmax, compute and uncoarsen. */
            vtx_data **graph,        /* array of vtx data for graph */
            int nvtxs,               /* number of vertices in graph */
            int nedges,              /* number of edges in graph */
            bool using_vwgts,        /* are vertices weights being used? */
            bool useEdgeWeights,     /* are edge weights being used? */
            float *[] term_wgts,     /* weights for terminal propagation */
            int igeom,               /* dimension for geometric information */
            float **coords,          /* coordinates for vertices */
            int vwgt_max,            /* largest vertex weight */
            int *assignment,         /* processor each vertex gets assigned to */
            double[] goal,           /* desired set sizes */
            bool architecture,       /* 0 => hypercube, d => d-dimensional mesh */
            int[][] hops,            /* cost of edge between sets */
            LanczosType solver_flag, /* which eigensolver to use */
            int ndims,               /* number of eigenvectors to calculate */
            int nsets,               /* number of sets being divided into */
            int vmax,                /* largest subgraph to stop coarsening */
            MappingType mediantype,  /* flag for different assignment strategies */
            bool mkconnected,        /* make graph connected before eigensolver? */
            double eigtol,           /* tolerance in eigen calculation */
            int nstep,               /* number of coarsenings between RQI steps */
            int step,                /* current step number */
            int **pbndy_list,        /* pointer to returned boundary list */
            double[] weights,        /* weights of vertices in each set */
            bool give_up             /* has coarsening bogged down? */
            )
        {
            connect_data *cdata;                             /* data structure for enforcing connectivity */
            vtx_data **   cgraph;                            /* array of vtx data for coarsened graph */

            double *[] yvecs    = new double *[MAXDIMS + 1]; /* eigenvectors for subgraph */
            double[]   evals    = new double[MAXDIMS + 1];   /* eigenvalues returned */
            double[]   new_goal = new double[MAXSETS];       /* new goal if not using vertex weights */
            double[]   real_goal;                            /* chooses between goal and new_goal */
            double     goal_weight;                          /* total weight of vertices in goal */
            double *   vwsqrt = null;                        /* square root of vertex weights */
            double     maxdeg;                               /* maximum weighted degree of a vertex */

            double[]  temp_goal = new double[2];             /* goal to simulate bisection while striping */
            double[]  fake_goal;                             /* either goal or temp_goal */
            float *[] cterm_wgts    = new float *[MAXSETS];  /* terminal weights for coarse graph */
            float *[] new_term_wgts = new float *[MAXSETS];  /* modified for Bui's method */
            float *[] real_term_wgts;                        /* which of previous two to use */
            float     ewgt_max;                              /* largest edge weight in graph */
            float *   twptr;                                 /* loops through term_wgts */
            float *   twptr_save;                            /* copy of twptr */
            float *   ctwptr;                                /* loops through cterm_wgts */
            float **  ccoords;                               /* coarse graph coordinates */
            int *     active;                                /* space for assign routine */
            int *     v2cv;                                  /* mapping from fine to coarse vertices */
            int *     cv2v;                                  /* mapping from coarse to fine vertices */
            int *     bndy_list;                             /* list of vertices on boundary */
            int *     cbndy_list;                            /* list of vertices of coarse graph on boundary */
            int *     mflag;                                 /* flags indicating matching */
            int *     cassignment;                           /* set assignments for coarsened vertices */
            int       clist_length;                          /* length of coarse graph boundary vtx list */
            int       list_length;                           /* length of boundary vtx list */
            int       vtx;                                   /* vertex in graph */
            int       cvtx;                                  /* vertex in coarse graph */
            int       cnvtxs;                                /* number of vertices in coarsened graph */
            int       cnedges;                               /* number of edges in coarsened graph */
            int       cvwgt_max;                             /* largest vertex weight in coarsened graph */
            int       nextstep;                              /* next step in RQI test */
            int       max_dev;                               /* largest allowed deviation from balance */
            int       set;                                   /* set a vertex is in */
            int       i, j;                                  /* loop counters */

            if (DEBUG_COARSEN || DEBUG_TRACE)
            {
                Trace.WriteLine($"<Entering coarsen_kl, {nameof(step)}={step:d}, {nameof(nvtxs)}={nvtxs:d}, {nameof(nedges)}={nedges:d}, {nameof(vmax)}={vmax:d}>");
            }

            /* Is problem small enough to solve? */
            if (nvtxs <= vmax || give_up)
            {
                if (using_vwgts)
                {
                    vwsqrt = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));
                    makevwsqrt(vwsqrt, graph, nvtxs);
                }
                else
                {
                    vwsqrt = null;
                }

                /* Create space for subgraph yvecs. */
                for (i = 1; i <= ndims; i++)
                {
                    yvecs[i] = (double *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(double));
                }

                active = (int *)Marshal.AllocHGlobal(nvtxs * sizeof(int));
                if (mkconnected)
                {
                    make_connected(graph, nvtxs, &nedges, (int *)&(yvecs[1][0]), active, &cdata, useEdgeWeights);
                    if (DEBUG_CONNECTED)
                    {
                        Trace.WriteLine("Enforcing connectivity on coarse graph");
                        print_connected(cdata);
                    }
                }

                /* If not coarsening ewgts, then need care with term_wgts. */
                if (!useEdgeWeights && term_wgts[1] != null && step != 0)
                {
                    twptr      = (float *)Marshal.AllocHGlobal((nvtxs + 1) * (nsets - 1) * sizeof(float));
                    twptr_save = twptr;
                    for (j = 1; j < nsets; j++)
                    {
                        new_term_wgts[j] = twptr;
                        twptr           += nvtxs + 1;
                    }

                    for (j = 1; j < nsets; j++)
                    {
                        twptr  = term_wgts[j];
                        ctwptr = new_term_wgts[j];
                        for (i = 1; i <= nvtxs; i++)
                        {
                            if (twptr[i] > .5)
                            {
                                ctwptr[i] = 1;
                            }
                            else if (twptr[i] < -.5)
                            {
                                ctwptr[i] = -1;
                            }
                            else
                            {
                                ctwptr[i] = 0;
                            }
                        }
                    }

                    real_term_wgts = new_term_wgts;
                }
                else
                {
                    real_term_wgts   = term_wgts;
                    new_term_wgts[1] = null;
                }

                if (!COARSEN_VWGTS && step != 0)
                {
                    /* Construct new goal */
                    goal_weight = 0;
                    for (i = 0; i < nsets; i++)
                    {
                        goal_weight += goal[i];
                    }

                    for (i = 0; i < nsets; i++)
                    {
                        new_goal[i] = goal[i] * (nvtxs / goal_weight);
                    }

                    real_goal = new_goal;
                }
                else
                {
                    real_goal = goal;
                }

                if (ndims == 1 && nsets > 2)
                {
                    /* Striping. */
                    mediantype   = MappingType.Striped;
                    temp_goal[0] = temp_goal[1] = 0;
                    for (i = 0; 2 * i + 1 < nsets; i++)
                    {
                        temp_goal[0] += real_goal[i];
                        temp_goal[1] += real_goal[nsets - 1 - i];
                    }

                    i = nsets / 2;
                    if (2 * i != nsets)
                    {
                        temp_goal[0] += .5 * real_goal[i];
                        temp_goal[1] += .5 * real_goal[i];
                    }

                    fake_goal = temp_goal;
                }
                else
                {
                    mediantype = MAPPING_TYPE;
                    fake_goal  = real_goal;
                }

                /* Partition coarse graph with spectral method */
                maxdeg = find_maxdeg(graph, nvtxs, useEdgeWeights, &ewgt_max);
                eigensolve(graph, nvtxs, nedges, maxdeg, vwgt_max, vwsqrt, using_vwgts, useEdgeWeights,
                           real_term_wgts, 0, (float **)null, yvecs, evals, architecture, assignment, fake_goal,
                           solver_flag, false, 0, ndims, mediantype, eigtol);

                if (mkconnected)
                {
                    make_unconnected(graph, &nedges, &cdata, useEdgeWeights);
                }

                Assign(graph, yvecs, nvtxs, ndims, architecture, nsets, vwsqrt, assignment, active, mediantype,
                       real_goal, vwgt_max);

                /*
                 * simple_part(graph, nvtxs, assignment, nsets, 1, real_goal);
                 */
                Marshal.FreeHGlobal((IntPtr)active);

                count_weights(graph, nvtxs, assignment, nsets, weights, (vwgt_max != 1));

                bndy_list = null;
                if (COARSE_KL_BOTTOM || (step % nstep) == 0)
                {
                    if (LIMIT_KL_EWGTS)
                    {
                        compress_ewgts(graph, nvtxs, nedges, ewgt_max, useEdgeWeights);
                    }

                    max_dev     = (step == 0) ? vwgt_max : 5 * vwgt_max;
                    goal_weight = 0;
                    for (i = 0; i < nsets; i++)
                    {
                        goal_weight += real_goal[i];
                    }

                    goal_weight *= KL_IMBALANCE / nsets;
                    if (goal_weight > max_dev)
                    {
                        max_dev = (int)goal_weight;
                    }

                    if (KL_ONLY_BNDY)
                    {
                        /* On small graph, quickest to include everybody in list. */
                        bndy_list = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));
                        for (i = 0; i < nvtxs; i++)
                        {
                            bndy_list[i] = i + 1;
                        }

                        bndy_list[nvtxs] = 0;
                    }

                    klspiff(graph, nvtxs, assignment, nsets, hops, real_goal, real_term_wgts, max_dev, maxdeg,
                            useEdgeWeights, &bndy_list, weights);
                    if (LIMIT_KL_EWGTS)
                    {
                        restore_ewgts(graph, nvtxs);
                    }
                }

                else if (KL_ONLY_BNDY)
                {
                    /* Find boundary vertices directly. */
                    bndy_list   = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));
                    list_length = 0;
                    for (i = 1; i <= nvtxs; i++)
                    {
                        set = assignment[i];
                        for (j = 1; j < graph[i]->nedges; j++)
                        {
                            if (assignment[graph[i]->edges[j]] != set)
                            {
                                bndy_list[list_length++] = i;
                                break;
                            }
                        }
                    }

                    bndy_list[list_length] = 0;
                    bndy_list = (int *)Marshal.ReAllocHGlobal((IntPtr)bndy_list, new IntPtr((list_length + 1) * sizeof(int)));
                }

                *pbndy_list = bndy_list;

                if (real_term_wgts != term_wgts && new_term_wgts[1] != null)
                {
                    Marshal.FreeHGlobal((IntPtr)real_term_wgts[1]);
                }

                if (vwsqrt != null)
                {
                    Marshal.FreeHGlobal((IntPtr)vwsqrt);
                }

                for (i = ndims; i > 0; i--)
                {
                    Marshal.FreeHGlobal((IntPtr)yvecs[i]);
                }

                return;
            }

            /* Otherwise I have to coarsen. */
            if (coords != null)
            {
                ccoords = (float **)Marshal.AllocHGlobal(igeom * sizeof(float *));
            }
            else
            {
                ccoords = null;
            }

            coarsen1(graph, nvtxs, nedges, &cgraph, &cnvtxs, &cnedges, &v2cv, igeom, coords, ccoords,
                     useEdgeWeights);

            if (term_wgts[1] != null)
            {
                twptr      = (float *)Marshal.AllocHGlobal((cnvtxs + 1) * (nsets - 1) * sizeof(float));
                twptr_save = twptr;
                for (i = (cnvtxs + 1) * (nsets - 1); i != 0; i--)
                {
                    *twptr++ = 0;
                }

                twptr = twptr_save;
                for (j = 1; j < nsets; j++)
                {
                    cterm_wgts[j] = twptr;
                    twptr        += cnvtxs + 1;
                }

                for (j = 1; j < nsets; j++)
                {
                    ctwptr = cterm_wgts[j];
                    twptr  = term_wgts[j];
                    for (i = 1; i < nvtxs; i++)
                    {
                        ctwptr[v2cv[i]] += twptr[i];
                    }
                }
            }
            else
            {
                cterm_wgts[1] = null;
            }

            /* If coarsening isn't working very well, give up and partition. */
            give_up = false;
            if (nvtxs * COARSEN_RATIO_MIN < cnvtxs && cnvtxs > vmax)
            {
                Trace.WriteLine($"WARNING: Coarsening not making enough progress, {nameof(nvtxs)} = {nvtxs:d}, {nameof(cnvtxs)} = {cnvtxs:d}.");
                Trace.WriteLine("         Recursive coarsening being stopped prematurely.");

                give_up = true;
            }

            /* Now recurse on coarse subgraph. */
            if (COARSEN_VWGTS)
            {
                cvwgt_max = 0;
                for (i = 1; i <= cnvtxs; i++)
                {
                    if (cgraph[i]->vwgt > cvwgt_max)
                    {
                        cvwgt_max = cgraph[i]->vwgt;
                    }
                }
            }
            else
            {
                cvwgt_max = 1;
            }

            cassignment = (int *)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(int));
            nextstep    = step + 1;
            coarsen_kl(cgraph, cnvtxs, cnedges, COARSEN_VWGTS, COARSEN_EWGTS, cterm_wgts, igeom, ccoords,
                       cvwgt_max, cassignment, goal, architecture, hops, solver_flag, ndims, nsets, vmax,
                       mediantype, mkconnected, eigtol, nstep, nextstep, &cbndy_list, weights, give_up);

            /* Interpolate assignment back to fine graph. */
            for (i = 1; i <= nvtxs; i++)
            {
                assignment[i] = cassignment[v2cv[i]];
            }

            if (KL_ONLY_BNDY)
            {
                /* Construct boundary list from coarse boundary list. */
                cv2v  = (int *)Marshal.AllocHGlobal((cnvtxs + 1) * sizeof(int));
                mflag = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));
                for (i = 1; i <= cnvtxs; i++)
                {
                    cv2v[i] = 0;
                }

                for (i = 1; i <= nvtxs; i++)
                {
                    mflag[i] = 0;
                    cvtx     = v2cv[i];
                    if (cv2v[cvtx] == 0)
                    {
                        cv2v[cvtx] = i;
                    }
                    else
                    {
                        mflag[cv2v[cvtx]] = i;
                    }
                }

                clist_length = 0;
                while (cbndy_list[clist_length] != 0)
                {
                    clist_length++;
                }

                bndy_list = (int *)Marshal.AllocHGlobal((2 * clist_length + 1) * sizeof(int));

                list_length = 0;
                for (i = 0; i < clist_length; i++)
                {
                    vtx = cv2v[cbndy_list[i]];
                    bndy_list[list_length++] = vtx;
                    if (mflag[vtx] != 0)
                    {
                        bndy_list[list_length++] = mflag[vtx];
                    }
                }

                bndy_list[list_length] = 0;
                bndy_list = (int *)Marshal.ReAllocHGlobal((IntPtr)bndy_list, new IntPtr((list_length + 1) * sizeof(int)));

                Marshal.FreeHGlobal((IntPtr)mflag);
                Marshal.FreeHGlobal((IntPtr)cv2v);
                Marshal.FreeHGlobal((IntPtr)cbndy_list);
            }
            else
            {
                bndy_list = null;
            }

            /* Free the space that was allocated. */
            Marshal.FreeHGlobal((IntPtr)cassignment);
            if (cterm_wgts[1] != null)
            {
                Marshal.FreeHGlobal((IntPtr)cterm_wgts[1]);
            }

            free_graph(cgraph);
            Marshal.FreeHGlobal((IntPtr)v2cv);

            /* Smooth using KL every nstep steps. */
            if ((step % nstep) == 0)
            {
                if (!COARSEN_VWGTS && step != 0)
                {
                    /* Construct new goal */
                    goal_weight = 0;
                    for (i = 0; i < nsets; i++)
                    {
                        goal_weight += goal[i];
                    }

                    for (i = 0; i < nsets; i++)
                    {
                        new_goal[i] = goal[i] * (nvtxs / goal_weight);
                    }

                    real_goal = new_goal;
                }
                else
                {
                    real_goal = goal;
                }

                maxdeg = find_maxdeg(graph, nvtxs, useEdgeWeights, &ewgt_max);
                if (LIMIT_KL_EWGTS)
                {
                    compress_ewgts(graph, nvtxs, nedges, ewgt_max, useEdgeWeights);
                }

                /* If not coarsening ewgts, then need care with term_wgts. */
                if (!useEdgeWeights && term_wgts[1] != null && step != 0)
                {
                    twptr      = (float *)Marshal.AllocHGlobal((nvtxs + 1) * (nsets - 1) * sizeof(float));
                    twptr_save = twptr;
                    for (j = 1; j < nsets; j++)
                    {
                        new_term_wgts[j] = twptr;
                        twptr           += nvtxs + 1;
                    }

                    for (j = 1; j < nsets; j++)
                    {
                        twptr  = term_wgts[j];
                        ctwptr = new_term_wgts[j];
                        for (i = 1; i <= nvtxs; i++)
                        {
                            if (twptr[i] > .5)
                            {
                                ctwptr[i] = 1;
                            }
                            else if (twptr[i] < -.5)
                            {
                                ctwptr[i] = -1;
                            }
                            else
                            {
                                ctwptr[i] = 0;
                            }
                        }
                    }

                    real_term_wgts = new_term_wgts;
                }
                else
                {
                    real_term_wgts   = term_wgts;
                    new_term_wgts[1] = null;
                }

                max_dev     = (step == 0) ? vwgt_max : 5 * vwgt_max;
                goal_weight = 0;
                for (i = 0; i < nsets; i++)
                {
                    goal_weight += real_goal[i];
                }

                goal_weight *= KL_IMBALANCE / nsets;
                if (goal_weight > max_dev)
                {
                    max_dev = (int)goal_weight;
                }

                if (!COARSEN_VWGTS)
                {
                    count_weights(graph, nvtxs, assignment, nsets, weights, (vwgt_max != 1));
                }

                klspiff(graph, nvtxs, assignment, nsets, hops, real_goal, real_term_wgts, max_dev, maxdeg,
                        useEdgeWeights, &bndy_list, weights);

                if (real_term_wgts != term_wgts && new_term_wgts[1] != null)
                {
                    Marshal.FreeHGlobal((IntPtr)real_term_wgts[1]);
                }

                if (LIMIT_KL_EWGTS)
                {
                    restore_ewgts(graph, nvtxs);
                }
            }

            *pbndy_list = bndy_list;

            if (ccoords != null)
            {
                for (i = 0; i < igeom; i++)
                {
                    Marshal.FreeHGlobal((IntPtr)ccoords[i]);
                }

                Marshal.FreeHGlobal((IntPtr)ccoords);
            }

            if (DEBUG_COARSEN)
            {
                Trace.WriteLine($" Leaving coarsen_kl, {nameof(step)}={step:d}");
            }
        }