示例#1
0
文件: rplib.cpp 项目: Eveyln74/KTAB
KMatrix rescaleRows(const KMatrix& m1, const double vMin, const double vMax) {
    assert(vMin < vMax);
    const unsigned int nr = m1.numR();
    const unsigned int nc = m1.numC();
    KMatrix m2 = KMatrix(nr, nc);

    for (unsigned int i = 0; i < nr; i++) {
        double rowMin = m1(i, 0);
        double rowMax = m1(i, 0);
        for (unsigned int j = 0; j < nc; j++) {
            const double mij = m1(i, j);
            if (mij < rowMin) {
                rowMin = mij;
            }
            if (mij > rowMax) {
                rowMax = mij;
            }
        }
        const double rowRange = rowMax - rowMin;
        assert(0 < rowRange);

        for (unsigned int j = 0; j < nc; j++) {
            const double mij = m1(i, j);
            const double nij = (mij - rowMin) / rowRange; // normalize into [0, 1]
            const double rij = vMin + (vMax - vMin)*nij; // rescale into [vMin, vMax]
            m2(i, j) = rij;
        }
    }


    return m2;
}
示例#2
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
KMatrix Model::bigRfromProb(const KMatrix & p, BigRRange rr) {
  double pMin = 1.0;
  double pMax = 0.0;
  for (double pi : p) {
    assert(0.0 <= pi);
    pMin = (pi < pMin) ? pi : pMin;
    pMax = (pi > pMax) ? pi : pMax;
  }

  const double pTol = 1E-8;
  assert(fabs(1 - KBase::sum(p)) < pTol);

  function<double(unsigned int, unsigned int)> rfn = nullptr;
  switch (rr) {
  case BigRRange::Min:
    rfn = [pMin, pMax, p](unsigned int i, unsigned int j) {
      return (p(i, j) - pMin) / (pMax - pMin);
    };
    break;
  case BigRRange::Mid:
    rfn = [pMin, pMax, p](unsigned int i, unsigned int j) {
      return (3 * p(i, j) - (pMax + 2 * pMin)) / (2 * (pMax - pMin));
    };
    break;
  case BigRRange::Max:
    rfn = [pMin, pMax, p](unsigned int i, unsigned int j) {
      return (2 * p(i, j) - (pMax + pMin)) / (pMax - pMin);
    };
    break;
  }
  auto rMat = KMatrix::map(rfn, p.numR(), p.numC());
  return rMat;
}
示例#3
0
// -------------------------------------------------------------------------------------------------------- 
void KPerspectiveProjection::rotate ( const GLfloat x, const GLfloat y, const GLfloat z )
{
    KVector savePos = getLookAtPosition();
    translate(-getPosition());
        
    KVector up   = getYVector();
    KVector look = getZVector();

    KMatrix rotxz; rotxz.rotate (x, 0.0, z);
    KMatrix roty;  roty.rotate  (0.0, y, 0.0);

    KVector yunit(0.0, 1.0, 0.0), zunit (0.0, 0.0, 1.0);

    KVector lookperp = look.perpendicular (yunit); // y-axis rotation    
    if (lookperp.length() > 0)
    {
        look = roty * lookperp + look.parallel(yunit);
        up   = roty * up.perpendicular(yunit) + up.parallel(yunit);
    }
    
    // x & z-axis rotation 
    KMatrix transmat(up.cross(look), up, look);
    
    KVector uprotxz   = rotxz * yunit;
    KVector lookrotxz = rotxz * zunit;

    up   = transmat * uprotxz;
    look = transmat * lookrotxz;
    
    *((KMatrix*)this) = KMatrix(up.cross(look), up, look);
    
    setPosition( savePos + eye_distance * getZVector());
}
示例#4
0
文件: rplib2.cpp 项目: KAPSARC/KTAB
void RP2Model::setRP2(const KMatrix & pm0) {
  const unsigned int nr = pm0.numR();
  const unsigned int nc = pm0.numC();
  if (0 < numAct) {
    assert(nr == numAct);
  }
  else {
    numAct = nr;
  }

  if (0 < numOptions()) {
    assert(nc == numOptions());
  }
  else {
    theta.resize(nc); // was size zero
    for (unsigned int i = 0; i < nc; i++) {
      theta[i] = i;
    }
  }

  assert(minNumActor <= numAct);
  assert(numAct <= maxNumActor);

  assert(minNumOptions <= numOptions());

  for (auto u : pm0) {
    assert(0.0 <= u);
    assert(u <= 1.0);
  }

  // if all OK, set it
  polUtilMat = pm0;

  return;
}
示例#5
0
void MVS::DecomposeProjectionMatrix(const PMatrix& P, RMatrix& R, CMatrix& C)
{
	#ifndef _RELEASE
	KMatrix K;
	DecomposeProjectionMatrix(P, K, R, C);
	ASSERT(K.IsEqual(Matrix3x3::IDENTITY));
	#endif
	// extract camera center as the right null vector of P
	const Vec4 hC(P.RightNullVector());
	C = (const CMatrix&)hC * INVERT(hC[3]);
	// get rotation
	const cv::Mat mP(3,4,cv::DataType<REAL>::type,(void*)P.val);
	mP(cv::Rect(0,0, 3,3)).copyTo(R);
	ASSERT(R.IsValid());
} // DecomposeProjectionMatrix
示例#6
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
// Given square matrix of Prob[i>j] returns a column vector for Prob[i].
// Uses Markov process, not 1-step conditional probability.
// Challenges have uniform probability 1/N
KMatrix Model::markovUniformPCE(const KMatrix & pv) {
  const double pTol = 1E-6;
  unsigned int numOpt = pv.numR();
  auto p = KMatrix(numOpt, 1, 1.0) / numOpt;  // all 1/n
  auto q = p;
  unsigned int iMax = 1000;  // 10-30 is typical
  unsigned int iter = 0;
  double change = 1.0;
  while (pTol < change) {
    change = 0;
    for (unsigned int i = 0; i < numOpt; i++) {
      double pi = 0.0;
      for (unsigned int j = 0; j < numOpt; j++) {
        pi = pi + pv(i, j)*(p(i, 0) + p(j, 0));
      }
      assert(0 <= pi); // double-check
      q(i, 0) = pi / numOpt;
      double c = fabs(q(i, 0) - p(i, 0));
      change = (c > change) ? c : change;
    }
    // Newton method improves convergence.
    p = (p + q) / 2.0;
    iter++;
    assert(fabs(sum(p) - 1.0) < pTol); // double-check
  }
  assert(iter < iMax); // no way to recover
  return p;
}
示例#7
0
文件: rplib.cpp 项目: Eveyln74/KTAB
tuple <KMatrix, VUI> RPState::pDist(int persp) const {
    /// Calculate the probability distribution over states from this perspective

    // TODO: convert this to a single, commonly used setup function

    const unsigned int numA = model->numAct;
    const unsigned int numP = numA; // for this demo, the number of positions is exactly the number of actors

    // get unique indices and their probability
    assert (0 < uIndices.size()); // should have been set with setUENdx();
    //auto uNdx2 = uniqueNdx(); // get the indices to unique positions

    const unsigned int numU = uIndices.size();
    assert(numU <= numP); // might have dropped some duplicates

    cout << "Number of aUtils: " << aUtil.size() << endl << flush;

    const KMatrix u = aUtil[0]; // all have same beliefs in this demo

    auto uufn = [u, this](unsigned int i, unsigned int j1) {
        return u(i, uIndices[j1]);
    };

    auto uMat = KMatrix::map(uufn, numA, numU);
    auto vpm = VPModel::Linear;
    assert(uMat.numR() == numA); // must include all actors
    assert(uMat.numC() == numU);

    // vote_k ( i : j )
    auto vkij = [this, uMat](unsigned int k, unsigned int i, unsigned int j) {
        auto ak = (RPActor*)(model->actrs[k]);
        auto v_kij = Model::vote(ak->vr, ak->sCap, uMat(k, i), uMat(k, j));
        return v_kij;
    };

    // the following uses exactly the values in the given euMat,
    // which may or may not be square
    const KMatrix c = Model::coalitions(vkij, uMat.numR(), uMat.numC());
    const KMatrix pv = Model::vProb(vpm, c); // square
    const KMatrix p = Model::probCE(PCEModel::ConditionalPCM, pv); // column
    const KMatrix eu = uMat*p; // column

    assert(numA == eu.numR());
    assert(1 == eu.numC());

    return tuple <KMatrix, VUI>(p, uIndices);
}
示例#8
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
// returns a square matrix of prob(OptI > OptJ)
// these are assumed to be unique options.
// w is a [1,actor] row-vector of actor strengths, u is [act,option] utilities.
KMatrix Model::vProb(VotingRule vr, VPModel vpm, const KMatrix & w, const KMatrix & u) {
  // u_ij is utility to actor i of the position advocated by actor j
  unsigned int numAct = u.numR();
  unsigned int numOpt = u.numC();
  // w_j is row-vector of actor weights, for simple voting
  assert(numAct == w.numC()); // require 1-to-1 matching of actors and strengths
  assert(1 == w.numR()); // weights must be a row-vector

  auto vfn = [vr, &w, &u](unsigned int k, unsigned int i, unsigned int j) {
    double vkij = vote(vr, w(0, k), u(k, i), u(k, j));
    return vkij;
  };

  auto c = coalitions(vfn, numAct, numOpt); // c(i,j) = strength of coaltion for i against j
  KMatrix p = vProb(vpm, c);  // p(i,j) = prob Ai defeats Aj
  return p;
}
示例#9
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
// note that while the C_ij can be any arbitrary positive matrix
// with C_kk = 0, the p_ij matrix has the symmetry pij + pji = 1
// (and hence pkk = 1/2).
KMatrix Model::vProb(VPModel vpm, const KMatrix & c) {
  unsigned int numOpt = c.numR();
  assert(numOpt == c.numC());
  auto p = KMatrix(numOpt, numOpt);
  for (unsigned int i = 0; i < numOpt; i++) {
    for (unsigned int j = 0; j < i; j++) {
      double cij = c(i, j);
      assert(0 <= cij);
      double cji = c(j, i);
      assert(0 <= cji);
      assert((0 < cij) || (0 < cji));
      auto ppr = vProb(vpm, cij, cji);
      p(i, j) = get<0>(ppr); // set the lower left  probability: if Linear, cij / (cij + cji)
      p(j, i) = get<1>(ppr); // set the upper right probability: if Linear, cji / (cij + cji)
    }
    p(i, i) = 0.5; // set the diagonal probability
  }
  return p;
}
示例#10
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
// calculate the [option,1] column vector of option-probabilities.
// w is a [1,actor] row-vector of actor strengths, u is [act,option] utilities.
// This assumes scalar capabilities of actors (w), so that the voting strength
// is a direct function of difference in utilities.Therefore, we can use
// Model::vProb(VotingRule vr, const KMatrix & w, const KMatrix & u)
KMatrix Model::scalarPCE(unsigned int numAct, unsigned int numOpt, const KMatrix & w, const KMatrix & u,
                         VotingRule vr, VPModel vpm, PCEModel pcem, ReportingLevel rl) {

  // auto pv = Model::vProb(vr, vpm, w, u);
  // auto p = Model::probCE(pcem, pv);

  auto vfn = [vr, &w, &u](unsigned int k, unsigned int i, unsigned int j) {
    double vkij = vote(vr, w(0, k), u(k, i), u(k, j));
    return vkij;
  };
  const auto c = coalitions(vfn, numAct, numOpt); // c(i,j) = strength of coaltion for i against j
  const auto pv2 = Model::probCE2(pcem, vpm, c);
  const auto p = get<0>(pv2); //column
  const auto pv = get<1>(pv2); // square
  if (ReportingLevel::Low < rl) {
    printf("Num actors: %i \n", numAct);
    printf("Num options: %i \n", numOpt);


    if ((numAct <= 20) && (numOpt <= 20)) {
      cout << "Actor strengths: " << endl;
      w.mPrintf(" %6.2f ");
      cout << endl << flush;
      cout << "Voting rule: " << vr << endl;
      // printf("         aka %s \n", KBase::vrName(vr).c_str());
      cout << flush;
      cout << "Utility to actors of options: " << endl;
      u.mPrintf(" %+8.3f ");
      cout << endl << flush;

      cout << "Coalition strengths of (i:j): " << endl;
      c.mPrintf(" %8.3f ");
      cout << endl;

      cout << "Probability Opt_i > Opt_j" << endl;
      pv.mPrintf(" %.4f ");
      cout << "Probability Opt_i" << endl;
      p.mPrintf(" %.4f ");
    }
    cout << "Found stable PCE distribution" << endl << flush;
  }
  return p;
}
示例#11
0
文件: hcsearch.cpp 项目: KAPSARC/KTAB
vector<KMatrix> VHCSearch::vn1(const KMatrix & m0, double s) {
  unsigned int n = m0.numR();
  auto nghbrs = vector<KMatrix>();
  double pms[] = { -1, +1 };
  for (unsigned int i = 0; i < n; i++) {
    for (double si : pms) {
      KMatrix m1 = m0;
      m1(i, 0) = m0(i, 0) + (si*s);
      nghbrs.push_back(m1);
    }
  }
  return nghbrs;
}
示例#12
0
文件: rplib2.cpp 项目: KAPSARC/KTAB
void RP2Model::setWeights(const KMatrix & w0) {
  const unsigned int nr = w0.numR();
  const unsigned int nc = w0.numC();

  assert(1 == nr);

  if (0 < numAct) {
    assert(nc == numAct);
  }
  else {
    numAct = nc;
  }

  for (auto w : w0) {
    assert(0.0 <= w);
  }
  assert(minNumActor <= numAct);
  assert(numAct <= maxNumActor);

  // if it is OK, set it
  wghtVect = w0;
  return;
}
示例#13
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
// Given square matrix of Prob[i>j] returns a column vector for Prob[i].
// Uses 1-step conditional probabilities, not Markov process
KMatrix Model::condPCE(const KMatrix & pv) {
  unsigned int numOpt = pv.numR();
  auto p = KMatrix(numOpt, 1);
  for (unsigned int i = 0; i < numOpt; i++) {
    double pi = 1.0;
    for (unsigned int j = 0; j < numOpt; j++) {
      pi = pi * pv(i, j);
    }
    // double-check
    assert(0 <= pi);
    assert(pi <= 1);
    p(i, 0) = pi; // probability that i beats all alternatives
  }
  double probOne = sum(p); // probability that one option, any option, beats all alternatives
  p = (p / probOne); // conditional probability that i is that one.
  return p;
}
示例#14
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
tuple<KMatrix, KMatrix> Model::probCE2(PCEModel pcm, VPModel vpm, const KMatrix & cltnStrngth) {
  const double pTol = 1E-8;
  unsigned int numOpt = cltnStrngth.numR();
  auto p = KMatrix(numOpt, 1);
  const auto victProb = Model::vProb(vpm, cltnStrngth); // prob of victory, square
  switch (pcm) {
  case PCEModel::ConditionalPCM:
    p = condPCE(victProb);
    break;
  case PCEModel::MarkovIPCM:
    p = markovIncentivePCE(cltnStrngth, vpm);
    break;
  case PCEModel::MarkovUPCM:
    p = markovUniformPCE(victProb);
    break;
  default:
    throw KException("Model::probCE unrecognized PCEModel");
    break;
  }
  assert(numOpt == p.numR());
  assert(1 == p.numC());
  assert(fabs(sum(p) - 1.0) < pTol);
  return tuple<KMatrix, KMatrix>(p, victProb);
}
Parallel::Parallel(std::vector <MolState>& molStates, std::vector<int>& nm_list, 
		   double fcf_threshold, double temperature, 
		   int max_n_initial, int max_n_target, 
		   bool if_comb_bands, bool if_use_target_nm, bool if_print_fsfs, bool if_web_version, const char* nmoverlapFName,
		   double energy_threshold_initial,  double energy_threshold_target)
{

  int N = nm_list.size();
  double intens_threshold=fcf_threshold*fcf_threshold;

  //initial state index
  int  iniN=0;

  // full space size
  int n_norm_modes = molStates[iniN].NNormModes();

  //
  std::vector <int> state_ini, state_targ, state_ini_subspace, state_targ_subspace;
  for (int i=0; i<n_norm_modes; i++)
    {
      state_ini.push_back(-1);
      state_targ.push_back(-1);
    }

  //"excite subspace" size
  for (int i=0; i<nm_list.size(); i++) 
    {
      state_ini_subspace.push_back(-1);
      state_targ_subspace.push_back(-1);
    }

  // stores set of the inital and target vibrational states (for each electronic state) -- after energy threshold applied
  std::vector < std::vector <int> > selected_states_ini, selected_states_targ;
  
  // matrix with FC factors (use the same for every target state)
  KMatrix FCFs_tmp(max_n_initial+1,max_n_target+1);
  std::vector <KMatrix> FCFs;

  // matrix with intensities of FC transitions = FCFs*population_of_initial_vibrational_levels(Temperature distrib.)
  KMatrix I_tmp (max_n_initial+1,max_n_target+1);
  std::vector <KMatrix> I;

  // energy position of each transition for a given normal mode; 1D; ofset by IP; when add for N dimensiond, substract IP from each energy;
  KMatrix E_position_tmp (max_n_initial+1,max_n_target+1);
  std::vector <KMatrix> E_position;

  // reduced mass for FCF calcualtions -- mass weighted coordinates
  double reducedMass=1.0;

  // ==========================================================================================
  // Calculate transformation matrix "cartesian->normal mode" coordinates (for each state):
  std::vector <KMatrix> Cart2Normal_Rs;

  for (int state=0; state<molStates.size(); state++)
    {
      KMatrix NormModes( CARTDIM*(molStates[state].NAtoms()), molStates[state].NNormModes() ); // NOT mass weighted normal modes i.e. (L~)=T^(0.5)*L
      NormModes.Set(0.0);  
      //Get L (normal modes in cartesian coordinates mass unweighted (in Angstroms) ):
      for (int j=0; j < molStates[state].NAtoms(); j++) 
	for (int i = 0; i < molStates[state].NNormModes(); i++) 
	  for (int k=0; k < CARTDIM; k++)
	    NormModes.Elem2(j*CARTDIM+k, i) = molStates[state].getNormMode(i).getDisplacement()[j*CARTDIM+k];

      //Make squrt(T)-matrix (diagonal matrix with sqrt(atomic masses) in cartesian coordinates):
      KMatrix SqrtT( CARTDIM*(molStates[state].NAtoms()), CARTDIM*(molStates[state].NAtoms()), true);
      SqrtT.Set(0.0);
      for(int i=0; i<molStates[state].NAtoms(); i++)
	SqrtT.Elem2(i*CARTDIM,i*CARTDIM) = SqrtT.Elem2(i*CARTDIM+1,i*CARTDIM+1)= SqrtT.Elem2(i*CARTDIM+2,i*CARTDIM+2)=sqrt(molStates[state].getAtom(i).Mass());

      // Cart->NormalModes transformation matrix R=L^T*sqrt(T); 
      // q' = q+d = q+R*(x-x') (for the parallel normal mode approximation); 
      // units of d are Angstr*sqrt(amu)
      NormModes.Transpose(); 
      NormModes*=SqrtT;

      Cart2Normal_Rs.push_back(NormModes);
    }


  // Initial geometry in cartesian coordinates:
  KMatrix InitialCartCoord( CARTDIM*(molStates[iniN].NAtoms()), 1);
  for (int i=0; i<molStates[iniN].NAtoms(); i++)
    for (int k=0; k<CARTDIM; k++)
      InitialCartCoord[i*CARTDIM+k]=molStates[iniN].getAtom(i).Coord(k);
  InitialCartCoord.Scale(ANGSTROM2AU); 

  // initialize spectrlPoint: create vector of VibrQuantNumbers for the initital and target state 
  // (keep only non-zero qunta, i.e. from the "excite subspace")
  // Also add subspace mask (the rest of nmodes do not have excitations, and  would not be printers in the spectrum)
  SpectralPoint tmpPoint;
  for (int nm=0; nm<nm_list.size(); nm++)
    {
      tmpPoint.getVibrState1().addVibrQuanta(0, nm_list[nm]);
      tmpPoint.getVibrState2().addVibrQuanta(0, nm_list[nm]);
    }


  // For each target state, for each normal mode: calculate shoft, FCFs, prints spectrum
  for (int targN=1; targN < molStates.size(); targN++)
    {
      std::cout << "===== Target state #" << targN << " =====\n\n"<< std::flush;

      // clear the FC factors and related data
      FCFs.clear();
      I.clear();
      E_position.clear();
     
      //----------------------------------------------------------------------
      // calculate dQ:

      // Target state geometry in cartesian coordinates:
      KMatrix TargetCartCoord( CARTDIM*(molStates[iniN].NAtoms()), 1);
      for(int i=0; i<molStates[targN].NAtoms(); i++)
	for (int k=0; k <CARTDIM; k++)
	  TargetCartCoord[i*CARTDIM+k]=molStates[targN].getAtom(i).Coord(k);
  
      //input is in angstroms
      TargetCartCoord.Scale(ANGSTROM2AU);

      // Shift of the target state relative to the initial (In cart. coord.)
      TargetCartCoord -= InitialCartCoord;

      // Transform Cart_>normal Mode coordinates

      // Geometry differences in normal coordinates
      KMatrix NormModeShift_ini(molStates[iniN].NNormModes(), 1), NormModeShift_targ(molStates[iniN].NNormModes(), 1);
      NormModeShift_ini.Multiply( Cart2Normal_Rs[iniN], TargetCartCoord);
      NormModeShift_targ.Multiply(Cart2Normal_Rs[targN] , TargetCartCoord);
  
      // Rescale it back & print:
      NormModeShift_ini*=(AU2ANGSTROM);
      NormModeShift_targ*=(AU2ANGSTROM);

      std::cout<<"Difference (dQ) between the initial and the target state geometries.\n"
	       <<"Angstrom*sqrt(amu):\n\n";
      std::cout << "normal mode  dQ in initial  dQ in target   frequency   frequency   comments\n";
      std::cout << "  number      state coord.  state coord.    initial      target\n\n";
      for (int nm=0; nm<n_norm_modes; nm++)
	{
	  std::cout << "     " << std::fixed << std::setw(3) << nm <<"      " 
		    << std::setprecision(6) 
		    << std::setw(9) <<  NormModeShift_ini[nm] << "       " 
		    << std::setw(9) << NormModeShift_targ[nm] << "      " 
		    << std::setprecision(2) 
		    << std::setw(7) << molStates[iniN].getNormMode(nm).getFreq() << "    " 
		    << std::setw(7) << molStates[targN].getNormMode(nm).getFreq() << "\n";
	}
      std::cout<<"\n\n";

      
      //----------------------------------------------------------------------
      // save the spectrumnm overlap to file (for normal mode reordering tool in the web interface)
      if (if_web_version)
	{
	  std::vector <int> nondiagonal_list;
	  KMatrix NMoverlap;
	  bool if_overlap_diagonal=molStates[targN].getNormalModeOverlapWithOtherState(molStates[iniN], NMoverlap, nondiagonal_list);
   
	  std::ofstream nmoverlapF;     
	  nmoverlapF.open(nmoverlapFName, std::ios::out);
	  nmoverlapF << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
		     << "<nmoverlap\n  nm_initial=\"" <<n_norm_modes <<"\"\n  nm_target =\""<<n_norm_modes << "\">\n\n<nm_order_initial>\n";
	  //inital state's nm order -- 0,1,2... -- always!
	  for (int nm=0; nm<n_norm_modes; nm++)
	    nmoverlapF << "<oi" << nm << ">"<< molStates[iniN].getNormModeIndex(nm) << "</oi" << nm << ">\n";
	  nmoverlapF << "</nm_order_initial>\n\n<frequencies_initial>\n";
	  for (int nm=0; nm<n_norm_modes; nm++)
	    nmoverlapF << "<fi" << nm << ">"<< std::fixed << std::setprecision(1) << molStates[iniN].getNormMode(nm).getFreq()<< "</fi" << nm << ">\n";
	  nmoverlapF << "</frequencies_initial>\n\n<displacements_initial>\n";
	  for (int nm=0; nm<n_norm_modes; nm++)
	    nmoverlapF << "<dqi" << nm << ">"<< std::fixed << std::setprecision(2) << NormModeShift_ini[nm]<< "</dqi" << nm << ">\n";
	  nmoverlapF << "</displacements_initial>\n\n<nm_order_target>\n";
	  for (int nm=0; nm<n_norm_modes; nm++)
	    nmoverlapF << "<ot" << nm << ">"<< molStates[targN].getNormModeIndex(nm) << "</ot" << nm << ">\n";
	  nmoverlapF << "</nm_order_target>\n\n<frequencies_target>\n";
	  for (int nm=0; nm<n_norm_modes; nm++)
	    nmoverlapF << "<ft" << nm << ">"<< std::fixed << std::setprecision(1) << molStates[targN].getNormMode(nm).getFreq()<< "</ft" << nm << ">\n";
	  nmoverlapF << "</frequencies_target>\n\n<displacements_target>\n";
	  for (int nm=0; nm<n_norm_modes; nm++)
	    nmoverlapF << "<dqt" << nm << ">"<< std::fixed << std::setprecision(2) << NormModeShift_targ[nm]<< "</dqt" << nm << ">\n";
	  nmoverlapF << "</displacements_target>\n\n<overlap_matrix>\n";
	  for (int nmt=0; nmt<n_norm_modes; nmt++)
	    {    
	      nmoverlapF << "<row"<<nmt<<">\n";
	      for (int nmi=0; nmi<n_norm_modes; nmi++)
		nmoverlapF << "<c"<<nmi<<">"<< NMoverlap.Elem2(nmt,nmi)<<"</c"<<nmi<<">";
	      nmoverlapF << "\n</row"<<nmt<<">\n";
	    }
	  nmoverlapF << "</overlap_matrix>\n\n</nmoverlap>";
	  nmoverlapF.close();
	}
      //----------------------------------------------------------------------
      

      if (if_use_target_nm) 
	std::cout<<"TARGET state normal coordinates (displacements dQ) will be used.\n\n"; 
      else 
	std::cout<<"INITIAL state normal coordinates are used.\n\n"; 
      // ----------------------------------------------------------------------
    
      if (if_print_fsfs)
	std::cout << "Peak positions, Franck-Condon factors, and intensities along each normal mode:\n\n";

      // for each normal mode
      for (int nm=0; nm<n_norm_modes; nm++) //for each normal mode of the initial state
	{      
	  // Calculate the energy positions:
	  for (int i=0; i<max_n_initial+1; i++)
	    for (int j=0; j<max_n_target+1; j++)
	      // energy position of each transition for a given normal mode; 1D; ofset by IP; when add for N dimensiond, substract IP from each energy;
	      E_position_tmp.Elem2(i,j)=-molStates[targN].Energy()
		+(molStates[iniN].getNormMode(nm).getFreq() * i
		  -molStates[targN].getNormMode(nm).getFreq() * j) * WAVENUMBERS2EV;
	  E_position.push_back(E_position_tmp);
	      
	  // Calculate the Franck-Condon factors
	  if (if_use_target_nm) // which normal modes (displacements) to use: of the initial or the target state?
	    harmonic_FCf(FCFs_tmp,reducedMass, NormModeShift_targ[nm],
			 molStates[iniN].getNormMode(nm).getFreq(), 
			 molStates[targN].getNormMode(nm).getFreq());
	  else
	    harmonic_FCf(FCFs_tmp,reducedMass, NormModeShift_ini[nm],
			 molStates[iniN].getNormMode(nm).getFreq(), 
			 molStates[targN].getNormMode(nm).getFreq());
	  
	  FCFs.push_back(FCFs_tmp);
	  
	  //Calculate the line intensities (FCF^2 *  the temperature distribution in the initial state):
	  for (int i=0; i<max_n_initial+1; i++)
	    { 
	      double IExponent=100*i; //(intensity < 10e-44 for non ground states if temperature=0)
	      if (temperature>0)
		{
		  IExponent= molStates[iniN].getNormMode(nm).getFreq()*WAVENUMBERS2EV * i 
		    / (temperature * KELVINS2EV );
		  if (IExponent > 100) 
		    IExponent=100; // keep the intensity >= 10e-44 == exp(-100)
		}

	      for (int j=0; j<max_n_target+1; j++)
		I_tmp.Elem2(i,j)=FCFs_tmp.Elem2(i,j) * FCFs_tmp.Elem2(i,j) * exp ( -IExponent);
	    }
	  I.push_back(I_tmp);

	  if (if_print_fsfs)
	    {
	      std::cout << "NORMAL MODE #" << nm+0 
			<<" (" << std::fixed << std::setw(8) << std::setprecision(2)
			<< molStates[iniN].getNormMode(nm).getFreq() << "cm-1 --> " 
			<<molStates[targN].getNormMode(nm).getFreq() << "cm-1, dQ="
			<< std::setw(6) << std::setprecision(4);
	      if (if_use_target_nm)
		std::cout << NormModeShift_targ[nm];
	      else
		std::cout << NormModeShift_ini[nm];
	      std::cout << ")\n";
	      
	      
	      E_position[nm].Print("Peak positions, eV");
	      FCFs[nm].PrintScientific("1D Harmonic Franck-Condon factors");  
	      I[nm].Print("Intensities (FCFs^2)*(initial vibrational states termal population)");
	    }
      
	} // end for each normal mode


      //================================================================================
      // evaluate the overal intensities as all possible products of 1D intensities (including combination bands)
      std::cout << "Maximum number of vibrational excitations: " << max_n_initial << " and "<< max_n_target 
		<< "\n in the initial and each target state, respectively.\n\n";

      unsigned long total_combs_ini=0, total_combs_targ=0;
      for (int curr_max_ini=0; curr_max_ini<=max_n_initial; curr_max_ini++)
	total_combs_ini += Combination(  (curr_max_ini + nm_list.size() - 1), (nm_list.size() - 1)  );
      for (int curr_max_targ=0; curr_max_targ<=max_n_target; curr_max_targ++)
	total_combs_targ += Combination(  (curr_max_targ + nm_list.size() -1), (nm_list.size() - 1)  );
      
      std::cout << "Maximum number of combination bands = " << total_combs_ini*total_combs_targ  
		<< "\n   = " << total_combs_ini << " (# of vibrational states in the initial electronic state)"
		<< "\n   * " << total_combs_targ  << " (# of vibrational states in the target electronic state)\n\n" << std::flush;
      
      for (int i=0; i<state_ini_subspace.size(); i++)
	state_ini_subspace[i]=-1;
      for (int i=0; i<state_targ_subspace.size(); i++)
	state_targ_subspace[i]=-1;

      // find INITIAL states with up to 'max_n_initial' vibrational quanta and with energy below 'energy_threshold_initial':
      std::cout << "A set of initial vibrational states is being created...\n";
      if (energy_threshold_initial < DBL_MAX)    
	std::cout << "  energy threshold = " << std::fixed << energy_threshold_initial <<" eV ("<< energy_threshold_initial/KELVINS2EV <<" K)\n" << std::flush;
      else
	std::cout << "  energy threshold is not specified in the input\n"<<std::flush;
      //      std::cout << "NOTE: ezSpectrum may crash at this point if memory is insufficient to store\n"
      //        	 <<"      all vibrational states. If so, please reduce the initial state's energy\n"
      //		 <<"      threshold or max_vibr_excitations_in_initial_el_state\n\n" << std::flush;

      selected_states_ini.clear();
      for (int curr_max_ini=0; curr_max_ini<=max_n_initial; curr_max_ini++)
	{
	  while (enumerateVibrStates(state_targ_subspace.size(), curr_max_ini, state_ini_subspace, if_comb_bands))
	    {
	      // reset the index list state_ini
	      for (int nm=0; nm < state_ini.size(); nm++)
		state_ini[nm]=0;

	      //copy indexes from the subspace state_ini_subspace into the full space state_ini (the rest stays=0):
	      int index=0;
	      for (int nm=0; nm<nm_list.size(); nm++)
		state_ini[ nm_list[nm] ] = state_ini_subspace[nm];


	      double energy = 0;

	      for (int nm=0; nm < n_norm_modes; nm++) 
		energy += E_position[nm].Elem2(state_ini[nm],0)+molStates[targN].Energy(); 

	      if (energy < energy_threshold_initial)
		{
		  // check memory available (dirty, but anyway one copying of the state is requared...)
		  //int * buffer = (int*) malloc ( sizeof(int)*n_norm_modes*100 );
		  //if (buffer==NULL)
		  //  {
		  //    std::cout << "\nError: not enough memory available to store all initial vibrational states\n\n";
		  //    exit(2);
		  //  }
		  //free(buffer);

		  selected_states_ini.push_back(state_ini);
		}

	    }
	  //reset the initial state's vibration "population"

	  state_ini_subspace[0]=-1;
	}
      std::cout << "  " << selected_states_ini.size() << " vibrational states below the energy threshold\n\n"<<std::flush;


      // find TARGET states with up to 'max_n_target' vibrational quanta and with energy below 'energy_threshold_target':
      std::cout << "A set of target vibrational states is being created...\n";
      if (energy_threshold_target < DBL_MAX)
	std::cout << "  energy threshold = " << std::fixed <<energy_threshold_target <<" eV ("<< energy_threshold_target/WAVENUMBERS2EV <<" cm-1)\n"<<std::flush;
      else
	std::cout << "  energy threshold is not specified in the input\n"<<std::flush;
      //  std::cout << "NOTE: ezSpectrum may crash at this point if memory is insufficient to store\n"
      //   	 <<"      all vibrational states. If so, please reduce the target state's energy\n"
      //		 <<"      threshold or max_vibr_excitations_in_target_el_state\n\n" << std::flush;

      selected_states_targ.clear();
      for (int curr_max_targ=0; curr_max_targ<=max_n_target; curr_max_targ++)
	{
	  while (enumerateVibrStates(state_targ_subspace.size(), curr_max_targ, state_targ_subspace, if_comb_bands))
	    {
	      // reset the index list state_targ
	      for (int nm=0; nm < state_targ.size(); nm++)
		state_targ[nm]=0;
	      //copy indexes from the subspace state_targ_subspace into the full space state_targ (the rest stays=0):
	      int index=0;
	      for (int nm=0; nm<nm_list.size(); nm++)
		state_targ[ nm_list[nm] ] = state_targ_subspace[nm];


	      double energy = 0;

	      for (int nm=0; nm < n_norm_modes; nm++)
		// threshold -- energy above the ground state:
		energy += E_position[nm].Elem2(0,state_targ[nm])+molStates[targN].Energy(); 

	      if ( -energy < energy_threshold_target )
		{
		  // check memory available (dirty, but anyway one copying of the state is requared...)
		  //VibronicState * state_tmp = (VibronicState*) malloc ( sizeof(VibronicState)*2 );
		  //if (state_tmp==NULL)
		  //  {
		  //    std::cout << "\nError: not enough memory available to store all target vibrational states\n\n";
		  //    exit(2);
		  //  }
		  //free (state_tmp);
		  
		  selected_states_targ.push_back(state_targ);
		}


	    }
	  //reset the target state's vibration "population"
	  state_targ_subspace[0]=-1;
	}

      std::cout << "  " << selected_states_targ.size() << " vibrational states below the energy threshold\n\n";

      std::cout << "Total number of combination bands with thresholds applied: " << selected_states_ini.size()*selected_states_targ.size() <<"\n\n"<<std::flush;

      std::cout << "Intensities of combination bands are being calculated...\n" <<std::flush;

      for (int curr_ini=0; curr_ini<selected_states_ini.size(); curr_ini++)
	for (int curr_targ=0; curr_targ<selected_states_targ.size(); curr_targ++)
	  {
	    double intens = 1;
	    double FCF = 1;
	    double energy = -molStates[targN].Energy();
	    double E_prime_prime = 0;

	    for (int nm=0; nm < n_norm_modes; nm++)
	      {
		intens *= I[nm].Elem2(selected_states_ini[curr_ini][nm],selected_states_targ[curr_targ][nm]);
		FCF *= FCFs[nm].Elem2(selected_states_ini[curr_ini][nm],selected_states_targ[curr_targ][nm]);
		energy += E_position[nm].Elem2(selected_states_ini[curr_ini][nm],selected_states_targ[curr_targ][nm])+molStates[targN].Energy(); 
		E_prime_prime += E_position[nm].Elem2(selected_states_ini[curr_ini][nm],0)+molStates[targN].Energy(); 
		// [ cancell the IE in each energy, which is stupid but inexpensive; probably should be eliminated ]
	      }
	    
	    // add the point to the spectrum if its intensity is above the threshold
	    if (intens > intens_threshold)
	      {
		tmpPoint.getIntensity() = intens;
		tmpPoint.getEnergy() = energy;
		tmpPoint.getE_prime_prime()= E_prime_prime;
		tmpPoint.getFCF()= FCF;
		tmpPoint.getVibrState1().reset();
		tmpPoint.getVibrState1().setElStateIndex(0);
		tmpPoint.getVibrState2().reset();
		tmpPoint.getVibrState2().setElStateIndex(targN);
		for (int nm=0; nm<nm_list.size(); nm++)
		  {
		    tmpPoint.getVibrState1().setVibrQuanta(nm, selected_states_ini[curr_ini][  nm_list[nm]  ]);
		    tmpPoint.getVibrState2().setVibrQuanta(nm, selected_states_targ[curr_targ][  nm_list[nm]  ]);
		  }
		spectrum.AddSpectralPoint( tmpPoint );
	      }
	  }
    } // end for each target state
}
示例#16
0
文件: rplib.cpp 项目: Eveyln74/KTAB
RPState* RPState::doSUSN(ReportingLevel rl) const {
    RPState* s2 = nullptr;
    const unsigned int numA = model->numAct;
    assert(numA == rpMod->actrs.size());

    const unsigned int numU = uIndices.size();
    assert ((0 < numU) && (numU <= numA));
    assert (numA == eIndices.size());

    // TODO: filter out essentially-duplicate positions
    //printf("RPState::doSUSN: numA %i \n", numA);
    //printf("RPState::doSUSN: numP %i \n", numP);
    //cout << endl << flush;

    const KMatrix u = aUtil[0]; // all have same beliefs in this demo

    auto vpm = VPModel::Linear;
    const unsigned int numP = pstns.size();
    // Given the utility matrix, uMat, calculate the expected utility to each actor,
    // as a column-vector. Again, this is from the perspective of whoever developed uMat.
    auto euMat = [rl, numA, numP, vpm, this](const KMatrix & uMat) {
        // BTW, be sure to lambda-bind uMat *after* it is modified.
        assert(uMat.numR() == numA); // must include all actors
        assert(uMat.numC() <= numP); // might have dropped some duplicates
        auto uRng = [uMat](unsigned int i, unsigned int j) {
            if ((uMat(i, j) < 0.0) || (1.0 < uMat(i, j))) {
                printf("%f  %i  %i  \n", uMat(i, j), i, j);
                cout << flush;
                cout << flush;

            }
            assert(0.0 <= uMat(i, j));
            assert(uMat(i, j) <= 1.0);
            return;
        };
        KMatrix::mapV(uRng, uMat.numR(), uMat.numC());
        // vote_k ( i : j )
        auto vkij = [this, uMat](unsigned int k, unsigned int i, unsigned int j) {
            auto ak = (RPActor*)(rpMod->actrs[k]);
            auto v_kij = Model::vote(ak->vr, ak->sCap, uMat(k, i), uMat(k, j));
            return v_kij;
        };

        // the following uses exactly the values in the given euMat,
        // which may or may not be square
        const KMatrix c = Model::coalitions(vkij, uMat.numR(), uMat.numC());
        const KMatrix pv = Model::vProb(vpm, c); // square
        const KMatrix p = Model::probCE(PCEModel::ConditionalPCM, pv); // column
        const KMatrix eu = uMat*p; // column

        assert(numA == eu.numR());
        assert(1 == eu.numC());
        auto euRng = [eu](unsigned int i, unsigned int j) {
            // due to round-off error, we must have a tolerance factor
            const double tol = 1E-10;
            const double euij = eu(i, j);
            assert(0.0 <= euij+tol);
            assert(euij <= 1.0+tol);
            return;
        };
        KMatrix::mapV(euRng, eu.numR(), eu.numC());


        if (ReportingLevel::Low < rl) {
            printf("Util matrix is %i x %i \n", uMat.numR(), uMat.numC());
            cout << "Assessing EU from util matrix: " << endl;
            uMat.mPrintf(" %.6f ");
            cout << endl << flush;

            cout << "Coalition strength matrix" << endl;
            c.mPrintf(" %12.6f ");
            cout << endl << flush;

            cout << "Probability Opt_i > Opt_j" << endl;
            pv.mPrintf(" %.6f ");
            cout << endl << flush;

            cout << "Probability Opt_i" << endl;
            p.mPrintf(" %.6f ");
            cout << endl << flush;

            cout << "Expected utility to actors: " << endl;
            eu.mPrintf(" %.6f ");
            cout << endl << flush;
        }

        return eu;
    };
    // end of euMat

    auto euState = euMat(u);
    cout << "Actor expected utilities: ";
    KBase::trans(euState).mPrintf("%6.4f, ");
    cout << endl << flush;

    if (ReportingLevel::Low < rl) {
        printf("--------------------------------------- \n");
        printf("Assessing utility of actual state to all actors \n");
        for (unsigned int h = 0; h < numA; h++) {
            cout << "not available" << endl;
        }
        cout << endl << flush;
        printf("Out of %u positions, %u were unique: ", numA, numU);
        cout << flush;
        for (auto i : uIndices) {
            printf("%2i ", i);
        }
        cout << endl;
        cout << flush;
    }


    auto uufn = [u, this](unsigned int i, unsigned int j1) {
        return u(i, uIndices[j1]);
    };
    auto uUnique = KMatrix::map(uufn, numA, numU);


    // Get expected-utility vector, one entry for each actor, in the current state.
    const KMatrix eu0 = euMat(uUnique); // 'u' with duplicates, 'uUnique' without duplicates

    s2 = new RPState(model);

    //s2->pstns = vector<KBase::Position*>();
    for (unsigned int h = 0; h < numA; h++) {
        s2->pstns.push_back(nullptr);
    }

    // TODO: clean up the nesting of lambda-functions.
    // need to create a hypothetical state and run setOneAUtil(h,Silent) on it
    //
    // The newPosFn does a GA optimization to find the best next position for actor h,
    // and stores it in s2. To do that, it defines three functions for evaluation, neighbors, and show:
    // efn, nfn, and sfn.
    auto newPosFn = [this, rl, euMat, u, eu0, s2](const unsigned int h) {
        s2->pstns[h] = nullptr;

        auto ph = ((const MtchPstn *)(pstns[h]));

        // Evaluate h's estimate of the expected utility, to h, of
        // advocating position mp. To do this, build a hypothetical utility matrix representing
        // h's estimates of the direct utilities to all other actors of h adopting this
        // Position. Do that by modifying the h-column of h's matrix.
        // Then compute the expected probability distribution, over h's hypothetical position
        // and everyone else's actual position. Finally, compute the expected utility to
        // each actor, given that distribution, and pick out the value for h's expected utility.
        // That is the expected value to h of adopting the position.
        auto efn = [this, euMat, rl, u, h](const MtchPstn & mph) {
            // This correctly handles duplicated/unique options
            // We modify the given euMat so that the h-column
            // corresponds to the given mph, but we need to prune duplicates as well.
            // This entails some type-juggling.
            const KMatrix uh0 = aUtil[h];
            assert(KBase::maxAbs(u - uh0) < 1E-10); // all have same beliefs in this demo
            if (mph.match.size() != rpMod->numItm) {
                cout << mph.match.size() << endl << flush;
                cout << rpMod->numItm << endl << flush;
                cout << flush << flush;
            }
            assert(mph.match.size() == rpMod->numItm);
            auto uh = uh0;
            for (unsigned int i = 0; i < rpMod->numAct; i++) {
                auto ai = (RPActor*)(rpMod->actrs[i]);
                double uih = ai->posUtil(&mph);
                uh(i, h) = uih; // utility to actor i of this hypothetical position by h
            }

            // 'uh' now has the correct h-column. Now we need to see how many options
            // are unique in the hypothetical state, and keep only those columns.
            // This entails juggling back and forth between the all current positions
            // and the one hypothetical position (mph at h).
            // Thus, the next call to euMat will consider only unique options.
            auto equivHNdx = [this, h, mph](const unsigned int i, const unsigned int j) {
                // this little function takes care of the different types needed to compare
                // dynamic pointers to positions (all but h) with a constant position (h itself).
                // In other words, the comparisons for index 'h' use the hypothetical mph, not pstns[h]
                bool rslt = false;
                auto mpi = ((const MtchPstn *)(pstns[i]));
                auto mpj = ((const MtchPstn *)(pstns[j]));
                assert(mpi != nullptr);
                assert(mpj != nullptr);
                if (i == j) {
                    rslt = true; // Pi == Pj, always
                }
                else if (h == i) {
                    rslt = (mph == (*mpj));
                }
                else if (h == j) {
                    rslt = ((*mpi) == mph);
                }
                else {
                    rslt = ((*mpi) == (*mpj));
                }
                return rslt;
            };

            auto ns = KBase::uiSeq(0, model->numAct - 1);
            const VUI uNdx = get<0>(KBase::ueIndices<unsigned int>(ns, equivHNdx));
            const unsigned int numU = uNdx.size();
            auto hypUtil = KMatrix(rpMod->numAct, numU);
            // we need now to go through 'uh', copying column J the first time
            // the J-th position is determined to be equivalent to something in the unique list
            for (unsigned int i = 0; i < rpMod->numAct; i++) {
                for (unsigned int j1 = 0; j1 < numU; j1++) {
                    unsigned int j2 = uNdx[j1];
                    hypUtil(i, j1) = uh(i, j2); // hypothetical utility in column h
                }
            }

            if (false) {
                cout << "constructed hypUtil matrix:" << endl << flush;
                hypUtil.mPrintf(" %8.2f ");
                cout << endl << flush;
            }


            if (ReportingLevel::Low < rl) {
                printf("--------------------------------------- \n");
                printf("Assessing utility to %2i of hypo-pos: ", h);
                printPerm(mph.match);
                cout << endl << flush;
                printf("Hypo-util minus base util: \n");
                (uh - uh0).mPrintf(" %+.4E ");
                cout << endl << flush;
            }
            const KMatrix eu = euMat(hypUtil); // uh or hypUtil
            // BUG: If we use 'uh' here, it passes the (0 <= delta-EU) test, because
            // both hypothetical and actual are then calculated without dropping duplicates.
            // If we use 'hypUtil' here, it sometimes gets (delta-EU < 0), because
            // the hypothetical drops duplicates but the actual (computed elsewhere) does not.
            // FIX: fix  the 'elsewhere'
            const double euh = eu(h, 0);
            assert(0 < euh);
            //cout << euh << endl << flush;
            //printPerm(mp.match);
            //cout << endl << flush;
            //cout << flush;
            return euh;
        }; // end of efn

        /*
                // I do not actually use prevMP, but it is still an example for std::set
                auto prevMP = [](const MtchPstn & mp1, const MtchPstn & mp2) {
                    bool r = std::lexicographical_compare(
                                 mp1.match.begin(), mp1.match.end(),
                                 mp2.match.begin(), mp2.match.end());
                    return r;
                };
                std::set<MtchPstn, bool(*)(const MtchPstn &, const MtchPstn &)> mpSet(prevMP);
        */

        // return vector of neighboring 1-permutations
        auto nfn = [](const MtchPstn & mp0) {
            const unsigned int numI = mp0.match.size();
            auto mpVec = vector <MtchPstn>();
            mpVec.push_back(MtchPstn(mp0));

            // one-permutations
            for (unsigned int i = 0; i < numI; i++) {
                for (unsigned int j = i + 1; j < numI; j++) {
                    unsigned int ei = mp0.match[i];
                    unsigned int ej = mp0.match[j];

                    auto mij = MtchPstn(mp0);
                    mij.match[i] = ej;
                    mij.match[j] = ei;
                    mpVec.push_back(mij);
                }
            }


            // two-permutations
            for (unsigned int i = 0; i < numI; i++) {
                for (unsigned int j = i + 1; j < numI; j++) {
                    for (unsigned int k = j + 1; k < numI; k++) {
                        unsigned int ei = mp0.match[i];
                        unsigned int ej = mp0.match[j];
                        unsigned int ek = mp0.match[k];

                        auto mjki = MtchPstn(mp0);
                        mjki.match[i] = ej;
                        mjki.match[j] = ek;
                        mjki.match[k] = ei;
                        mpVec.push_back(mjki);

                        auto mkij = MtchPstn(mp0);
                        mkij.match[i] = ek;
                        mkij.match[j] = ei;
                        mkij.match[k] = ej;
                        mpVec.push_back(mkij);

                    }
                }
            }
            //unsigned int mvs = mpVec.size() ;
            //cout << mvs << endl << flush;
            //cout << flush;
            return mpVec;
        }; // end of nfn

        // show some representation of this position on cout
        auto sfn = [](const MtchPstn & mp0) {
            printPerm(mp0.match);
            return;
        };

        auto ghc = new KBase::GHCSearch<MtchPstn>();
        ghc->eval = efn;
        ghc->nghbrs = nfn;
        ghc->show = sfn;

        auto rslt = ghc->run(*ph, // start from h's current positions
                             ReportingLevel::Silent,
                             100, // iter max
                             3, 0.001); // stable-max, stable-tol

        if (ReportingLevel::Low < rl) {
            printf("---------------------------------------- \n");
            printf("Search for best next-position of actor %2i \n", h);
            //printf("Search for best next-position of actor %2i starting from ", h);
            //trans(*aPos).printf(" %+.6f ");
            cout << flush;
        }

        double vBest = get<0>(rslt);
        MtchPstn pBest = get<1>(rslt);
        unsigned int iterN = get<2>(rslt);
        unsigned int stblN = get<3>(rslt);

        delete ghc;
        ghc = nullptr;
        if (ReportingLevel::Medium < rl) {
            printf("Iter: %u  Stable: %u \n", iterN, stblN);
            printf("Best value for %2i: %+.6f \n", h, vBest);
            cout << "Best position:    " << endl;
            cout << "numCat: " << pBest.numCat << endl;
            cout << "numItm: " << pBest.numItm << endl;
            cout << "perm: ";
            printPerm(pBest.match);
            cout << endl << flush;
        }
        MtchPstn * posBest = new MtchPstn(pBest);
        s2->pstns[h] = posBest;
        // no need for mutex, as s2->pstns is the only shared var,
        // and each h is different.

        double du = vBest - eu0(h, 0); // (hypothetical, future) - (actual, current)
        if (ReportingLevel::Low < rl) {
            printf("EU improvement for %2i of %+.4E \n", h, du);
        }
        //printf("  vBest = %+.6f \n", vBest);
        //printf("  eu0(%i, 0) for %i = %+.6f \n", h, h, eu0(h,0));
        //cout << endl << flush;
        // Logically, du should always be non-negative, as GHC never returns a worse value than the starting point.
        // However, actors plan on the assumption that all others do not change - yet they do.
        const double eps = 0.05; // 0.025; // enough to avoid problems with round-off error
        assert(-eps <= du);
        return;
    }; // end of newPosFn

    const bool par = true;
    auto ts = vector<thread>();
    // Each actor, h, finds the position which maximizes their EU in this situation.
    for (unsigned int h = 0; h < numA; h++) {
        if (par) { // launch all, concurrent
            ts.push_back(thread([newPosFn, h]() {
                newPosFn(h);
                return;
            }));
        }
        else { // do each, sequential
            newPosFn(h);
        }
    }

    if (par) { // now join them all before continuing
        for (auto& t : ts) {
            t.join();
        }
    }

    assert(nullptr != s2);
    assert(numP == s2->pstns.size());
    assert(numA == s2->model->numAct);
    for (auto p : s2->pstns) {
        assert(nullptr != p);
    }
    s2->setUENdx();
    return s2;
}
示例#17
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;
}
示例#18
0
文件: kmodel.cpp 项目: KAPSARC/KTAB
// Given square matrix of strengths, Coalition[i over j] returns a column vector for Prob[i].
// Uses Markov process, not 1-step conditional probability.
// Challenge probabilities are proportional to influence promoting a challenge
KMatrix Model::markovIncentivePCE(const KMatrix & coalitions, VPModel vpm) {
  using KBase::sqr;
  using KBase::qrtc;
  const bool printP = false;
  const double pTol = 1E-8;
  const unsigned int numOpt = coalitions.numR();
  assert(numOpt == coalitions.numC());

  const auto victProbMatrix = vProb(vpm, coalitions);

  // given coalitions, calculate the total incentive for i to challenge j
  // This is n[ i -> j] in the "Markov Voting with Incentives in KTAB" paper
  auto iFn = [victProbMatrix, coalitions](unsigned int i, unsigned int j) {
    const double epsSupport = 1E-10;
    const double sij = coalitions(i, j);
    double inctv = sij * victProbMatrix(i,j);
    if (i == j) {
      inctv = inctv + epsSupport;
    }
    return inctv;
  };

  const auto inctvMatrix = KMatrix::map(iFn, numOpt, numOpt);

  // Using the incentives, calculate the probability of i challenging j,
  // given that j is the current favorite proposal.
  // This is P[ i -> j] in the "Markov Voting with Incentives in KTAB" paper
  // Note that if every actor prefers j to every other option,
  // then all incentive(i,j) will be zero, except incentive(j,j) = eps.
  // Even in this case, we will not get a division by zero error,
  // and it will correctly return that the only "challenger" is j itself,
  // with guaranteed success.
  //
  auto cpFn = [inctvMatrix, numOpt](unsigned int i, unsigned int j) {
    double sum = 0.0;
    for (unsigned int k = 0; k < numOpt; k++) {
      sum = sum + inctvMatrix(k, j);
    }
    const double pij = inctvMatrix(i, j) / sum;
    return pij;
  };

  const auto chlgProbMatrix = KMatrix::map(cpFn, numOpt, numOpt);

  // probability starts as uniform distribution (column vector)
  auto p = KMatrix(numOpt, 1, 1.0) / numOpt;  // all 1/n
  auto q = p;
  unsigned int iMax = 1000;  // 10-30 is typical
  unsigned int iter = 0;
  double change = 1.0;

  // do the markov calculation
  while (pTol < change)  { // && (iter < iMax)
    if (printP) {
      printf("Iteration  %u / %u \n", iter, iMax);
      cout << "pDist:" << endl;
      trans(p).mPrintf(" %.4f");
      cout << endl;
      printf("change: %.4e \n", change);
      cout << endl << flush;
    }
    auto ct = KMatrix(numOpt, numOpt);
    for (unsigned int i = 0; i < numOpt; i++) {
      for (unsigned int j = 0; j < numOpt; j++) {
        // See "Markov Voting with Incentives in KTAB" paper
        ct(i, j) = p(i, 0) * chlgProbMatrix(j, i);
      }
    }
    if (printP) {
      cout << "Ct:" << endl;
      ct.mPrintf("  %.3f");
      cout << endl << flush;
    }
    change = 0.0;
    for (unsigned int i = 0; i < numOpt; i++) {
      double qi = 0.0;
      for (unsigned int j = 0; j < numOpt; j++) {
        double vij = victProbMatrix(i, j);
        double cj = ct(i, j) + ct(j, i);
        qi = qi + vij* cj;
      }
      assert(0 <= qi); // double-check
      q(i, 0) = qi;
      double c = fabs(q(i, 0) - p(i, 0));
      change = (c > change) ? c : change;
    }
    // Newton method improves convergence.
    p = (p+q)/2.0;
    iter++;
    assert(fabs(sum(p) - 1.0) < pTol); // double-check
  }

  assert(iter < iMax); // no way to recover
  return p;
}