// Copyright (c) 2003 Nick Mathewson.  See LICENSE for licensing information.
// $Id: simmain.cpp 1341 2004-09-13 18:47:46Z nickm $
#include <vector>
#include <algorithm>
#include <iostream>
#include <string>
#include "sim.h"
#include "vec.h"
#include "trials.h"

using std::cout;
using std::ostream;
using std::endl;

void incBatchSize(int &batchSize)
{
    if (batchSize < 25)
      batchSize += 5;
    else if (batchSize < 100)
      batchSize += 25;
    else if (batchSize < 250)
      batchSize += 150;
    else if (batchSize < 1000)
      batchSize += 250;
    else
      batchSize += 2000;
}

void trial1() {
  // Statistical disclosure attack.

  for (int batchSize = 5; batchSize < 5000; incBatchSize(batchSize)) {
    for (int nRecips = 32; nRecips <= 2000000; nRecips *= 2) {
      for (int nAR = 1; (nAR <= 1024 && nAR < nRecips); nAR *= 2) {
	SDTrialSpec s;
	s.setNRecipients(nRecips);
	s.setAliceRecipients(nAR);
	s.setBatchSize(1000);
	s.setCutoff(1000000);
	if (nRecips > 2000)
	  s.setGranularity(100);
	else
	  s.setGranularity(10);
	for (int i = 1; i <= 100; ++i) {
	  s.write(std::cout);
	  std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
	  SDTrial trial(s);
	  TrialResult res = trial.attempt();
	  std::cout << res << std::endl << std::endl;
	}
      }
    }
  }
}

void trial1_1()
{
  for (int batchSize = 5; batchSize <= 125; batchSize *= 5) {
    for (int nRecips = 32; nRecips < 2000000; nRecips *= 8) {
      for (int nAR = 1; (nAR <= 64 && nAR < nRecips); nAR *= 2) {
	SDTrialSpec s;
	s.setNRecipients(nRecips);
	s.setAliceRecipients(nAR);
	s.setBatchSize(batchSize);
	if (nRecips > 65536)
	  s.setCutoff(4000000);
	else
	  s.setCutoff(1000000);
	if (nRecips > 2000)
	  s.setGranularity(100);
	else
	  s.setGranularity(10);
	int nBad = 0;
	int nGood = 0;
	for (int i = 1; i <= 100; ++i) {
	  s.write(std::cout);
	  std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
	  SDTrial trial(s);
	  TrialResult res = trial.attempt();
	  std::cout << res << std::endl << std::endl;
	  if (res.failed)
	    ++nBad;
	  else
	    ++nGood;
	  if (nBad >= 5 && nGood < nBad/2) {
	    break;
	  }
	}
      }
    }
  }
}

void trial1_1_1()
{
  // fill in gaps in 1.1 :(
  int nrArray[] = { 16, 4096, 65536 };

  for (int batchSize = 5; batchSize <= 125; batchSize *= 5) {
    for (int nrIdx = 0; nrIdx < 3; ++nrIdx) {
      int nRecips = nrArray[nrIdx];
      for (int nAR = 1; (nAR <= 64 && nAR < nRecips); nAR *= 4) {
	SDTrialSpec s;
	s.setNRecipients(nRecips);
	s.setAliceRecipients(nAR);
	s.setBatchSize(batchSize);
	if (nRecips > 65536)
	  s.setCutoff(4000000);
	else
	  s.setCutoff(1000000);
	if (nRecips > 2000)
	  s.setGranularity(100);
	else
	  s.setGranularity(10);
	int nBad = 0;
	int nGood = 0;
	for (int i = 1; i <= 100; ++i) {
	  s.write(std::cout);
	  std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
	  SDTrial trial(s);
	  TrialResult res = trial.attempt();
	  std::cout << res << std::endl << std::endl;
	  if (res.failed)
	    ++nBad;
	  else
	    ++nGood;
	  if (nBad >= 5 && nGood < nBad/2) {
	    break;
	  }
	}
      }
    }
  }
}


void trial1u_base(int batchSize, int nRecips, int nAMin, int nAMax)
{
  // unclip 1.1u

  for (int nAR = nAMin; nAR <= nAMax; nAR *= 4) {
    SDTrialSpec s;
    s.setNRecipients(nRecips);
    s.setAliceRecipients(nAR);
    s.setBatchSize(batchSize);
    s.setCutoff(10000);
    s.setGranularity(5);
    int nBad = 0;
    int nGood = 0;
    for (int i = 1; i <= 100; ++i) {
      s.write(std::cout);
      std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
      SDTrial trial(s);
      TrialResult res = trial.attempt();
      std::cout << res << std::endl << std::endl;
      if (res.failed)
	++nBad;
      else
	++nGood;
      if (nBad >= 5 && nGood < nBad/2) {
	break;
      }
    }
  }
}

void trial1u_1()
{
  trial1u_base(5,32,8,8);
  trial1u_base(5,256,16,16);
  trial1u_base(5,2048,1,16);
  trial1u_base(5,4096,1,16);
  trial1u_base(5,8192,1,16);
  trial1u_base(5,16384,1,16);
  trial1u_base(5,65536,1,16);
  trial1u_base(5,131072,1,16);
  trial1u_base(5,1048576,1,16);

  trial1u_base(25,2048,1,8);
  trial1u_base(25,4096,1,4);
  trial1u_base(25,8192,1,16);
  trial1u_base(25,16384,1,16);
  trial1u_base(25,65536,1,16);
  trial1u_base(25,131072,1,16);
  trial1u_base(25,1048576,1,16);
}

