Zoltan2
Zoltan2_Metric.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
51 #ifndef ZOLTAN2_METRIC_HPP
52 #define ZOLTAN2_METRIC_HPP
53 
54 #include <Zoltan2_StridedData.hpp>
56 #include <Tpetra_Map.hpp>
57 #include <Tpetra_CrsMatrix.hpp>
58 #include <Zoltan2_GraphModel.hpp>
59 
60 #include <Epetra_SerialDenseVector.h>
61 
62 #include <cmath>
63 #include <iomanip>
64 #include <iostream>
65 
66 namespace Zoltan2{
67 
69 // Classes
71 
75 template <typename scalar_t>
76  class MetricValues{
77 
78 private:
79  void resetValues(){
80  scalar_t *tmp = new scalar_t [evalNumMetrics];
81  memset(tmp, 0, sizeof(scalar_t) * evalNumMetrics);
82  values_ = arcp(tmp, 0, evalNumMetrics, true);
83  }
84  ArrayRCP<scalar_t> values_;
85  std::string metricName_;
86  multiCriteriaNorm mcnorm_; // store "actualNorm + 1"
87 
88 public:
89 
107 };
108 
116 static void printHeader(std::ostream &os);
117 
119 void printLine(std::ostream &os) const;
120 
122 MetricValues(std::string mname) :
123  values_(), metricName_(mname), mcnorm_(multiCriteriaNorm(0)) {
124  resetValues();}
125 
128  values_(), metricName_("unset"), mcnorm_(multiCriteriaNorm(0)) {
129  resetValues();}
130 
132 void setName(std::string name) { metricName_ = name;}
133 
135 void setNorm(multiCriteriaNorm normVal) {
136  mcnorm_ = multiCriteriaNorm(normVal+1);}
137 
139 void setLocalSum(scalar_t x) { values_[evalLocalSum] = x;}
140 
142 void setGlobalSum(scalar_t x) { values_[evalGlobalSum] = x;}
143 
145 void setGlobalMin(scalar_t x) { values_[evalGlobalMin] = x;}
146 
148 void setGlobalMax(scalar_t x) { values_[evalGlobalMax] = x;}
149 
151 void setGlobalAvg(scalar_t x) { values_[evalGlobalAvg] = x;}
152 
154 void setMinImbalance(scalar_t x) { values_[evalMinImbalance] = x;}
155 
159 void setMaxImbalance(scalar_t x) { values_[evalMaxImbalance] = x;}
160 
162 void setAvgImbalance(scalar_t x) { values_[evalAvgImbalance] = x;}
163 
165 const std::string &getName() const { return metricName_; }
166 
169 
171 scalar_t getLocalSum() const { return values_[evalLocalSum];}
172 
174 scalar_t getGlobalSum() const { return values_[evalGlobalSum];}
175 
177 scalar_t getGlobalMin() const { return values_[evalGlobalMin];}
178 
180 scalar_t getGlobalMax() const { return values_[evalGlobalMax];}
181 
183 scalar_t getGlobalAvg() const { return values_[evalGlobalAvg];}
184 
186 scalar_t getMinImbalance() const { return values_[evalMinImbalance];}
187 
191 scalar_t getMaxImbalance() const { return values_[evalMaxImbalance];}
192 
194 scalar_t getAvgImbalance() const { return values_[evalAvgImbalance];}
195 
196 }; // end class
197 
201 template <typename scalar_t>
203 
204 private:
205  void resetValues(){
206  scalar_t *tmp = new scalar_t [evalNumMetrics];
207  memset(tmp, 0, sizeof(scalar_t) * evalNumMetrics);
208  values_ = arcp(tmp, 0, evalNumMetrics, true);
209  }
210  ArrayRCP<scalar_t> values_;
211  std::string metricName_;
212 
213 public:
214 
221 };
222 
225 static void printHeader(std::ostream &os);
226 
228 void printLine(std::ostream &os) const;
229 
231 GraphMetricValues(std::string mname) :
232  values_(), metricName_(mname) {
233  resetValues();}
234 
237  values_(), metricName_("unset") {
238  resetValues();}
239 
241 void setName(std::string name) { metricName_ = name;}
242 
244 void setGlobalSum(scalar_t x) { values_[evalGlobalSum] = x;}
245 
247 void setGlobalMax(scalar_t x) { values_[evalGlobalMax] = x;}
248 
250 const std::string &getName() const { return metricName_; }
251 
253 scalar_t getGlobalSum() const { return values_[evalGlobalSum];}
254 
256 scalar_t getGlobalMax() const { return values_[evalGlobalMax];}
257 
258 }; // end class
259 
260 template <typename scalar_t>
261  void MetricValues<scalar_t>::printLine(std::ostream &os) const
262 {
263  std::string label(metricName_);
264  if (mcnorm_ > 0){
265  multiCriteriaNorm realNorm = multiCriteriaNorm(mcnorm_ - 1);
266  std::ostringstream oss;
267  switch (realNorm){
268  case normMinimizeTotalWeight: // 1-norm = Manhattan norm
269  oss << metricName_ << " (1)";
270  break;
271  case normBalanceTotalMaximum: // 2-norm = sqrt of sum of squares
272  oss << metricName_ << " (2)";
273  break;
274  case normMinimizeMaximumWeight: // inf-norm = maximum norm
275  oss << metricName_ << " (inf)";
276  break;
277  default:
278  oss << metricName_ << " (?)";
279  break;
280  }
281 
282  label = oss.str();
283  }
284 
285  os << std::setw(20) << label;
286  os << std::setw(12) << std::setprecision(4) << values_[evalGlobalMin];
287  os << std::setw(12) << std::setprecision(4) << values_[evalGlobalMax];
288  os << std::setw(12) << std::setprecision(4) << values_[evalGlobalAvg];
289  os << std::setw(2) << " ";
290  os << std::setw(6) << std::setprecision(4) << values_[evalMinImbalance];
291  os << std::setw(6) << std::setprecision(4) << values_[evalMaxImbalance];
292  os << std::setw(6) << std::setprecision(4) << values_[evalAvgImbalance];
293  os << std::endl;
294 }
295 
296 template <typename scalar_t>
297  void MetricValues<scalar_t>::printHeader(std::ostream &os)
298 {
299  os << std::setw(20) << " ";
300  os << std::setw(36) << "------------SUM PER PART-----------";
301  os << std::setw(2) << " ";
302  os << std::setw(18) << "IMBALANCE PER PART";
303  os << std::endl;
304 
305  os << std::setw(20) << " ";
306  os << std::setw(12) << "min" << std::setw(12) << "max" << std::setw(12) << "avg";
307  os << std::setw(2) << " ";
308  os << std::setw(6) << "min" << std::setw(6) << "max" << std::setw(6) << "avg";
309  os << std::endl;
310 }
311 
312 template <typename scalar_t>
313  void GraphMetricValues<scalar_t>::printLine(std::ostream &os) const
314 {
315  std::string label(metricName_);
316 
317  os << std::setw(20) << label;
318  os << std::setw(12) << std::setprecision(4) << values_[evalGlobalSum];
319  os << std::setw(12) << std::setprecision(4) << values_[evalGlobalMax];
320  os << std::endl;
321 }
322 
323 template <typename scalar_t>
325 {
326  os << std::setw(20) << " ";
327  os << std::setw(24) << "----------SUM----------";
328  os << std::endl;
329 
330  os << std::setw(20) << " ";
331  os << std::setw(12) << "sum" << std::setw(12) << "max";
332  os << std::endl;
333 }
334 
336 // Namespace methods to compute metric values
338 
348 template <typename scalar_t>
349  void getStridedStats(const ArrayView<scalar_t> &v, int stride,
350  int offset, scalar_t &min, scalar_t &max, scalar_t &sum)
351 {
352  if (v.size() < 1) return;
353  min = max = sum = v[offset];
354 
355  for (int i=offset+stride; i < v.size(); i += stride){
356  if (v[i] < min) min = v[i];
357  else if (v[i] > max) max = v[i];
358  sum += v[i];
359  }
360 }
361 
370 template <typename scalar_t>
371  void getStridedStats(const ArrayView<scalar_t> &v, int stride,
372  int offset, scalar_t &max, scalar_t &sum)
373 {
374  if (v.size() < 1) return;
375  max = sum = v[offset];
376 
377  for (int i=offset+stride; i < v.size(); i += stride){
378  if (v[i] > max) max = v[i];
379  sum += v[i];
380  }
381 }
382 
401 template <typename scalar_t, typename lno_t, typename part_t>
403  const RCP<const Environment> &env,
404  part_t numberOfParts,
405  const ArrayView<const part_t> &parts,
406  const ArrayView<StridedData<lno_t, scalar_t> > &vwgts,
407  multiCriteriaNorm mcNorm,
408  scalar_t *weights)
409 {
410  env->localInputAssertion(__FILE__, __LINE__, "parts or weights",
411  numberOfParts > 0 && vwgts.size() > 0, BASIC_ASSERTION);
412 
413  int numObjects = parts.size();
414  int vwgtDim = vwgts.size();
415 
416  memset(weights, 0, sizeof(scalar_t) * numberOfParts);
417 
418  if (numObjects == 0)
419  return;
420 
421  if (vwgtDim == 0) {
422  for (lno_t i=0; i < numObjects; i++){
423  weights[parts[i]]++;
424  }
425  }
426  else if (vwgtDim == 1){
427  for (lno_t i=0; i < numObjects; i++){
428  weights[parts[i]] += vwgts[0][i];
429  }
430  }
431  else{
432  switch (mcNorm){
434  for (int wdim=0; wdim < vwgtDim; wdim++){
435  for (lno_t i=0; i < numObjects; i++){
436  weights[parts[i]] += vwgts[wdim][i];
437  }
438  } // next weight index
439  break;
440 
442  for (lno_t i=0; i < numObjects; i++){
443  scalar_t ssum = 0;
444  for (int wdim=0; wdim < vwgtDim; wdim++)
445  ssum += (vwgts[wdim][i] * vwgts[wdim][i]);
446  weights[parts[i]] += sqrt(ssum);
447  }
448  break;
449 
451  for (lno_t i=0; i < numObjects; i++){
452  scalar_t max = 0;
453  for (int wdim=0; wdim < vwgtDim; wdim++)
454  if (vwgts[wdim][i] > max)
455  max = vwgts[wdim][i];
456  weights[parts[i]] += max;
457  }
458  break;
459 
460  default:
461  env->localBugAssertion(__FILE__, __LINE__, "invalid norm", false,
463  break;
464  }
465  }
466 }
467 
509 template <typename scalar_t, typename lno_t, typename part_t>
511  const RCP<const Environment> &env,
512  const RCP<const Comm<int> > &comm,
513  const ArrayView<const part_t> &part,
514  int vwgtDim,
515  const ArrayView<StridedData<lno_t, scalar_t> > &vwgts,
516  multiCriteriaNorm mcNorm,
517  part_t &numParts,
518  part_t &numNonemptyParts,
519  ArrayRCP<MetricValues<scalar_t> > &metrics,
520  ArrayRCP<scalar_t> &globalSums)
521 {
522  env->debug(DETAILED_STATUS, "Entering globalSumsByPart");
524  // Initialize return values
525 
526  numParts = numNonemptyParts = 0;
527 
528  int numMetrics = 1; // "object count"
529  if (vwgtDim) numMetrics++; // "normed weight" or "weight 1"
530  if (vwgtDim > 1) numMetrics += vwgtDim; // "weight n"
531 
532  typedef MetricValues<scalar_t> mv_t;
533  mv_t *newMetrics = new mv_t [numMetrics];
534  env->localMemoryAssertion(__FILE__, __LINE__, numMetrics, newMetrics);
535  ArrayRCP<mv_t> metricArray(newMetrics, 0, numMetrics, true);
536 
537  metrics = metricArray;
538 
540  // Figure out the global number of parts in use.
541  // Verify number of vertex weights is the same everywhere.
542 
543  lno_t localNumObj = part.size();
544  part_t localNum[2], globalNum[2];
545  localNum[0] = static_cast<part_t>(vwgtDim);
546  localNum[1] = 0;
547 
548  for (lno_t i=0; i < localNumObj; i++)
549  if (part[i] > localNum[1]) localNum[1] = part[i];
550 
551  try{
552  reduceAll<int, part_t>(*comm, Teuchos::REDUCE_MAX, 2,
553  localNum, globalNum);
554  }
556 
557  env->globalBugAssertion(__FILE__,__LINE__,
558  "inconsistent number of vertex weights",
559  globalNum[0] == localNum[0], DEBUG_MODE_ASSERTION, comm);
560 
561  part_t nparts = globalNum[1] + 1;
562 
563  part_t globalSumSize = nparts * numMetrics;
564  scalar_t * sumBuf = new scalar_t [globalSumSize];
565  env->localMemoryAssertion(__FILE__, __LINE__, globalSumSize, sumBuf);
566  globalSums = arcp(sumBuf, 0, globalSumSize);
567 
569  // Calculate the local totals by part.
570 
571  scalar_t *localBuf = new scalar_t [globalSumSize];
572  env->localMemoryAssertion(__FILE__, __LINE__, globalSumSize, localBuf);
573  memset(localBuf, 0, sizeof(scalar_t) * globalSumSize);
574 
575  scalar_t *obj = localBuf; // # of objects
576 
577  for (lno_t i=0; i < localNumObj; i++)
578  obj[part[i]]++;
579 
580  if (numMetrics > 1){
581 
582  scalar_t *wgt = localBuf + nparts; // single normed weight or weight 1
583  try{
584  normedPartWeights<scalar_t, lno_t, part_t>(env, nparts,
585  part, vwgts, mcNorm, wgt);
586  }
588 
589  // This code assumes the solution has the part ordered the
590  // same way as the user input. (Bug 5891 is resolved.)
591  if (vwgtDim > 1){
592  wgt += nparts; // individual weights
593  for (int vdim = 0; vdim < vwgtDim; vdim++){
594  for (lno_t i=0; i < localNumObj; i++)
595  wgt[part[i]] += vwgts[vdim][i];
596  wgt += nparts;
597  }
598  }
599  }
600 
601  // Metric: local sums on process
602 
603  int next = 0;
604 
605  metrics[next].setName("object count");
606  metrics[next].setLocalSum(localNumObj);
607  next++;
608 
609  if (numMetrics > 1){
610  scalar_t *wgt = localBuf + nparts; // single normed weight or weight 1
611  scalar_t total = 0.0;
612 
613  for (int p=0; p < nparts; p++){
614  total += wgt[p];
615  }
616 
617  if (vwgtDim == 1)
618  metrics[next].setName("weight 1");
619  else
620  metrics[next].setName("normed weight");
621 
622  metrics[next].setLocalSum(total);
623  next++;
624 
625  if (vwgtDim > 1){
626  for (int vdim = 0; vdim < vwgtDim; vdim++){
627  wgt += nparts;
628  total = 0.0;
629  for (int p=0; p < nparts; p++){
630  total += wgt[p];
631  }
632 
633  std::ostringstream oss;
634  oss << "weight " << vdim+1;
635 
636  metrics[next].setName(oss.str());
637  metrics[next].setLocalSum(total);
638  next++;
639  }
640  }
641  }
642 
644  // Obtain global totals by part.
645 
646  try{
647  reduceAll<int, scalar_t>(*comm, Teuchos::REDUCE_SUM, globalSumSize,
648  localBuf, sumBuf);
649  }
651 
652  delete [] localBuf;
653 
655  // Global sum, min, max, and average over all parts
656 
657  obj = sumBuf; // # of objects
658  scalar_t min=0, max=0, sum=0;
659  next = 0;
660 
661  ArrayView<scalar_t> objVec(obj, nparts);
662  getStridedStats<scalar_t>(objVec, 1, 0, min, max, sum);
663 
664  metrics[next].setGlobalMin(min);
665  metrics[next].setGlobalMax(max);
666  metrics[next].setGlobalSum(sum);
667  metrics[next].setGlobalAvg(sum / nparts);
668  next++;
669 
670  if (numMetrics > 1){
671  scalar_t *wgt = sumBuf + nparts; // single normed weight or weight 1
672 
673  ArrayView<scalar_t> normedWVec(wgt, nparts);
674  getStridedStats<scalar_t>(normedWVec, 1, 0, min, max, sum);
675 
676  if (vwgtDim > 1)
677  metrics[next].setNorm(multiCriteriaNorm(mcNorm));
678 
679  metrics[next].setGlobalMin(min);
680  metrics[next].setGlobalMax(max);
681  metrics[next].setGlobalSum(sum);
682  metrics[next].setGlobalAvg(sum / nparts);
683  next++;
684 
685  if (vwgtDim > 1){
686  for (int vdim=0; vdim < vwgtDim; vdim++){
687  wgt += nparts; // individual weights
688  ArrayView<scalar_t> fromVec(wgt, nparts);
689  getStridedStats<scalar_t>(fromVec, 1, 0, min, max, sum);
690 
691  metrics[next].setGlobalMin(min);
692  metrics[next].setGlobalMax(max);
693  metrics[next].setGlobalSum(sum);
694  metrics[next].setGlobalAvg(sum / nparts);
695  next++;
696  }
697  }
698  }
699 
701  // How many parts do we actually have.
702 
703  numParts = nparts;
704  obj = sumBuf; // # of objects
705 
706  /*for (part_t p=nparts-1; p > 0; p--){
707  if (obj[p] > 0) break;
708  numParts--;
709  }*/
710 
711  numNonemptyParts = numParts;
712 
713  for (part_t p=0; p < numParts; p++)
714  if (obj[p] == 0) numNonemptyParts--;
715 
716  env->debug(DETAILED_STATUS, "Exiting globalSumsByPart");
717 }
718 
748 template <typename Adapter>
750  const RCP<const Environment> &env,
751  const RCP<const Comm<int> > &comm,
752  const RCP<const GraphModel<typename Adapter::base_adapter_t> > &graph,
753  const ArrayView<const typename Adapter::part_t> &part,
754  typename Adapter::part_t &numParts,
756  ArrayRCP<typename Adapter::scalar_t> &globalSums)
757 {
758  env->debug(DETAILED_STATUS, "Entering globalWeightedCutsByPart");
760  // Initialize return values
761 
762  numParts = 0;
763 
764  int ewgtDim = graph->getNumWeightsPerEdge();
765 
766  int numMetrics = 1; // "cut count" or "weight 1"
767  if (ewgtDim > 1) numMetrics = ewgtDim; // "weight n"
768 
769  typedef typename Adapter::scalar_t scalar_t;
770  typedef typename Adapter::gno_t gno_t;
771  typedef typename Adapter::lno_t lno_t;
772  typedef typename Adapter::node_t node_t;
773  typedef typename Adapter::part_t part_t;
774  typedef StridedData<lno_t, scalar_t> input_t;
775 
776  typedef GraphMetricValues<scalar_t> mv_t;
777  typedef Tpetra::CrsMatrix<part_t,lno_t,gno_t,node_t> sparse_matrix_type;
778  typedef Tpetra::Map<lno_t, gno_t, node_t> map_type;
779  typedef Tpetra::global_size_t GST;
780  const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
781 
782  using Teuchos::as;
783 
784  mv_t *newMetrics = new mv_t [numMetrics];
785  env->localMemoryAssertion(__FILE__,__LINE__,numMetrics,newMetrics);
786  ArrayRCP<mv_t> metricArray(newMetrics, 0, numMetrics, true);
787 
788  metrics = metricArray;
789 
791  // Figure out the global number of parts in use.
792  // Verify number of vertex weights is the same everywhere.
793 
794  lno_t localNumObj = part.size();
795  part_t localNum[2], globalNum[2];
796  localNum[0] = static_cast<part_t>(ewgtDim);
797  localNum[1] = 0;
798 
799  for (lno_t i=0; i < localNumObj; i++)
800  if (part[i] > localNum[1]) localNum[1] = part[i];
801 
802  try{
803  reduceAll<int, part_t>(*comm, Teuchos::REDUCE_MAX, 2,
804  localNum, globalNum);
805  }
807 
808  env->globalBugAssertion(__FILE__,__LINE__,
809  "inconsistent number of edge weights",
810  globalNum[0] == localNum[0], DEBUG_MODE_ASSERTION, comm);
811 
812  part_t nparts = globalNum[1] + 1;
813 
814  part_t globalSumSize = nparts * numMetrics;
815  scalar_t * sumBuf = new scalar_t [globalSumSize];
816  env->localMemoryAssertion(__FILE__, __LINE__, globalSumSize, sumBuf);
817  globalSums = arcp(sumBuf, 0, globalSumSize);
818 
820  // Calculate the local totals by part.
821 
822  scalar_t *localBuf = new scalar_t [globalSumSize];
823  env->localMemoryAssertion(__FILE__,__LINE__,globalSumSize,localBuf);
824  memset(localBuf, 0, sizeof(scalar_t) * globalSumSize);
825 
826  scalar_t *cut = localBuf; // # of cuts
827 
828  ArrayView<const gno_t> Ids;
829  ArrayView<input_t> vwgts;
830  //size_t nv =
831  graph->getVertexList(Ids, vwgts);
832 
833  ArrayView<const gno_t> edgeIds;
834  ArrayView<const lno_t> offsets;
835  ArrayView<input_t> wgts;
836  //size_t numLocalEdges =
837  graph->getEdgeList(edgeIds, offsets, wgts);
838  // **************************************************************************
839  // *************************** BUILD MAP FOR ADJS ***************************
840  // **************************************************************************
841 
842  Array<gno_t> vertexGIDs;
843  RCP<const map_type> vertexMapG;
844 
845  // Build a list of the global vertex ids...
846  vertexGIDs.resize(localNumObj);
847  gno_t min;
848  min = as<gno_t> (Ids[0]);
849  for (lno_t i = 0; i < localNumObj; ++i) {
850  vertexGIDs[i] = as<gno_t> (Ids[i]);
851 
852  if (vertexGIDs[i] < min) {
853  min = vertexGIDs[i];
854  }
855  }
856 
857  gno_t gmin;
858  Teuchos::reduceAll<int, gno_t>(*comm,Teuchos::REDUCE_MIN,1,&min,&gmin);
859 
860  //Generate Map for vertex
861  vertexMapG = rcp(new map_type(INVALID, vertexGIDs(), gmin, comm));
862 
863  // **************************************************************************
864  // ************************** BUILD GRAPH FOR ADJS **************************
865  // **************************************************************************
866 
867  RCP<sparse_matrix_type> adjsMatrix;
868 
869  // Construct Tpetra::CrsGraph objects.
870  adjsMatrix = rcp (new sparse_matrix_type (vertexMapG, 0));
871 
872  part_t justOne = 1;
873  ArrayView<part_t> justOneAV = Teuchos::arrayView (&justOne, 1);
874 
875  for (lno_t localElement=0; localElement<localNumObj; ++localElement){
876 
877  //globalRow for Tpetra Graph
878  gno_t globalRowT = as<gno_t> (Ids[localElement]);
879 
880  for (lno_t j=offsets[localElement]; j<offsets[localElement+1]; ++j){
881  gno_t globalCol = as<gno_t> (edgeIds[j]);
882  //create ArrayView globalCol object for Tpetra
883  ArrayView<gno_t> globalColAV = Teuchos::arrayView (&globalCol,1);
884 
885  //Update Tpetra adjs Graph
886  adjsMatrix->insertGlobalValues(globalRowT,globalColAV,justOneAV);
887  }// *** edge loop ***
888  }// *** vertex loop ***
889 
890  //Fill-complete adjs Graph
891  /*adjsMatrix->fillComplete (adjsMatrix->getRowMap());
892 
893  // **************************************************************************
894  // ************************ BUILD IDENTITY FOR PARTS ************************
895  // **************************************************************************
896 
897  RCP<sparse_matrix_type> Ipart;
898 
899  // Ipart: Identity matrix for part numbers
900  Ipart = rcp (new sparse_matrix_type (vertexMapG, 0));
901 
902  for (lno_t localElement=0; localElement<localNumObj; ++localElement) {
903  part_t justPart = part[localElement];
904  ArrayView<part_t> justPartAV = Teuchos::arrayView (&justPart, 1);
905 
906  // globalRow for Tpetra Matrix
907  gno_t globalRowT = as<gno_t> (Ids[localElement]);
908 
909  gno_t globalCol = as<gno_t> (Ids[localElement]);
910  //create ArrayView globalCol object for Tpetra
911  ArrayView<gno_t> globalColAV = Teuchos::arrayView (&globalCol,1);
912 
913  //Update Tpetra Ipart matrix
914  Ipart->insertGlobalValues(globalRowT,globalColAV,justPartAV);
915  }// *** vertex loop ***
916 
917  //Fill-complete parts Matrix
918  Ipart->fillComplete (Ipart->getRowMap());
919 
920  // Create matrix to store adjs part
921  RCP<sparse_matrix_type> adjsPart =
922  rcp (new sparse_matrix_type(adjsMatrix->getRowMap(),0));
923  Tpetra::MatrixMatrix::Multiply(*adjsMatrix,false,*Ipart,false,
924  *adjsPart); // adjsPart:= adjsMatrix * Ipart
925  Array<gno_t> Indices;
926  Array<part_t> Values;
927 
928  if (!ewgtDim) {
929  for (lno_t i=0; i < localNumObj; i++) {
930  const gno_t globalRow = Ids[i];
931  size_t NumEntries = adjsPart->getNumEntriesInGlobalRow (globalRow);
932  Indices.resize (NumEntries);
933  Values.resize (NumEntries);
934  adjsPart->getGlobalRowCopy (globalRow,Indices(),Values(),NumEntries);
935 
936  for (size_t j=0; j < NumEntries; j++)
937  if (part[i] != Values[j])
938  cut[part[i]]++;
939  }
940 
941  // This code assumes the solution has the part ordered the
942  // same way as the user input. (Bug 5891 is resolved.)
943  } else {
944  scalar_t *wgt = localBuf; // weight 1
945  for (int edim = 0; edim < ewgtDim; edim++){
946  for (lno_t i=0; i < localNumObj; i++) {
947  const gno_t globalRow = Ids[i];
948  size_t NumEntries = adjsPart->getNumEntriesInGlobalRow (globalRow);
949  Indices.resize (NumEntries);
950  Values.resize (NumEntries);
951  adjsPart->getGlobalRowCopy (globalRow,Indices(),Values(),NumEntries);
952 
953  for (size_t j=0; j < NumEntries; j++)
954  if (part[i] != Values[j])
955  wgt[part[i]] = wgt[part[i]] + wgts[offsets[i] + j];
956  }
957  wgt += nparts; // individual weights
958  }
959  }*/
960 
962  // Obtain global totals by part.
963 
964  try{
965  reduceAll<int, scalar_t>(*comm, Teuchos::REDUCE_SUM, globalSumSize,
966  localBuf, sumBuf);
967  }
969 
970  delete [] localBuf;
971 
973  // Global max and sum over all parts
974 
975  cut = sumBuf; // # of cuts
976  scalar_t max=0, sum=0;
977  int next = 0;
978 
979  ArrayView<scalar_t> cutVec(cut, nparts);
980  getStridedStats<scalar_t>(cutVec, 1, 0, max, sum);
981 
982  metrics[next].setName("cut count");
983  metrics[next].setGlobalMax(max);
984  metrics[next].setGlobalSum(sum);
985 
986  if (ewgtDim){
987  scalar_t *wgt = sumBuf; // weight 1
988 
989  for (int edim=0; edim < ewgtDim; edim++){
990  ArrayView<scalar_t> fromVec(wgt, nparts);
991  getStridedStats<scalar_t>(fromVec, 1, 0, max, sum);
992 
993  std::ostringstream oss;
994  oss << "weight " << edim+1;
995 
996  metrics[next].setName(oss.str());
997  metrics[next].setGlobalMax(max);
998  metrics[next].setGlobalSum(sum);
999  next++;
1000  wgt += nparts; // individual weights
1001  }
1002  }
1003 
1004  numParts = nparts;
1005 
1006  env->debug(DETAILED_STATUS, "Exiting globalWeightedCutsByPart");
1007 }
1008 
1039 template <typename scalar_t, typename part_t>
1040  void computeImbalances(part_t numParts, part_t targetNumParts,
1041  const scalar_t *psizes, scalar_t sumVals , const scalar_t *vals,
1042  scalar_t &min, scalar_t &max, scalar_t &avg)
1043 {
1044  min = sumVals;
1045  max = avg = 0;
1046 
1047  if (sumVals <= 0 || targetNumParts < 1 || numParts < 1)
1048  return;
1049 
1050  if (targetNumParts==1 || numParts==1){
1051  min = max = avg = 0; // 0 imbalance
1052  return;
1053  }
1054 
1055  if (!psizes){
1056  scalar_t target = sumVals / targetNumParts;
1057  for (part_t p=0; p < numParts; p++){
1058  scalar_t diff = abs(vals[p] - target);
1059  scalar_t tmp = diff / target;
1060  avg += tmp;
1061  if (tmp > max) max = tmp;
1062  if (tmp < min) min = tmp;
1063  }
1064  part_t emptyParts = targetNumParts - numParts;
1065  if (emptyParts > 0){
1066  if (max < 1.0)
1067  max = 1.0; // target divided by target
1068  avg += emptyParts;
1069  }
1070  }
1071  else{
1072  for (part_t p=0; p < targetNumParts; p++){
1073  if (psizes[p] > 0){
1074  if (p < numParts){
1075  scalar_t target = sumVals * psizes[p];
1076  scalar_t diff = abs(vals[p] - target);
1077  scalar_t tmp = diff / target;
1078  avg += tmp;
1079  if (tmp > max) max = tmp;
1080  if (tmp < min) min = tmp;
1081  }
1082  else{
1083  if (max < 1.0)
1084  max = 1.0; // target divided by target
1085  avg += 1.0;
1086  }
1087  }
1088  }
1089  }
1090 
1091  avg /= targetNumParts;
1092 }
1093 
1127 template <typename scalar_t, typename part_t>
1128  void computeImbalances(part_t numParts, part_t targetNumParts,
1129  int numSizes, ArrayView<ArrayRCP<scalar_t> > psizes,
1130  scalar_t sumVals , const scalar_t *vals,
1131  scalar_t &min, scalar_t &max, scalar_t &avg)
1132 {
1133  min = sumVals;
1134  max = avg = 0;
1135 
1136  if (sumVals <= 0 || targetNumParts < 1 || numParts < 1)
1137  return;
1138 
1139  if (targetNumParts==1 && numParts==1){
1140  min = max = avg = 0; // 0 imbalance
1141  return;
1142  }
1143 
1144  bool allUniformParts = true;
1145  for (int i=0; i < numSizes; i++){
1146  if (psizes[i].size() != 0){
1147  allUniformParts = false;
1148  break;
1149  }
1150  }
1151 
1152  if (allUniformParts){
1153  computeImbalances<scalar_t, part_t>(numParts, targetNumParts, NULL,
1154  sumVals, vals, min, max, avg);
1155  return;
1156  }
1157 
1158  double uniformSize = 1.0 / targetNumParts;
1159  ArrayRCP<double> sizeVec(new double [numSizes], 0, numSizes, true);
1160  for (int i=0; i < numSizes; i++){
1161  sizeVec[i] = uniformSize;
1162  }
1163 
1164  for (part_t p=0; p < numParts; p++){
1165 
1166  // If we have objects in parts that should have 0 objects,
1167  // we don't compute an imbalance. It means that other
1168  // parts have too few objects, and the imbalance will be
1169  // picked up there.
1170 
1171  if (p >= targetNumParts)
1172  break;
1173 
1174  // Vector of target amounts: T
1175 
1176  for (int i=0; i < numSizes; i++)
1177  if (psizes[i].size() > 0)
1178  sizeVec[i] = psizes[i][p];
1179 
1180  Epetra_SerialDenseVector target(View, sizeVec.getRawPtr(), numSizes);
1181  target.Scale(sumVals);
1182  double targetNorm = target.Norm2();
1183 
1184  // If part is supposed to be empty, we don't compute an
1185  // imbalance. Same argument as above.
1186 
1187  if (targetNorm > 0){
1188 
1189  // Vector of actual amounts: A
1190 
1191  Epetra_SerialDenseVector actual(numSizes);
1192  for (int i=0; i < numSizes; i++)
1193  actual[i] = vals[p] * -1.0;
1194 
1195  actual += target;
1196 
1197  // |A - T| / |T|
1198 
1199  scalar_t imbalance = actual.Norm2() / targetNorm;
1200 
1201  if (imbalance < min)
1202  min = imbalance;
1203  else if (imbalance > max)
1204  max = imbalance;
1205  avg += imbalance;
1206  }
1207  }
1208 
1209  part_t numEmptyParts = 0;
1210 
1211  for (part_t p=numParts; p < targetNumParts; p++){
1212  bool nonEmptyPart = false;
1213  for (int i=0; !nonEmptyPart && i < numSizes; i++)
1214  if (psizes[i].size() > 0 && psizes[i][p] > 0.0)
1215  nonEmptyPart = true;
1216 
1217  if (nonEmptyPart){
1218  // The partitioning has no objects for this part, which
1219  // is supposed to be non-empty.
1220  numEmptyParts++;
1221  }
1222  }
1223 
1224  if (numEmptyParts > 0){
1225  avg += numEmptyParts;
1226  if (max < 1.0)
1227  max = 1.0; // target divided by target
1228  }
1229 
1230  avg /= targetNumParts;
1231 }
1232 
1262 template <typename Adapter>
1264  const RCP<const Environment> &env,
1265  const RCP<const Comm<int> > &comm,
1266  multiCriteriaNorm mcNorm,
1267  const RCP<const Adapter> &ia,
1268  const RCP<const PartitioningSolution<Adapter> > &solution,
1269  typename Adapter::part_t &numParts,
1270  typename Adapter::part_t &numNonemptyParts,
1271  ArrayRCP<MetricValues<typename Adapter::scalar_t> > &metrics)
1272 {
1273  env->debug(DETAILED_STATUS, "Entering objectMetrics");
1274 
1275  typedef typename Adapter::scalar_t scalar_t;
1276  typedef typename Adapter::lno_t lno_t;
1277  typedef typename Adapter::part_t part_t;
1278  typedef StridedData<lno_t, scalar_t> sdata_t;
1279 
1280  // Local number of objects.
1281 
1282  size_t numLocalObjects = ia->getLocalNumIDs();
1283 
1284  // Parts to which objects are assigned.
1285 
1286  const part_t *parts = solution->getPartListView();
1287  env->localInputAssertion(__FILE__, __LINE__, "parts not set",
1288  ((numLocalObjects == 0) || parts), BASIC_ASSERTION);
1289  ArrayView<const part_t> partArray(parts, numLocalObjects);
1290 
1291  // Weights, if any, for each object.
1292 
1293  int nWeights = ia->getNumWeightsPerID();
1294  int numCriteria = (nWeights > 0 ? nWeights : 1);
1295  Array<sdata_t> weights(numCriteria);
1296 
1297  if (nWeights == 0){
1298  // One set of uniform weights is implied.
1299  // StridedData default constructor creates length 0 strided array.
1300  weights[0] = sdata_t();
1301  }
1302  else{
1303  for (int i=0; i < nWeights; i++){
1304  int stride;
1305  const scalar_t *wgt;
1306  ia->getWeightsView(wgt, stride, i);
1307  ArrayRCP<const scalar_t> wgtArray(wgt, 0, stride*numLocalObjects, false);
1308  weights[i] = sdata_t(wgtArray, stride);
1309  }
1310  }
1311 
1312  // Relative part sizes, if any, assigned to the parts.
1313 
1314  part_t targetNumParts = solution->getTargetGlobalNumberOfParts();
1315  scalar_t *psizes = NULL;
1316 
1317  ArrayRCP<ArrayRCP<scalar_t> > partSizes(numCriteria);
1318  for (int dim=0; dim < numCriteria; dim++){
1319  if (solution->criteriaHasUniformPartSizes(dim) != true){
1320  psizes = new scalar_t [targetNumParts];
1321  env->localMemoryAssertion(__FILE__, __LINE__, numParts, psizes);
1322  for (part_t i=0; i < targetNumParts; i++){
1323  psizes[i] = solution->getCriteriaPartSize(dim, i);
1324  }
1325  partSizes[dim] = arcp(psizes, 0, targetNumParts, true);
1326  }
1327  }
1328 
1330  // Get number of parts, and the number that are non-empty.
1331  // Get sums per part of objects, individual weights, and normed weight sums.
1332 
1333  ArrayRCP<scalar_t> globalSums;
1334 
1335  try{
1336  globalSumsByPart<scalar_t, lno_t, part_t>(env, comm,
1337  partArray, nWeights, weights.view(0, numCriteria), mcNorm,
1338  numParts, numNonemptyParts, metrics, globalSums);
1339  }
1341 
1343  // Compute imbalances for the object count.
1344  // (Use first index of part sizes.)
1345 
1346  scalar_t *objCount = globalSums.getRawPtr();
1347  scalar_t min, max, avg;
1348  psizes=NULL;
1349 
1350  if (partSizes[0].size() > 0)
1351  psizes = partSizes[0].getRawPtr();
1352 
1353  computeImbalances<scalar_t, part_t>(numParts, targetNumParts, psizes,
1354  metrics[0].getGlobalSum(), objCount,
1355  min, max, avg);
1356 
1357  metrics[0].setMinImbalance(1.0 + min);
1358  metrics[0].setMaxImbalance(1.0 + max);
1359  metrics[0].setAvgImbalance(1.0 + avg);
1360 
1362  // Compute imbalances for the normed weight sum.
1363 
1364  scalar_t *wgts = globalSums.getRawPtr() + numParts;
1365 
1366  if (metrics.size() > 1){
1367 
1368  computeImbalances<scalar_t, part_t>(numParts, targetNumParts,
1369  numCriteria, partSizes.view(0, numCriteria),
1370  metrics[1].getGlobalSum(), wgts,
1371  min, max, avg);
1372 
1373  metrics[1].setMinImbalance(1.0 + min);
1374  metrics[1].setMaxImbalance(1.0 + max);
1375  metrics[1].setAvgImbalance(1.0 + avg);
1376 
1377  if (metrics.size() > 2){
1378 
1380  // Compute imbalances for each individual weight.
1381 
1382  int next = 2;
1383 
1384  for (int vdim=0; vdim < numCriteria; vdim++){
1385  wgts += numParts;
1386  psizes = NULL;
1387 
1388  if (partSizes[vdim].size() > 0)
1389  psizes = partSizes[vdim].getRawPtr();
1390 
1391  computeImbalances<scalar_t, part_t>(numParts, targetNumParts, psizes,
1392  metrics[next].getGlobalSum(), wgts, min, max, avg);
1393 
1394  metrics[next].setMinImbalance(1.0 + min);
1395  metrics[next].setMaxImbalance(1.0 + max);
1396  metrics[next].setAvgImbalance(1.0 + avg);
1397  next++;
1398  }
1399  }
1400 
1401  }
1402  env->debug(DETAILED_STATUS, "Exiting objectMetrics");
1403 }
1404 
1408 template <typename scalar_t, typename part_t>
1409  void printMetrics( std::ostream &os,
1410  part_t targetNumParts, part_t numParts, part_t numNonemptyParts,
1411  const ArrayView<MetricValues<scalar_t> > &infoList)
1412 {
1413  os << "NUMBER OF PARTS IS " << numParts;
1414  if (numNonemptyParts < numParts)
1415  os << " (" << numNonemptyParts << " of which are non-empty)";
1416  os << std::endl;
1417  if (targetNumParts != numParts)
1418  os << "TARGET NUMBER OF PARTS IS " << targetNumParts << std::endl;
1419 
1420  std::string unset("unset");
1421 
1423 
1424  for (int i=0; i < infoList.size(); i++)
1425  if (infoList[i].getName() != unset)
1426  infoList[i].printLine(os);
1427 
1428  os << std::endl;
1429 }
1430 
1434 template <typename scalar_t, typename part_t>
1435  void printMetrics( std::ostream &os,
1436  part_t targetNumParts, part_t numParts, part_t numNonemptyParts,
1437  const MetricValues<scalar_t> &info)
1438 {
1439  ArrayView<MetricValues<scalar_t> > infoList(&info, 1);
1440  printMetrics( os, targetNumParts, numParts, numNonemptyParts, infoList);
1441 }
1442 
1443 
1446 template <typename scalar_t>
1447  scalar_t normedWeight(ArrayView <scalar_t> weights,
1448  multiCriteriaNorm norm)
1449 {
1450  size_t dim = weights.size();
1451  if (dim == 0)
1452  return 0.0;
1453  else if (dim == 1)
1454  return weights[0];
1455 
1456  scalar_t nweight = 0;
1457 
1458  switch (norm){
1461  for (size_t i=0; i <dim; i++)
1462  nweight += weights[i];
1463 
1464  break;
1465 
1467  for (size_t i=0; i <dim; i++)
1468  nweight += (weights[i] * weights[i]);
1469 
1470  nweight = sqrt(nweight);
1471 
1472  break;
1473 
1476  nweight = weights[0];
1477  for (size_t i=1; i <dim; i++)
1478  if (weights[i] > nweight)
1479  nweight = weights[i];
1480 
1481  break;
1482 
1483  default:
1484  Environment env; // default environment
1485  env.localBugAssertion(__FILE__, __LINE__, "invalid norm", false,
1486  BASIC_ASSERTION);
1487  break;
1488  }
1489 
1490  return nweight;
1491 }
1492 
1495 template<typename lno_t, typename scalar_t>
1496  scalar_t normedWeight(ArrayView<StridedData<lno_t, scalar_t> > weights,
1497  lno_t idx, multiCriteriaNorm norm)
1498 {
1499  size_t dim = weights.size();
1500  if (dim < 1)
1501  return 0;
1502 
1503  Array<scalar_t> vec(dim, 1.0);
1504  for (size_t i=0; i < dim; i++)
1505  if (weights[i].size() > 0)
1506  vec[dim] = weights[i][idx];
1507 
1508  return normedWeight(vec, norm);
1509 }
1510 
1511 } //namespace Zoltan2
1512 #endif
#define INVALID(STR)
metricOffset
Enumerator for offsets into metric data.
checks for logic errors
scalar_t getMaxImbalance() const
Get the imbalance of the most imbalanced part. This is what we normally call the imbalance of a parti...
void setName(std::string name)
Set or reset the name.
void computeImbalances(part_t numParts, part_t targetNumParts, const scalar_t *psizes, scalar_t sumVals, const scalar_t *vals, scalar_t &min, scalar_t &max, scalar_t &avg)
Compute the imbalance.
fast typical checks for valid arguments
void normedPartWeights(const RCP< const Environment > &env, part_t numberOfParts, const ArrayView< const part_t > &parts, const ArrayView< StridedData< lno_t, scalar_t > > &vwgts, multiCriteriaNorm mcNorm, scalar_t *weights)
Compute the total weight in each part on this process.
void setAvgImbalance(scalar_t x)
Set the average imbalance of all parts.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
void setGlobalSum(scalar_t x)
Set the global sum.
scalar_t getGlobalMin() const
Get the global minimum across all parts.
scalar_t getGlobalMax() const
Get the global maximum across all parts.
size_t global_size_t
metricOffset
Enumerator for offsets into metric data.
void objectMetrics(const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, multiCriteriaNorm mcNorm, const RCP< const Adapter > &ia, const RCP< const PartitioningSolution< Adapter > > &solution, typename Adapter::part_t &numParts, typename Adapter::part_t &numNonemptyParts, ArrayRCP< MetricValues< typename Adapter::scalar_t > > &metrics)
Compute imbalance metrics for a distribution.
scalar_t getGlobalAvg() const
Get the average of the sum over all parts.
void setGlobalMax(scalar_t x)
Set the global maximum across parts.
void printMetrics(std::ostream &os, part_t targetNumParts, part_t numParts, part_t numNonemptyParts, const ArrayView< MetricValues< scalar_t > > &infoList)
Print out a header and the values for a list of metrics.
Defines the PartitioningSolution class.
void setGlobalSum(scalar_t x)
Set the global sum.
scalar_t getLocalSum() const
Get the sum on the local process.
sub-steps, each method&#39;s entry and exit
scalar_t getAvgImbalance() const
Get the average of the part imbalances.
const std::string & getName() const
Get the name of the item measured.
const std::string & getName() const
Get the name of the item measured.
void setNorm(multiCriteriaNorm normVal)
Set or reset the norm.
GraphMetricValues(std::string mname)
Constructor.
void getStridedStats(const ArrayView< scalar_t > &v, int stride, int offset, scalar_t &min, scalar_t &max, scalar_t &sum)
Find min, max and sum of metric values.
dictionary vals
Definition: xml2dox.py:186
A PartitioningSolution is a solution to a partitioning problem.
void setGlobalAvg(scalar_t x)
Set the global average (sum / numParts).
void localBugAssertion(const char *file, int lineNum, const char *msg, bool ok, AssertionLevel level) const
Test for valid library behavior on local process only.
The StridedData class manages lists of weights or coordinates.
void setMinImbalance(scalar_t x)
Set the imbalance of the least imbalanced part.
scalar_t getGlobalSum() const
Get the global sum for all parts.
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
static void printHeader(std::ostream &os)
Print a standard header.
void setName(std::string name)
Set or reset the name.
MetricValues(std::string mname)
Constructor.
void printLine(std::ostream &os) const
Print a standard line of data that fits under the header.
GraphModel defines the interface required for graph models.
scalar_t getGlobalMax() const
Get the global maximum across all parts.
void setGlobalMin(scalar_t x)
Set the global minimum across parts.
A class containing the metrics for one measurable item.
multiCriteriaNorm
Enumerator used in code for multicriteria norm choice.
A class containing the metrics for one measurable item.
MetricValues()
Constructor.
void setGlobalMax(scalar_t x)
Set the global maximum across parts.
void globalSumsByPart(const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, const ArrayView< const part_t > &part, int vwgtDim, const ArrayView< StridedData< lno_t, scalar_t > > &vwgts, multiCriteriaNorm mcNorm, part_t &numParts, part_t &numNonemptyParts, ArrayRCP< MetricValues< scalar_t > > &metrics, ArrayRCP< scalar_t > &globalSums)
Given the local partitioning, compute the global sums in each part.
void setLocalSum(scalar_t x)
Set the sum on the local process.
multiCriteriaNorm getNorm()
Get the norm.
Defines the GraphModel interface.
#define Z2_THROW_OUTSIDE_ERROR(env)
Throw an error returned from outside the Zoltan2 library.
void globalWeightedCutsByPart(const RCP< const Environment > &env, const RCP< const Comm< int > > &comm, const RCP< const GraphModel< typename Adapter::base_adapter_t > > &graph, const ArrayView< const typename Adapter::part_t > &part, typename Adapter::part_t &numParts, ArrayRCP< GraphMetricValues< typename Adapter::scalar_t > > &metrics, ArrayRCP< typename Adapter::scalar_t > &globalSums)
Given the local partitioning, compute the global weighted cuts in each part.
static void printHeader(std::ostream &os)
Print a standard header.
scalar_t getMinImbalance() const
Get the imbalance of the least imbalanced part.
scalar_t getGlobalSum() const
Get the global sum for all parts.
void setMaxImbalance(scalar_t x)
Set the imbalance of the worst imbalanced part. This is what we normally call the imbalance of a part...
void printLine(std::ostream &os) const
Print a standard line of data that fits under the header.
This file defines the StridedData class.
scalar_t normedWeight(ArrayView< scalar_t > weights, multiCriteriaNorm norm)
Compute the norm of the vector of weights.