Пример #1
0
void initScen(uint64_t sd) {

  using KBase::quadUfromV;
  auto rng = new PRNG(sd);
  const unsigned int numA = 40;
  const unsigned int numItm = 7;

  const auto govCost = KMatrix::uniform(rng, 1, numItm, 25, 100); //col-vec
  const double govBudget = 0.625 * sum(govCost); // cannot afford everything
  const double obFactor = 0.125;

  // The 'riVals' matrix shows the value to the actor (row) of each reform item (clm),
  // not the utility of entire positions (which are permutations of items)
  const KMatrix riVal = KMatrix::uniform(rng, numA, numItm, 10, 100);

  const double pDecline = 0.8750;

  vector<double> aCap = {};
  for (unsigned int i = 0; i < numA; i++)
  {
    double ac = rng->uniform(2.0, 4.0); // [4.0, 16.0] with median at 9.0
    ac = rng->uniform(17.0, 18.0)*ac*ac;
    aCap.push_back(ac);
  }


  vector<double> prob = {};
  double pj = 1.0;
  printf("pDecline factor: %.3f \n", pDecline);
  printf("obFactor: %.3f \n", obFactor);
  // rate of decline has little effect on the results.
  for (unsigned int j = 0; j < numItm; j++) {
    prob.push_back(pj);
    pj = pj * pDecline;
  }

  cout << "Computing positions ... " << endl;
  vector<VUI> positions; // list of all positions
  VUI pstn;
  // build the first permutation: 1,2,3,...
  for (unsigned int i = 0; i < numItm; i++) {
    pstn.push_back(i);
  }
  positions.push_back(pstn);
  while (next_permutation(pstn.begin(), pstn.end())) {
    positions.push_back(pstn);
  }
  const unsigned int numPos = positions.size();
  cout << "For " << numItm << " reform items there are ";
  cout << numPos << " positions" << endl;


  cout << "Building position utility matrix ... " << flush;
  auto rpValFn = [positions, riVal, aCap, govCost, govBudget, obFactor, prob](unsigned int ai, unsigned int pj) {
    VUI pstn = positions[pj];
    double rvp = rawValPos(ai, pstn, riVal, aCap, govCost, govBudget, obFactor, prob);
    return rvp;
  };

  const auto rpRawVal = KMatrix::map(rpValFn, numA, numPos);

  const auto rpNormVal = KBase::rescaleRows(rpRawVal, 0.0, 1.0);

  const double bigR = 0.5;
  auto curve = [bigR](double v) {
    return quadUfromV(v, bigR);
  };

  const auto rpUtil = KMatrix::map(curve, rpNormVal);
  cout << "done." << endl << flush;

  // This is an attempt to define a domain-independent measure of similarity,
  // by looking at the difference in outcomes to actors.
  // Notice that if we sort the columns by difference from #i,
  // those with small differences in outcome might do it by very different
  // means, so that columns from all over the matrix are placed near i.
  auto diffFn = [](unsigned int i, unsigned int j, const KMatrix& uMat) {
    const auto colI = KBase::vSlice(uMat, i);
    const auto colJ = KBase::vSlice(uMat, j);
    for (unsigned int k=0;k<colI.numR(); k++){
    }
    double dij = KBase::norm(colI - colJ);
    return dij;
  };

  auto diffVUI = [&rpUtil, numPos, diffFn](unsigned int n, unsigned int nSim) {
    vector<TDI> vdk = {};
    for (unsigned int k = 0; k < numPos; k++) {
      double dkn = diffFn(k, n, rpUtil);
      auto dk = TDI(dkn, k);
      vdk.push_back(dk);
    }
    auto tupleLess = [](TDI t1, TDI t2) {
      double d1 = get<0>(t1);
      double d2 = get<0>(t2);
      return (d1 < d2);
    };
    std::sort(vdk.begin(), vdk.end(), tupleLess);
    vector<TDI> sdk = {};
    for (unsigned int i = 0; ((i < nSim) && (i < numPos)); i++) {
      sdk.push_back(vdk[i]);
    }
    return sdk;
  };

  // The permutations with outcomes most similar to the given
  // one are those which make the most minor changes
  // (somewhat similar to a vector hill climbing search where the
  // points in a nearby neighborhood make small changes in objective).
  // So looking at a few dozen (out of thousands) might be enough to
  // get significant variation to keep the search progressing.
  unsigned int numClose = 50;
  unsigned int rand1 = rng->uniform(0, numPos);
  auto rslt1 = diffVUI(rand1, numClose);
  
  
  cout << "Permutations with outcomes most similar to " << rand1 << endl;
  for (unsigned int i = 0; i < rslt1.size(); i++) {
    auto dp = rslt1[i];
    double d = get<0>(dp);
    unsigned int p = get<1>(dp);
    auto posP = positions[p];
    printf("%2u: %4u  %.4f  ", i, p, d);
    KBase::printVUI(posP);
    cout << endl;
  }

  delete rng;
  rng = nullptr;
  return;
}
Пример #2
0
// return the list of the most self-interested position of each actor,
// with the CP last.
// As a side-affect, set each actor's min/max permutation values so as to
// compute normalized utilities later.
vector<VUI> scanAllPossiblePositions(const RPModel * rpm) {
  unsigned int numA = rpm->numAct;
  unsigned int numRefItem = rpm->numItm;
  assert(numRefItem == rpm->numCat);

  LOG(INFO) << "There are" << numA << "actors and" << numRefItem << "reform items";



  KMatrix aCap = KMatrix(1, numA);
  for (unsigned int i = 0; i < numA; i++) {
    auto ri = ((const RPActor *)(rpm->actrs[i]));
    aCap(0, i) = ri->sCap;
  }
  LOG(INFO) << "Actor capabilities: ";
  aCap.mPrintf(" %.2f ");


  LOG(INFO) << "Effective gov cost of items:";
  (rpm->govCost).mPrintf("%.3f ");
  LOG(INFO) << "Government budget: " << rpm->govBudget;
  assert(0 < rpm->govBudget);


  string log("Value to actors (rows) of individual reform items (columns):");
  for (unsigned int i = 0; i < rpm->actrs.size(); i++) {
    auto rai = ((const RPActor*)(rpm->actrs[i]));
    for (unsigned int j = 0; j < numRefItem; j++) {
      double vij = rai->riVals[j];
      log += KBase::getFormattedString(" %6.2f", vij);
    }
  }
  LOG(INFO) << log;

  LOG(INFO) << "Computing positions ... ";
  vector<VUI> allPositions; // list of all possiblepositions
  VUI pstn;
  // build the first permutation: 0,1,2,3,...
  for (unsigned int i = 0; i < numRefItem; i++) {
    pstn.push_back(i);
  }
  allPositions.push_back(pstn);
  while (next_permutation(pstn.begin(), pstn.end())) {
    allPositions.push_back(pstn);
  }
  const unsigned int numPos = allPositions.size();
  LOG(INFO) << "For" << numRefItem << "reform items there are"
   << numPos << "positions";


  // -------------------------------------------------
  // The next section sets up actor utilities.
  // First, we compute the unnormalized, raw utilities. The 'utilActorPos' checks
  // to see if pvMin/pvMax have been set, and returns the raw scores if not.
  // Then we scan across rows to find that actor's pvMin/pvMax, and record that
  // so utilActorPos can use it in the future. Finally, we normalize the rows and
  // display the normalized utility matrix.
  auto ruFn = [allPositions, rpm](unsigned int ai, unsigned int pj) {
    auto pstn = allPositions[pj];
    double uip = rpm->utilActorPos(ai, pstn);
    return uip;
  };

  LOG(INFO) << "Computing utilities of positions ... ";
  // rows are actors, columns are all possible positions
  auto rawUij = KMatrix::map(ruFn, numA, numPos);

  // set the min/max for each actor
  for (unsigned int i = 0; i < numA; i++) {
    double pvMin = rawUij(i, 0);
    double pvMax = rawUij(i, 0);
    for (unsigned int j = 0; j < numPos; j++) {
      double rij = rawUij(i, j);
      if (rij < pvMin) {
        pvMin = rij;
      }
      if (rij > pvMax) {
        pvMax = rij;
      }
    }
    assert(0 <= pvMin);
    assert(pvMin < pvMax);
    auto ai = ((RPActor*)(rpm->actrs[i]));
    ai->posValMin = pvMin;
    ai->posValMax = pvMax;
  }
  LOG(INFO) << "Normalizing utilities of positions ... ";
  KMatrix uij = KBase::rescaleRows(rawUij, 0.0, 1.0); // von Neumann utility scale

  string utilMtx("Complete (normalized) utility matrix of all possible positions (rows) versus actors (columns) \n");
  for (unsigned int pj = 0; pj < numPos; pj++) {
    utilMtx += KBase::getFormattedString("%3u  ", pj);
    auto pstn = allPositions[pj];
    //printVUI(pstn);
    utilMtx += KBase::stringVUI(pstn);
    utilMtx += "  ";
    for (unsigned int ai = 0; ai < numA; ai++) {
      double uap = uij(ai, pj);
      utilMtx += KBase::getFormattedString("%6.4f, ", uap);
    }
    utilMtx += KBase::getFormattedString("\n");
  }
  LOG(INFO) << utilMtx;

  // -------------------------------------------------
  // The next section determines the most self-interested positions for each actor,
  // as well as the 'central position' over all possible reform priorities
  // (which 'office seeking politicans' would adopt IF proportional voting).
  LOG(INFO) << "Computing best position for each actor";
  vector<VUI> bestAP; // list of each actor's best position (followed by CP)
  for (unsigned int ai = 0; ai < numA; ai++) {
    unsigned int bestJ = 0;
    double bestV = 0;
    for (unsigned int pj = 0; pj < numPos; pj++) {
      if (bestV < uij(ai, pj)) {
        bestJ = pj;
        bestV = uij(ai, pj);
      }
    }
    string bestMtx("Best position for ");
    string ais = std::to_string(ai);
    //string bjs = std::to_string(bestJ);
    string ps = KBase::stringVUI(allPositions[bestJ]);
    bestMtx += ais + " is " + ps;
    LOG(INFO) << bestMtx; 
    //LOG(INFO) << "Best for" << ai << "is ";
    //printVUI(positions[bestJ]);
    bestAP.push_back(allPositions[bestJ]);
  }


  LOG(INFO) << "Computing zeta ... ";
  KMatrix zeta = aCap * uij;
  assert((1 == zeta.numR()) && (numPos == zeta.numC()));


  LOG(INFO) << "Sorting positions from most to least net support ...";

  auto betterPR = [](tuple<unsigned int, double, VUI> pr1,
      tuple<unsigned int, double, VUI> pr2) {
    double v1 = get<1>(pr1);
    double v2 = get<1>(pr2);
    bool better = (v1 > v2);
    return better;
  };

  auto pairs = vector<tuple<unsigned int, double, VUI>>();
  for (unsigned int i = 0; i < numPos; i++) {
    auto pri = tuple<unsigned int, double, VUI>(i, zeta(0, i), allPositions[i]);
    pairs.push_back(pri);
  }

  sort(pairs.begin(), pairs.end(), betterPR);

  const unsigned int maxDisplayed = 720; // factorial(6)
  unsigned int  numPr = (pairs.size() < maxDisplayed) ? pairs.size() : maxDisplayed;

  LOG(INFO) << "Displaying highest" << numPr;
  for (unsigned int i = 0; i < numPr; i++) {
    auto pri = pairs[i];
    unsigned int ni = get<0>(pri);
    double zi = get<1>(pri);
    VUI pi = get<2>(pri);
    string ps = KBase::stringVUI(pi);
    LOG(INFO) << KBase::getFormattedString(" %3u: %4u  %.2f  %s", i, ni, zi, ps.c_str());
    //printVUI(pi);
  }

  VUI bestPerm = get<2>(pairs[0]);

  bestAP.push_back(bestPerm);
  return bestAP;
}