void trial1u_2()
{
  trial1u_base(125,2048,1,4);
  trial1u_base(125,4096,1,4);
  trial1u_base(125,16384,1,8);
  trial1u_base(125,65536,1,4);
  trial1u_base(125,131072,1,16);
  trial1u_base(125,1048576,1,16);

  trial1u_base(1000,2048,1,2);
  trial1u_base(1000,4096,1,4);
  trial1u_base(1000,8192,1,4);
  trial1u_base(1000,16384,1,4);
  trial1u_base(1000,65536,1,8);
  trial1u_base(1000,131072,1,8);
  trial1u_base(1000,1048576,1,8);
}

void trial1u_3()
{
  trial1u_base(125, 8192, 8, 8);
  trial1u_base(125, 16384, 8, 8);
  trial1u_base(125, 65536, 8, 8);
  trial1u_base(125, 131072, 8, 8);
}

void trial1u_4()
{
   trial1u_base(125, 1048576, 8, 8);
}

void trial2()
{
  const double pMsgAlice[] = { 0.6, 0.9, 0.99 };

  // attack with small-worlds network and unknown background.
  for (int batchSize = 5; batchSize < 5000; incBatchSize(batchSize)) {
    for (int nRecips = 32; nRecips <= 2000000; nRecips *= 2) {
      for (int nAR = 1; (nAR <= 1024 && nAR < nRecips); nAR *= 2) {
	for (int pMA = 0; pMA <= 2; ++pMA) {
	  for (int AISW=0; AISW <= 2; ++AISW) {
	    UnkBGBatchTrialSpec s;
	    s.setNRecipients(nRecips).setNAliceRecipients(nAR)
	      .setBatchSize(batchSize).setPaddingLevel(0).setCutoff(1000000)
	      .setAliceIsSmallworld(AISW>0).setWeightAlice(AISW==2)
	      .setExpMsgDist(true)
	      .setPMsgAlice(pMsgAlice[pMA])
	      .setPDummyAlice(0.0);
	    if (nRecips > 2000)
	      s.setGranularity(100);
	    else
	      s.setGranularity(10);
	    for (int i = 1; i <= 100; ++i) {
	      s.write(std::cout);
	      std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
	      UnkBGBatchTrial trial(s);
	      TrialResult res = trial.attempt();
	      std::cout << res << std::endl << std::endl;
	    }
	  }
	}
      }
    }
  }
}

void trial2_base(int batchSize, int nRecips)
{
  for (int nAR = 1; (nAR <= 64 && nAR < nRecips); nAR *= 4) {
    UnkBGBatchTrialSpec s;
    s.setNRecipients(nRecips).setNAliceRecipients(nAR)
      .setBatchSize(batchSize).setPaddingLevel(0)
      .setAliceIsSmallworld(1).setWeightAlice(0)
      .setExpMsgDist(true)
      .setPMsgAlice(0.9)
      .setPDummyAlice(0.0);
    if (nRecips > 2000)
      s.setGranularity(100);
    else
      s.setGranularity(10);
    if (nRecips > 65536)
      s.setCutoff(4000000);
    else
      s.setCutoff(1000000);
    int nBad = 0;
    int nGood = 0;
    for (int i = 1; i <= 100; ++i) {
      s.write(std::cout);
      std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
      UnkBGBatchTrial trial(s);
      TrialResult res = trial.attempt();
      std::cout << res << std::endl << std::endl;
      if (res.failed)
	++nBad;
      else
	++nGood;
      if (nBad >= 5 && nGood < nBad/2) {
	break;
      }
    }
  }
}

void trial2_1()
{
  for (int nRecips = 65536; nRecips <= 2000000; nRecips *= 8) {
    trial2_base(5,nRecips);
  }
}

void trial2_1_1()
{
  for (int nRecips = 65536; nRecips <= 2000000; nRecips *= 16) {
    trial2_base(5,nRecips);
  }
}

void trial2_1_2()
{
  trial2_base(5,1<<20);
}


void trial2_2()
{
  for (int batchSize = 25; batchSize <= 125; batchSize *= 5) {
    for (int nRecips = 32; nRecips <= 2000000; nRecips *= 8) {
      trial2_base(batchSize,nRecips);
    }
  }
}

void trial2_2_1()
{
  for (int nRecips = 16; nRecips <= 2000000; nRecips *= 16) {
    if (nRecips == 256) continue; // already have
    trial2_base(25,nRecips);
  }
}
void trial2_2_2()
{
  for (int nRecips = 16; nRecips <= 2000000; nRecips *= 16) {
    if (nRecips == 256) continue; // already have
    trial2_base(125,nRecips);
  }
}

void trial2u_base(int batchSize, int nRecips, int nAMin, int nAMax,
		  int nAStep,
		  double pMsg, bool sgw=false)

{
  for (int nAR = nAMin; (nAR <= nAMax && nAR < nRecips); nAR *= nAStep) {
    for (int strategy=0; strategy < 2; ++strategy) {
      if (strategy && sgw)
	continue;

      UnkBGBatchTrialSpec s;
      s.setNRecipients(nRecips).setNAliceRecipients(nAR)
	.setBatchSize(batchSize).setPaddingLevel(0)
	.setExpMsgDist(pMsg)
	.setPMsgAlice(0.9)
	.setPDummyAlice(0.0);

      if (sgw) {
	s.setAliceIsSmallworld(1).setWeightAlice(1);
      } else {
	if (strategy == 0)
	  s.setAliceIsSmallworld(0).setWeightAlice(0);
	else
	  s.setAliceIsSmallworld(1).setWeightAlice(0);
      }

      s.setGranularity(10);
      s.setCutoff(1000000);
      int nBad = 0;
      int nGood = 0;
      for (int i = 1; i <= 100; ++i) {
	s.write(std::cout);
	std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
	UnkBGBatchTrial trial(s);
	TrialResult res = trial.attempt();
	std::cout << res << std::endl << std::endl;
	if (res.failed)
	  ++nBad;
	else
	  ++nGood;
	if (nBad >= 5 && nGood < nBad/2) {
	  break;
	}
      }
    }
  }
}

