-rw-r--r-- 4285 cryptattacktester-20231020/searchparams.cpp raw
#include <iostream>
#include <set>
#include <map>
#include "bigint.h"
#include "problem.h"
#include "attack.h"
#include "selection.h"
using namespace std;
struct evaluation {
  bigint cost;
  bigfloat prob;
  bigfloat lgcost;
  bigfloat lgprob;
  bigfloat lgratio;
  evaluation(const vector<bigint> &P,const attack &A,const vector<bigint> &Q) :
    cost(A.cost(P,Q)),
    prob(A.prob(P,Q)),
    lgcost(log2(bigfloat(cost))),
    lgprob(log2(prob)),
    lgratio(lgcost-lgprob)
  {
  }
} ;
#define MODS 6
static vector<bigint> modification(const vector<bigint> &Q,bigint pos,bigint mod)
{
  auto result = Q;
  if (mod == 0) result.at(pos) = Q.at(pos)*2;
  if (mod == 1) result.at(pos) = Q.at(pos)/2;
  if (mod == 2) result.at(pos) = (Q.at(pos)*3)/2;
  if (mod == 3) result.at(pos) = (Q.at(pos)*2+1)/3;
  if (mod == 4) result.at(pos) = Q.at(pos)+1;
  if (mod == 5) result.at(pos) = Q.at(pos)-1;
  return result;
}
static void printevaluation(const std::string &prefix,const problem &C,const vector<bigint> &P,const attack &A,const vector <bigint> &Q,const evaluation &E)
{
  cout << prefix;
  cout << " problem=" << C.name;
  for (bigint j = 0;j < P.size();++j)
    cout << (j ? ',' : ' ') << C.paramnames.at(j) << "=" << P.at(j);
  cout << " attack=" << A.name;
  for (bigint j = 0;j < Q.size();++j)
    cout << (j ? ',' : ' ') << A.paramnames.at(j) << "=" << Q.at(j);
  cout << " lgratio " << E.lgratio;
  cout << " cost " << E.cost;
  cout << " lgcost " << E.lgcost;
  cout << " prob " << E.prob;
  cout << " lgprob " << E.lgprob;
  cout << '\n' << flush;
}
int attack_handle(const problem &C,const vector<bigint> &P,const attack &A,const vector<bigint> &Qorig)
{
  if (!A.params_valid) return -1;
  vector<bigint> Q = Qorig;
  selection_type S = attack_selection;
  vector<bool> canchange(Q.size(),1); // becomes 0 if S prohibits a change
  set<vector<bigint>> Qevaluated;
  bigint printallevaluations = 0;
  selection_constrain(S,"printallevaluations",printallevaluations,printallevaluations);
  bigfloat epsilon = 1/512.0;
  Qevaluated.insert(Q);
  evaluation E = evaluation(P,A,Q);
  if (printallevaluations) printevaluation("evaluation",C,P,A,Q,E);
  for (;;) {
    printevaluation("searchparams",C,P,A,Q,E);
    auto Qbest = Q;
    auto Ebest = E;
    for (bigint pos = 0;pos < Q.size();++pos) {
      if (!canchange.at(pos)) continue;
      for (bigint mod = 0;mod < MODS;++mod) {
        auto Qnew = modification(Q,pos,mod);
        if (Qevaluated.count(Qnew) > 0) continue; // saw already
        if (!A.params_valid(P,Qnew)) continue;
        if (!selection_allows(S,A.paramnames.at(pos),Qnew.at(pos).get_str())) {
          canchange.at(pos) = 0;
          break;
        }
        Qevaluated.insert(Qnew);
        evaluation Enew(P,A,Qnew);
        if (printallevaluations) printevaluation("evaluation",C,P,A,Qnew,Enew);
        if (Enew.lgratio.definitely_less(Ebest.lgratio)) {
          Ebest = Enew;
          Qbest = Qnew;
        }
      }
    }
    if ((Ebest.lgratio+epsilon).definitely_less(E.lgratio)) {
      Q = Qbest;
      E = Ebest;
      continue;
    }
    Qbest = Q;
    Ebest = E;
    for (bigint pos1 = 0;pos1 < Q.size();++pos1) {
      if (!canchange.at(pos1)) continue;
      for (bigint mod1 = 0;mod1 < MODS;++mod1) {
        auto Q1 = modification(Q,pos1,mod1);
        for (bigint pos2 = pos1;pos2 < Q.size();++pos2) {
          if (!canchange.at(pos2)) continue;
          for (bigint mod2 = 0;mod2 < MODS;++mod2) {
            auto Qnew = modification(Q1,pos2,mod2);
            if (Qevaluated.count(Qnew) > 0) continue;
            if (!A.params_valid(P,Qnew)) continue;
            if (!selection_allows(S,A.paramnames.at(pos1),Qnew.at(pos1).get_str())) continue;
            if (!selection_allows(S,A.paramnames.at(pos2),Qnew.at(pos2).get_str())) continue;
            Qevaluated.insert(Qnew);
            evaluation Enew(P,A,Qnew);
            if (printallevaluations) printevaluation("evaluation",C,P,A,Qnew,Enew);
            if (Enew.lgratio.definitely_less(Ebest.lgratio)) {
              Ebest = Enew;
              Qbest = Qnew;
            }
          }
        }
      }
    }
    if ((Ebest.lgratio+epsilon).definitely_less(E.lgratio)) {
      Q = Qbest;
      E = Ebest;
      continue;
    }
    return -1;
  }
}