void trial2u_1()
{
  trial2u_base(5, 2048,  1,8,2,  .6);
  trial2u_base(5, 2048,  1,8,2,  .9);
  trial2u_base(5, 4096,  1,16,2,  .6);
  trial2u_base(5, 4096,  1,16,2,  .9);
  trial2u_base(5, 8192,  1,16,2,  .6);
  trial2u_base(5, 8192,  1,16,2,  .9);
  trial2u_base(5, 16384,  1,16,2,  .6);
  trial2u_base(5, 16384,  1,16,2,  .9);
  trial2u_base(5, 65536,  1,64,2,  .9);

  trial2u_base(25, 2048,  1,32,2,  .9);
  trial2u_base(25, 4096,  1,16,4,  .9);
  trial2u_base(25, 8192,  1,32,2,  .9);
  trial2u_base(25, 65536,  1,16,4,  .9);
  trial2u_base(25, 131072,  1,2,2,  .9);
}

void trial2u_1_1()
{
  trial2u_base(25, 131072,  2,2,2,  .9);
}


void trial2u_2() {
  trial2u_base(125, 4096,  1,4,4,  .9);
  trial2u_base(125, 65536, 1,16,4,  .9);

  trial2u_base(5, 64,    4,4,4,  .6, true);
  trial2u_base(5, 2048,  1,1,2,  .6, true);
  trial2u_base(5, 2048,  1,1,2,  .9, true);
  trial2u_base(5, 4096,  1,2,2,  .6, true);
  trial2u_base(5, 4096,  1,2,2,  .9, true);
  trial2u_base(5, 8192,  1,2,2,  .6, true);
  trial2u_base(5, 8192,  1,2,2,  .9, true);
  trial2u_base(5, 16384,  1,2,2,  .6, true);
  trial2u_base(5, 16384,  1,2,2,  .9, true);
}


void trial2r_base(int batchSize, int nRecips, int nAMin, int nAMax,
		  int nAStep,
		  double pMsg, bool sgw=false)

{
  for (int nAR = nAMin; (nAR <= nAMax && nAR < nRecips); nAR *= nAStep) {
    UnkBGBatchTrialSpec s;
    s.setNRecipients(nRecips).setNAliceRecipients(nAR)
      .setBatchSize(batchSize).setPaddingLevel(0)
      .setExpMsgDist(pMsg)
      .setPMsgAlice(0.9)
      .setPDummyAlice(0.0);

    if (sgw) {
      s.setAliceIsSmallworld(1).setWeightAlice(1);
    } else {
      s.setAliceIsSmallworld(1).setWeightAlice(0);
    }

    s.setGranularity(2);
    s.setCutoff(1000000);
    int nBad = 0;
    int nGood = 0;
    for (int i = 1; i <= 100; ++i) {
      s.write(std::cout);
      std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
      UnkBGBatchTrial trial(s);
      TrialResult res = trial.attempt();
      std::cout << res << std::endl << std::endl;
      if (res.failed)
	++nBad;
      else
	++nGood;
      if (nBad >= 5 && nGood < nBad/2) {
	break;
      }
    }
  }
}

void trial2r_1() {
  for (int n = 32; n <= 65536; n *= 2) {
    trial2r_base(125, n, 8,16,2, .5, false);
  }
}

void trial2r_2() {
  for (int n = 32; n <= 65536; n *= 2) {
    trial2r_base(125, n, 8,16,2, .5, true);
  }
}

void trial2r_3() {
  for (int n = 16384; n <= 65536; n *= 2) {
    trial2r_base(125, n, 8,16,2, .5, false);
  }
}

void trial3()
{
  // attack with small-worlds network and unknown background.

  const double pMsgAlice[] = { 0.6, 0.75, 0.9, 0.99 };
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pMAi = 0; pMAi <= 3; ++pMAi) {
    for (int pDi = 0; pDi <= 3; ++pDi) {
      for (int bg = 32*10; bg <= 32*1000; bg*= 10) {
	MixTrialSpec s;
	s.setNRecipients(65536).setNAliceRecipients(32)
	  .setPathLen(1).setPadding(0)
	  .setExpAlice(1)
	  .setPMessage(1.0)
	  .setPartial(false)

	  .setPDelay(pDelay[pDi])
	  .setPMessage(pMsgAlice[pMAi])
	  .setBGVolMean(bg).setBGVolDev(bg/10.0)
	  .setPObserve(1.0)
	  .setPDummy(0.0);

	s.setGranularity(50);

	s.setCutoff(1500000);
	int nBad = 0;
	int nGood = 0;
	for (int i = 1; i <= 100; ++i) {
	  s.write(std::cout);
	  std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
	  MixTrial trial(s);
	  TrialResult res = trial.attempt();
	  std::cout << res << std::endl << std::endl;
	  if (res.failed)
	    ++nBad;
	  else
	    ++nGood;
	  if (nBad >= 5 && nGood < nBad/2) {
	    break;
	  }
	}
      }
    }
  }
}

void trial3_base(double pMsgA, double pDel, int bg)
{
  MixTrialSpec s;
  s.setNRecipients(65536).setNAliceRecipients(32)
    .setPathLen(1).setPadding(0)
    .setExpAlice(1)
    .setPartial(false)

    .setPDelay(pDel)
    .setPMessage(pMsgA)
    .setBGVolMean(bg).setBGVolDev(bg/10.0)
    .setPObserve(1.0)
    .setPDummy(0.0);

  s.setGranularity(50);

  s.setCutoff(1500000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial3_1() {
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pDi = 0; pDi <= 3; ++pDi) {
    for (int bg = 32*10; bg <= 32*1000; bg*= 10) {
      trial3_base(.3, pDelay[pDi], bg);
    }
  }
}

void trial3_2() {
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pDi = 0; pDi <= 3; ++pDi) {
    for (int bg = 32*10; bg <= 32*1000; bg*= 10) {
      trial3_base(.1, pDelay[pDi], bg);
    }
  }
}


void trial3_3() {
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pDi = 0; pDi <= 3; ++pDi) {
    for (int bg = 32*10; bg <= 32*1000; bg*= 10) {
      trial3_base(.9, pDelay[pDi], bg);
    }
  }
}


void trial3r_1() {
  const double pAlice[] = { .1, .3, .6, .9 };
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pAi = 0; pAi <= 3; ++pAi) {
    for (int pDi = 0; pDi <= 3; ++pDi) {
      trial3_base(pAlice[pAi], pDelay[pDi], 25);
    }
  }
}
void trial3r_1_1() {
  const double pAlice[] = { .6, .9 };
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pAi = 0; pAi <= 1; ++pAi) {
    for (int pDi = 0; pDi <= 3; ++pDi) {
      trial3_base(pAlice[pAi], pDelay[pDi], 25);
    }
  }
}
void trial3r_1_2() {
  trial3_base(.3, .9, 25);
}
void trial3r_2() {
  const double pAlice[] = { .1, .3, .6, .9 };
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pAi = 0; pAi <= 3; ++pAi) {
    for (int pDi = 0; pDi <= 3; ++pDi) {
      trial3_base(pAlice[pAi], pDelay[pDi], 125);
    }
  }
}
void trial3r_2_1() {
  const double pAlice[] = { .3, .6, .9 };
  const double pDelay[] = { .1, .3, .6, .9 };

  for (int pAi = 0; pAi <= 2; ++pAi) {
    for (int pDi = 0; pDi <= 3; ++pDi) {
      trial3_base(pAlice[pAi], pDelay[pDi], 125);
    }
  }
}

void trial3r_3() {
  trial3_base(.1, .3, 320);
  trial3_base(.1, .6, 320);
  trial3_base(.1, .9, 320);
  trial3_base(.1, .3, 3200);
  trial3_base(.1, .6, 3200);
  trial3_base(.1, .9, 3200);
}

void trial3r_3_1() {
  trial3_base(.1, .3, 320);
  trial3_base(.1, .6, 320);
  trial3_base(.1, .9, 320);
  trial3_base(.1, .3, 3200);
  trial3_base(.1, .6, 3200);
  trial3_base(.1, .9, 3200);
}

void trial3r_3_2() {
  trial3_base(.1, .3, 320);
  trial3_base(.1, .6, 320);
  trial3_base(.1, .9, 320);
  trial3_base(.1, .3, 3200);
  trial3_base(.1, .6, 3200);
  trial3_base(.1, .9, 3200);
}


void trial3r_4() {
  trial3_base(.3, .3, 320);
  trial3_base(.3, .6, 320);
  trial3_base(.3, .9, 320);
  trial3_base(.3, .3, 3200);
  trial3_base(.3, .6, 3200);
  trial3_base(.3, .9, 3200);
}

void trial3r_5() {
  trial3_base(.6, .9, 320);
  trial3_base(.9, .9, 320);
  trial3_base(.6, .9, 3200);
  trial3_base(.9, .9, 3200);
}

void trial3r_6() {
  trial3_base(.4, .1, 125);
  trial3_base(.5, .1, 125);
  trial3_base(.7, .1, 125);
  trial3_base(.4, .3, 125);
  trial3_base(.5, .3, 125);
  trial3_base(.7, .3, 125);
  trial3_base(.4, .6, 125);
  trial3_base(.5, .6, 125);
  trial3_base(.7, .6, 125);
  trial3_base(.4, .9, 125);
  trial3_base(.5, .9, 125);
  trial3_base(.7, .9, 125);
}

void trial3r_7() {
  trial3_base(.4, .1, 25);
  trial3_base(.5, .1, 25);
  trial3_base(.7, .1, 25);
  trial3_base(.4, .3, 25);
  trial3_base(.5, .3, 25);
  trial3_base(.7, .3, 25);
  trial3_base(.4, .6, 25);
  trial3_base(.5, .6, 25);
  trial3_base(.7, .6, 25);
  trial3_base(.4, .9, 25);
  trial3_base(.5, .9, 25);
  trial3_base(.7, .9, 25);
}

void trial4_base(double pMsgA, double pDel, int pathlen, int bgVol=320)
{
  MixTrialSpec s;
  s.setNRecipients(65536).setNAliceRecipients(32)
    .setPathLen(pathlen).setPadding(0)
    .setExpAlice(1)
    .setPMessage(1.0)
    .setPartial(false)

    .setPDelay(pDel)
    .setPMessage(pMsgA)
    .setBGVolMean(bgVol).setBGVolDev(bgVol/10.0)
    .setPObserve(1.0)
    .setPDummy(0.0);

  s.setGranularity(25);

  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial4_1()
{
  for (int pd = 0; pd < 2; ++pd) {
    for (int pl = 2; pl <= 8; pl *= 2) {
      trial4_base(.1, (!pd)?.1:.6, pl);
    }
  }
}

void trial4_2()
{
  for (int pd = 0; pd < 2; ++pd) {
    for (int pl = 2; pl <= 8; pl *= 2) {
      trial4_base(.6, (!pd)?.1:.6, pl);
    }
  }
}

void trial4r_1()
{
  trial4_base(.1, .1, 2, 125);
  trial4_base(.1, .6, 2, 125);
  trial4_base(.6, .1, 2, 125);
  trial4_base(.6, .6, 2, 125);
  trial4_base(.9, .1, 2, 125);
  trial4_base(.9, .6, 2, 125);
}

void trial4r_1_1()
{
  trial4_base(.9, .6, 2, 125);
}


void trial4r_2()
{
  trial4_base(.1, .1, 4, 125);
  trial4_base(.1, .6, 4, 125);
  trial4_base(.6, .1, 4, 125);
  trial4_base(.6, .6, 4, 125);
  trial4_base(.9, .1, 4, 125);
  trial4_base(.9, .6, 4, 125);
}

void trial4r_2_1()
{
  trial4_base(.9, .1, 4, 125);
  trial4_base(.9, .6, 4, 125);
}

void trial4r_3_1()
{
  trial4_base(.1, .1, 8, 125);
  trial4_base(.6, .1, 8, 125);
  trial4_base(.9, .1, 8, 125);
}

void trial4r_3_1_1()
{
  trial4_base(.9, .1, 8, 125);
}

void trial4r_3_1_2()
{
  trial4_base(.1, .1, 8, 125);
  trial4_base(.6, .1, 8, 125);
}

void trial4r_3_2()
{
  trial4_base(.1, .6, 8, 125);
  trial4_base(.6, .6, 8, 125);
  trial4_base(.9, .6, 8, 125);
}

void trial4r_4()
{
  trial4_base(.4, .1, 2, 125);
  trial4_base(.4, .1, 4, 125);
  trial4_base(.4, .1, 8, 125);
  trial4_base(.4, .6, 2, 125);
  trial4_base(.4, .6, 4, 125);
  trial4_base(.4, .6, 8, 125);
}
void trial4r_5()
{
  trial4_base(.5, .1, 2, 125);
  trial4_base(.5, .1, 4, 125);
  trial4_base(.5, .1, 8, 125);
  trial4_base(.5, .6, 2, 125);
  trial4_base(.5, .6, 4, 125);
  trial4_base(.5, .6, 8, 125);
}
void trial4r_6()
{
  trial4_base(.7, .1, 2, 125);
  trial4_base(.7, .1, 4, 125);
  trial4_base(.7, .1, 8, 125);
  trial4_base(.7, .6, 2, 125);
  trial4_base(.7, .6, 4, 125);
  trial4_base(.7, .6, 8, 125);
}

void trial4r_7()
{
  trial4_base(.2, .6, 2, 125);
  trial4_base(.3, .6, 2, 125);
  trial4_base(.8, .6, 2, 125);
}

void trial4r_8()
{
  trial4_base(.2, .6, 4, 125);
  trial4_base(.3, .6, 4, 125);
  trial4_base(.8, .6, 4, 125);
}

void trial4r_9()
{
  trial4_base(.2, .9, 1, 125);
  trial4_base(.8, .9, 1, 125);
}


void trial5a_base(double pMsgA, double pDelay, double pDummy, int pathLen=4)
{
  MixTrialSpec s;
  s.setNRecipients(65536).setNAliceRecipients(32)
    .setPathLen(pathLen).setPadding(0)
    .setExpAlice(1)
    .setPartial(false)
    .setPOnline(1.0)

    .setPDelay(pDelay)
    .setPMessage(pMsgA)
    .setBGVolMean(125).setBGVolDev(125/10.0)
    .setPObserve(1.0)
    .setPDummy(pDummy);

  s.setGranularity(10);
  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial5a_1()
{
  trial5a_base(.6,.1,.05);
  trial5a_base(.6,.1,.1);
  trial5a_base(.6,.1,.3);
  trial5a_base(.6,.1,.6);
  trial5a_base(.6,.1,.9);
}
void trial5a_2()
{
  trial5a_base(.6,.6,.05);
  trial5a_base(.6,.6,.1);
  trial5a_base(.6,.6,.3);
  trial5a_base(.6,.6,.6);
  trial5a_base(.6,.6,.9);
}

void trial5a_3()
{
  trial5a_base(.6,.1,.05,1);
  trial5a_base(.6,.1,.1,1);
  trial5a_base(.6,.1,.3,1);
  trial5a_base(.6,.1,.6,1);
  trial5a_base(.6,.1,.9,1);
}
void trial5a_4()
{
  trial5a_base(.6,.6,.05,1);
  trial5a_base(.6,.6,.1,1);
  trial5a_base(.6,.6,.3,1);
  trial5a_base(.6,.6,.6,1);
  trial5a_base(.6,.6,.9,1);
}
void trial5a_4_1()
{
  trial5a_base(.6,.6,.1,1);
  trial5a_base(.6,.6,.3,1);
}
void trial5a_4_2()
{
  trial5a_base(.6,.6,.6,1);
  trial5a_base(.6,.6,.9,1);
}
void trial5a_4_3()
{
  trial5a_base(.6,.6,.9,1);
}

void trial5a_5()
{
  trial5a_base(.6,.6,  .5, 1);
  trial5a_base(.6,.6,  .65, 1);
  trial5a_base(.6,.6,  .7, 1);
  trial5a_base(.6,.6,  .8, 1);
}

void trial5a_5_1()
{
  trial5a_base(.6,.6,  .7, 1);
  trial5a_base(.6,.6,  .8, 1);
}

void trial5a_6()
{
  trial5a_base(.6,.6,  .5, 4);
  trial5a_base(.6,.6,  .65, 4);
  trial5a_base(.6,.6,  .7, 4);
  trial5a_base(.6,.6,  .8, 4);
}

void trial5a_6_1()
{
  trial5a_base(.6,.6,  .7, 4);
  trial5a_base(.6,.6,  .8, 4);
}

void trial5a_7()
{
  trial5a_base(.6,.1,  .8, 1);
  trial5a_base(.6,.1,  .8, 4);
}


void trial5b_base(double pMsgA, double pDelay, int nPad, double pOnline,
		  int pathLen=4)
{
  MixTrialSpec s;
  s.setNRecipients(65536).setNAliceRecipients(32)
    .setPathLen(pathLen).setPadding(nPad)
    .setExpAlice(1)
    .setPartial(false)
    .setPOnline(pOnline)

    .setPDelay(pDelay)
    .setPMessage(pMsgA)
    .setBGVolMean(125).setBGVolDev(125/10.0)
    .setPObserve(1.0)
    .setPDummy(0.0);

  s.setGranularity(10);

  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial5b_1()
{
  for(int i=1; i<=9; i+=2) {
    trial5b_base(.6, .1, 2, i/10.0);
  }
}
void trial5b_2()
{
  for(int i=1; i<=9; i+=2) {
    trial5b_base(.6, .6, 2, i/10.0);
  }
}
void trial5b_3()
{
  for(int i=1; i<=9; i+=2) {
    trial5b_base(.6, .1, 5, i/10.0);
  }
}
void trial5b_4()
{
  for(int i=1; i<=9; i+=2) {
    trial5b_base(.6, .6, 5, i/10.0);
  }
}

void trial5b_5_1()
{
  trial5b_base(.1,  .1,2,  .1);
  trial5b_base(.1,  .1,2,  .5);
  trial5b_base(.1,  .1,2,  .9);
}

void trial5b_5_2()
{
  trial5b_base(.9,  .1,2,  .1);
  trial5b_base(.9,  .1,2,  .5);
  trial5b_base(.9,  .1,2,  .9);
}

void trial5b_6_1()
{
  trial5b_base(.6,  .1,2,  .5, 1);
}
void trial5b_6_2()
{
  trial5b_base(.6,  .1,2,  .9, 1);
}

void trial5b_7()
{
  trial5b_base(.6,  .1, 1,  .9, 1);
}

void trial5b_8()
{
  trial5b_base(.6,  .1, 1,  .8, 1);
  trial5b_base(.6,  .1, 1,  .7, 1);
  trial5b_base(.6,  .1, 1,  .6, 1);
  trial5b_base(.6,  .1, 1,  .5, 1);
  trial5b_base(.6,  .1, 1,  .4, 1);
}

void trial5b_8_1()
{
  trial5b_base(.6,  .1, 1,  .6, 1);
  trial5b_base(.6,  .1, 1,  .5, 1);
  trial5b_base(.6,  .1, 1,  .4, 1);
}
void trial5b_9()
{
  trial5b_base(.6,  .1, 1,  .9, 1);
  trial5b_base(.7,  .1, 1,  .9, 1);
  trial5b_base(.8,  .1, 1,  .9, 1);
}

void trial5b_10()
{
  trial5b_base(.5,  .1, 1,  .9, 1);
  trial5b_base(.4,  .1, 1,  .9, 1);
  trial5b_base(.3,  .1, 1,  .9, 1);
  trial5b_base(.2,  .1, 1,  .9, 1);
  trial5b_base(.1,  .1, 1,  .9, 1);
}


void trial5b_11()
{
  trial5b_base(.6,.6,2,.1,1);
  trial5b_base(.6,.6,2,.3,1);
  trial5b_base(.6,.6,2,.6,1);
  trial5b_base(.6,.6,2,.9,1);
}

void trial5b_12()
{
  trial5b_base(.6,.1,2,.1,1);
  trial5b_base(.9,.1,2,.1,1);
}

void trial5c_base(double pOnline, int nPad, int smooth, double pDelay,
		  int pathLen, double pMsg=0.6)
{
  MixTrialSpec s;

  s.setNRecipients(65536).setNAliceRecipients(32)
    .setPathLen(pathLen).setPadding(nPad).setSmoothPadding(smooth)
    .setExpAlice(1)
    .setPartial(false)
    .setPOnline(pOnline)
    .setPDelay(pDelay)
    .setPMessage(pMsg)
    .setBGVolMean(125).setBGVolDev(125/10.0)
    .setPObserve(1.0)
    .setPDummy(0.0);

  s.setGranularity(10);

  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial5c_1()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 2, false, .1, L);
    }
  }
}

void trial5c_2()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 2, false, .6, L);
    }
  }
}
void trial5c_3()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 2, true, .1, L);
    }
  }
}
void trial5c_4()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 2, true, .6, L);
    }
  }
}
void trial5c_5()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 4, false, .1, L);
    }
  }
}
void trial5c_6()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 4, false, .6, L);
    }
  }
}
void trial5c_7()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 4, true, .1, L);
    }
  }
}
void trial5c_8()
{
  for(int pTrial=1; pTrial <= 9; pTrial +=2) {
    for (int L=1; L <= 4; L +=3) {
      trial5c_base(pTrial*0.1, 4, true, .6, L);
    }
  }
}
void trial5c_9()
{
  trial5c_base(.8, 2, true, .6, 4);
}

void trial5c_10_1()
{
  trial5c_base(.95, 2, true, .1, 1);
  trial5c_base(.99, 2, true, .1, 1);
}

void trial5c_10_2()
{
  trial5c_base(.95, 2, true, .1, 4);
  trial5c_base(.99, 2, true, .1, 4);
}
void trial5c_10_3()
{
  trial5c_base(.95, 2, true, .6, 1);
  trial5c_base(.99, 2, true, .6, 1);
}
void trial5c_10_4()
{
  trial5c_base(.975, 2, true, .1, 1);
  trial5c_base(.975, 2, true, .1, 4);
  trial5c_base(.975, 2, true, .6, 1);
}
void trial5c_10_5()
{
  trial5c_base(.2, 2, true, .6, 4);
}

void trial5d_base(double pDelay, int pathLen, int nAlice, bool padding=true)
{
  MixTrialSpec s;

  s.setNRecipients(65536).setNAliceRecipients(nAlice)
    .setPathLen(pathLen)
    .setExpAlice(1)
    .setPartial(false)
    .setPOnline(1.0)
    .setPDelay(pDelay)
    .setPMessage(0.6)
    .setBGVolMean(125).setBGVolDev(125/10.0)
    .setPObserve(1.0)
    .setPDummy(0.0)
    .setKnownBackground(true);
  if (padding)
    s.setPadding(2).setSmoothPadding(true);

  s.setGranularity(10);

  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial5d_1()
{
  for (int nA = 2; nA <= 128; nA *= 4) {
    for (int L = 1; L <= 4; L += 3) {
      trial5d_base(.1, L, nA);
    }
  }
}

void trial5d_2()
{
  for (int nA = 2; nA <= 128; nA *= 4) {
    for (int L = 1; L <= 4; L += 3) {
      trial5d_base(.6, L, nA);
    }
  }
}

void trial5d_3()
{
  for (int nA = 2; nA <= 128; nA *= 4) {
    for (int L = 1; L <= 4; L += 3) {
      trial5d_base(.9, L, nA);
    }
  }
}

void trial5d_4()
{
  trial5d_base(.3, 1, 32);
  trial5d_base(.6, 1, 32);
}

void trial5dd_1()
{
  trial5d_base(.1, 1, 32, false);
  trial5d_base(.3, 1, 32, false);
  trial5d_base(.6, 1, 32, false);
  trial5d_base(.9, 1, 32, false);
}



void trial6_base(double pDelay, double pObserve)
{
  MixTrialSpec s;
  s.setNRecipients(65536).setNAliceRecipients(32)
    .setPathLen(4).setPadding(0)
    .setExpAlice(1)
    .setPMessage(1.0)
    .setPartial(true)

    .setPDelay(pDelay)
    .setPMessage(0.6)
    .setBGVolMean(125).setBGVolDev(125/10.0)
    .setPObserve(pObserve)
    .setPDummy(0.0);

  s.setGranularity(50);

  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial6_1(void) {
  trial6_base(.6,.99);
  trial6_base(.6,.95);
  trial6_base(.6,.90);
  trial6_base(.6,.85);
}

void trial6_2(void) {
  trial6_base(.1,.99);
  trial6_base(.1,.95);
  trial6_base(.1,.90);
  trial6_base(.1,.85);
}

void trial6_3(void) {
  trial6_base(.6,.80);
  trial6_base(.6,.70);
}

void trial6_4(void) {
  trial6_base(.1,.80);
  trial6_base(.1,.70);
}

void trial6_5(void) {
  trial6_base(.6,.60);
  trial6_base(.6,.50);
}

void trial6_6(void) {
  trial6_base(.1,.60);
  trial6_base(.1,.50);
}

void trial6_7(void) {
  trial6_base(.6,.40);
  trial6_base(.6,.30);
  trial6_base(.6,.20);
}

void trial6_7_1(void) {
  trial6_base(.6,.30);
  trial6_base(.6,.20);
}


void trial6_8(void) {
  trial6_base(.1,.40);
  trial6_base(.1,.30);
  trial6_base(.1,.20);
}

void trial6_9(void) {
  trial6_base(.6,.10);
  trial6_base(.6,.05);
}
void trial6_10_1(void) {
  trial6_base(.1,.10);
}
void trial6_10_2(void) {
  trial6_base(.1,.05);
}


void trial7_base(int N, double pDelay, int pathLen, double pMsg, int bgvol)
{
  MixTrialSpec s;

  s.setNRecipients(N).setNAliceRecipients(1)
    .setPathLen(pathLen)
    .setExpAlice(1)
    .setPartial(false)
    .setPOnline(1.0)
    .setPDelay(pDelay)
    .setPMessage(pMsg)
    .setBGVolMean(bgvol).setBGVolDev(bgvol/10.0)
    .setPObserve(1.0)
    .setPDummy(0.0);

  s.setGranularity(10);

  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    MixTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trial7a_base(double pDelay, int pathLen)
{
  for (int N=1024; N <=232144; N *= 4) {
    for (int bg=128; bg <= N; bg *= 8) {
      for (int pM =1; pM <= 6; pM += 5) {
	trial7_base(N,pDelay,pathLen,pM/10.0,bg);
      }
    }
  }
}

void trial7a_1()
{
  trial7a_base(.1,1);
}
void trial7a_2()
{
  trial7a_base(.6,1);
}
void trial7a_3()
{
  trial7a_base(.9,1);
}
void trial7a_4()
{
  trial7a_base(.1,4);
}
void trial7a_5()
{
  trial7a_base(.6,4);
}
void trial7a_6()
{
  trial7a_base(.9,4);
}

void trialnym_base(int nR, int pL, double pD, double pA)
{
  NymTrialSpec s;
  double bgvol = nR * (1.0/(1.0-pA));
  s.setNRecipients(nR).setPathLen(pL).setPDelay(pD)
    .setPartial(false).setPObserve(1.0)
    .setPMsgAlice(pA).setBGVolMean(bgvol).setBGVolDev(bgvol/10.0);

  s.setGranularity(1);
  s.setCutoff(1000000);
  int nBad = 0;
  int nGood = 0;
  for (int i = 1; i <= 100; ++i) {
    s.write(std::cout);
    std::cout << "\"" << i << "/" << 100 << "\"" << std::endl;
    NymTrial trial(s);
    TrialResult res = trial.attempt();
    std::cout << res << std::endl << std::endl;
    if (res.failed)
      ++nBad;
    else
      ++nGood;
    if (nBad >= 5 && nGood < nBad/2) {
      break;
    }
  }
}

void trialnym_1()
{
  for (int n = 1024; n <= 65536; n *= 4) {
    trialnym_base(n, 1, .1, .5);
    trialnym_base(n, 1, .6, .5);
    trialnym_base(n, 1, .1, .1);
    trialnym_base(n, 1, .6, .1);
  }
}

void trialnym_2()
{
  for (int n = 1024; n <= 65536; n *= 4) {
    trialnym_base(n, 1, .9, .5);
    trialnym_base(n, 1, .9, .5);
  }
}

void trialnym_3()
{
  for (int n = 1024; n <= 65536; n *= 4) {
    trialnym_base(n, 4, .1, .1);
    trialnym_base(n, 4, .6, .1);
    trialnym_base(n, 4, .9, .1);
  }
}

void trialnym_4()
{
  for (int n = 1024; n <= 65536; n *= 4) {
    trialnym_base(n, 4, .1, .5);
    trialnym_base(n, 4, .6, .5);
    trialnym_base(n, 4, .9, .5);
  }
}

typedef void (*trialfunc)(void);

struct {
  char *n; trialfunc t;
} trials[] = {
  { "1", trial1 },
  { "1.1", trial1_1 },
  { "1.1.1", trial1_1_1 },
  { "1u.1", trial1u_1 },
  { "1u.2", trial1u_2 },
  { "1u.3", trial1u_3 },
  { "1u.4", trial1u_4 },

  { "2", trial2 },
  { "2.1", trial2_1 },
  { "2.1.1", trial2_1_1 },
  { "2.1.2", trial2_1_2 },
  { "2.2", trial2_2 },
  { "2.2.2", trial2_2_1 },
  { "2.2.1", trial2_2_2 },
  { "2u.1", trial2u_1 },
  { "2u.1.1", trial2u_1_1 },
  { "2u.2", trial2u_2 },

  { "2r.1", trial2r_1 },
  { "2r.2", trial2r_2 },
  { "2r.3", trial2r_3 },

  { "3", trial3 },
  { "3.1", trial3_1 },
  { "3.2", trial3_2 },
  { "3.3", trial3_3 },
  { "4.1", trial4_1 },
  { "4.2", trial4_2 },
  { "3r.1", trial3r_1 },
  { "3r.1.1", trial3r_1_1 },
  { "3r.1.2", trial3r_1_2 },
  { "3r.2", trial3r_2 },
  { "3r.2.1", trial3r_2_1 },
  { "3r.3", trial3r_3 },
  { "3r.4", trial3r_4 },
  { "3r.5", trial3r_5 },
  { "3r.6", trial3r_6 },
  { "3r.7", trial3r_7 },

  { "4r.1",   trial4r_1 },
  { "4r.1.1",   trial4r_1_1 },
  { "4r.2",   trial4r_2 },
  { "4r.2.1",   trial4r_2_1 },
  { "4r.3.1", trial4r_3_1 },
  { "4r.3.1.1", trial4r_3_1_1 },
  { "4r.3.1.2", trial4r_3_1_2 },
  { "4r.3.2", trial4r_3_2 },
  { "4r.4", trial4r_4 },
  { "4r.5", trial4r_5 },
  { "4r.6", trial4r_6 },
  { "4r.7", trial4r_7 },
  { "4r.8", trial4r_8 },
  { "4r.9", trial4r_9 },

  { "5a.1", trial5a_1 },
  { "5a.2", trial5a_2 },
  { "5a.3", trial5a_3 },
  { "5a.4", trial5a_4 },
  { "5a.4.1", trial5a_4_1 },
  { "5a.4.2", trial5a_4_2 },
  { "5a.4.3", trial5a_4_3 },
  { "5a.5", trial5a_5 },
  { "5a.5.1", trial5a_5_1 },
  { "5a.6", trial5a_6 },
  { "5a.6.1", trial5a_6_1 },
  { "5a.7", trial5a_7 },

  { "5b.1", trial5b_1 },
  { "5b.2", trial5b_2 },
  { "5b.3", trial5b_3 },
  { "5b.4", trial5b_4 },
  { "5b.5.1", trial5b_5_1 },
  { "5b.5.2", trial5b_5_2 },
  { "5b.6.1", trial5b_6_1 },
  { "5b.6.2", trial5b_6_2 },
  { "5b.7", trial5b_7 },
  { "5b.8", trial5b_8 },
  { "5b.8.1", trial5b_8_1 },
  { "5b.9", trial5b_9 },
  { "5b.10", trial5b_10 },
  { "5b.11", trial5b_11 },
  { "5b.12", trial5b_12 },

  { "5c.1", trial5c_1 },
  { "5c.2", trial5c_2 },
  { "5c.3", trial5c_3 },
  { "5c.4", trial5c_4 },
  { "5c.5", trial5c_5 },
  { "5c.6", trial5c_6 },
  { "5c.7", trial5c_7 },
  { "5c.8", trial5c_8 },
  { "5c.9", trial5c_9 },
  { "5c.10.1", trial5c_10_1 },
  { "5c.10.2", trial5c_10_2 },
  { "5c.10.3", trial5c_10_3 },
  { "5c.10.4", trial5c_10_4 },
  { "5c.10.5", trial5c_10_5 },

  { "5d.1", trial5d_1 },
  { "5d.2", trial5d_2 },
  { "5d.3", trial5d_3 },
  { "5d.4", trial5d_4 },
  { "5dd.1", trial5dd_1 },

  { "6.1",    trial6_1 },
  { "6.2",    trial6_2 },
  { "6.3",    trial6_3 },
  { "6.4",    trial6_4 },
  { "6.5",    trial6_5 },
  { "6.6",    trial6_6 },
  { "6.7",    trial6_7 },
  { "6.7.1",  trial6_7_1 },
  { "6.8",    trial6_8 },
  { "6.9",    trial6_9 },
  { "6.10.1",   trial6_10_1 },
  { "6.10.2",   trial6_10_2 },

  { "7a.1", trial7a_1 },
  { "7a.2", trial7a_2 },
  { "7a.3", trial7a_3 },
  { "7a.4", trial7a_4 },
  { "7a.5", trial7a_5 },
  { "7a.6", trial7a_6 },

  { "nym.1", trialnym_1 },
  { "nym.2", trialnym_2 },
  { "nym.3", trialnym_3 },
  { "nym.4", trialnym_4 },

  { 0, 0 }
};

int
main(int c, char **v)
{
  if (c < 2) {
    std::cout << "no args given";
    return -1;
  }
  seed_rng();

  std::string trialname(v[1]);

  for (int i = 0; trials[i].n; ++i) {
    if (trialname == trials[i].n) {
      trials[i].t();
      return 0;
    }
  }

  std::cout << "unrecognized trial name: " << trialname << std::endl;

  return 0;
}

