<commit_before>/********** tell emacs we use -*- c++ -*- style comments *******************
 $Revision: 1.11 $  $Author: trey $  $Date: 2006-02-06 19:28:55 $

 @file    Interleave.cc
 @brief   No brief

 Copyright (c) 2002-2005, <NAME>
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:

 * The software may not be sold or incorporated into a commercial
   product without specific prior written permission.
 * The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 ***************************************************************************/

/***************************************************************************
 * INCLUDES
 ***************************************************************************/

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>
#include <fstream>

#include "zmdpCommonTime.h"
#include "Interleave.h"
#include "zmdpCommonDefs.h"
#include "MatrixUtils.h"

using namespace std;
using namespace MatrixUtils;

namespace zmdp {

#define NUM_SIM_ITERATIONS_TO_LOG (1)

void Interleave::interleave(int numIterations,
			    AbstractSim* _sim,
			    Solver& solver,
			    int numSteps,
			    double minPrecision,
			    double minWait,
			    const string& scatterFileName,
			    const string& boundsFileNameFmt,
			    const string& simFileNameFmt)
{
  int action;
  belief_vector last_belief, diff;
  ofstream scatterFile, boundsFile, simFile;
  char boundsFileName[PATH_MAX], simFileName[PATH_MAX];
  double deltaTime, timeSoFar, episodeTimeSoFar;
  bool achievedPrecision, achievedTerminalState;

  sim = _sim;

  scatterFile.open( scatterFileName.c_str() );
  if (! scatterFile) {
    cerr << "ERROR: couldn't open " << scatterFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  system("mkdir -p plots");

  FOR (i, numIterations) {
    cout << "=-=-=-=-= interleave: trial " << (i+1) << " / " << numIterations << endl;

    // reset the planner
    solver.planInit(sim->getModel());

    // set up a new bounds file and sim file for each iteration
    snprintf( boundsFileName, sizeof(boundsFileName), boundsFileNameFmt.c_str(), i );
    boundsFile.open( boundsFileName );
    if (! boundsFile) {
      cerr << "ERROR: couldn't open " << boundsFileName << " for writing: "
	   << strerror(errno) << endl;
      exit(EXIT_FAILURE);
    }
    solver.setBoundsFile(&boundsFile);
    
    snprintf( simFileName, sizeof(simFileName), simFileNameFmt.c_str(), i );
    simFile.open( simFileName );
    if (! simFile) {
      cerr << "ERROR: couldn't open " << simFileName << " for writing: "
	   << strerror(errno) << endl;
      exit(EXIT_FAILURE);
    }
    sim->simOutFile = &simFile;

    // restart the sim
    sim->restart();
    timeSoFar = 0;
    achievedTerminalState = false;

    // run in interleaved mode
    FOR (t, numSteps) {
      cout << "#-#-#-#-#-#-# interleave: trial " << (i+1) << " / " << numIterations
	   << ", time step " << (t+1) << " / " << numSteps << endl;
      // iterate the planner until it achieves the desired precision
      episodeTimeSoFar = 0.0;
      do {
	timeval plan_start = getTime();
	achievedPrecision =
	  solver.planFixedTime(sim->getModel()->getInitialState(),
			       /* maxTime = */ -1, /* minPrecision = */ minPrecision);
	deltaTime = timevalToSeconds(getTime() - plan_start);
	timeSoFar += deltaTime;
	episodeTimeSoFar += deltaTime;
      } while ( !(achievedPrecision && episodeTimeSoFar >= minWait) );

      // take one action
      action = solver.chooseAction(sim->getInformationState());
      sim->performAction(action);
      
      // check if we reached a terminal state
      if (sim->terminated) {
	achievedTerminalState = true;
	break;
      }
    }

    // record the total planning time and reward from this interleaved run
    scatterFile << timeSoFar << " "
		<< sim->rewardSoFar << " "
		<< achievedTerminalState << endl;

    boundsFile.close();
    simFile.close();
  }
  scatterFile.close();
}

void Interleave::batchTestIncremental(int numIterations,
				      AbstractSim* _sim,
				      Solver& solver,
				      int numSteps,
				      double minPrecision,
				      double minOrder, double maxOrder,
				      double ticksPerOrder,
				      const string& outFileName,
				      const string& boundsFileName,
				      const string& simFileName)
{
  int action, last_action;
  belief_vector last_belief, diff;
  bool can_reuse_last_action;

  sim = _sim;
  solver.planInit(sim->getModel());

  ofstream out( outFileName.c_str() );
  if (! out) {
    cerr << "ERROR: couldn't open " << outFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  ofstream boundsFile( boundsFileName.c_str() );
  if (! boundsFile) {
    cerr << "ERROR: couldn't open " << boundsFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  solver.setBoundsFile(&boundsFile);
  
  ofstream simOutFile( simFileName.c_str() );
  if (! simOutFile) {
    cerr << "ERROR: couldn't open " << simFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  double timeSoFar = 1e-20;
  double logLastSimTime = -99;
  bool achieved_precision = false;
  bool achieved_terminal_state;
  while (!achieved_precision && timeSoFar < pow(10,maxOrder)) {
    timeval plan_start = getTime();
    achieved_precision =
      solver.planFixedTime(sim->getModel()->getInitialState(),
			   /* maxTime = */ -1, minPrecision);
    double deltaTime = timevalToSeconds(getTime() - plan_start);
    timeSoFar += deltaTime;

    sim->simOutFile = &simOutFile;

    if ((timeSoFar > pow(10,minOrder)
	 && log(timeSoFar) - logLastSimTime > ::log(10) / ticksPerOrder)
	// ensure we do a simulation after the last iteration
	|| timeSoFar >= pow(10,maxOrder)) {
      logLastSimTime = ::log(timeSoFar);

      // repeatedly simulate, reusing the initial solution
      simOutFile << "----- time " << timeSoFar << endl;
      rewardRecord.clear();
      cout << endl;
      int num_successes = 0;
      FOR (i, numIterations) {
	cout << "#-#-#-#-#-#-# batchTest " << (i+1) << " / " << numIterations;
	cout.flush();
	if (i >= NUM_SIM_ITERATIONS_TO_LOG) {
	  sim->simOutFile = NULL;
	}
	sim->restart();
	last_action = -1;
	achieved_terminal_state = false;
	FOR (j, numSteps) {
	  can_reuse_last_action = false;
	  if (-1 != last_action) {
	    diff = sim->getInformationState();
	    diff -= last_belief;
	    if (norm_inf(diff) < 1e-10) {
	      can_reuse_last_action = true;
	    }
	  }
	  if (can_reuse_last_action) {
	    action = last_action;
	  } else {
	    action = solver.chooseAction(sim->getInformationState());
	  }

	  last_action = action;
	  last_belief = sim->getInformationState();

	  sim->performAction(action);

	  if (sim->terminated) {
	    num_successes++;
	    achieved_terminal_state = true;
	    break;
	  }
	}
	cout << " (reward " << sim->rewardSoFar << ")" << endl;
	rewardRecord.push_back(sim->rewardSoFar);
	if (!achieved_terminal_state) {
	  cout << "(time ran out in simulation)" << endl;
	}
      }
      
      // collect statistics and write a line to the output file
      double avg, stdev;
      calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);
      
      double success_rate = ((double) num_successes) / numIterations;

#if 0
      ValueInterval val = solver.getValueAt(model->getInitialState());
      // for some reason, if i use sqrt() instead of ::sqrt(), it's ambiguous
      out << timeSoFar << " " << avg << " "
	  << (stdev/::sqrt(numIterations)*1.96) << " "
	  << val.l << " " << val.u << " " << success_rate << endl;
#else
      out << timeSoFar
	  << " " << avg
	  << " " << (stdev/::sqrt(numIterations)*1.96)
	  << " " << success_rate << endl;
#endif
     
      out.flush();
    }
  }
  out.close();
  boundsFile.close();
  simOutFile.close();
}
  
void Interleave::printRewards(void) {
  cout << "rewards: ";
  FOR_EACH( reward, rewardRecord ) {
    cout << (*reward) << " ";
  }
  cout << endl;
  double avg, stdev;
  calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);
  cout << "reward avg stdev: " << avg << " " << stdev << endl;
}

}; // namespace zmdp

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.10  2006/02/01 01:09:37  trey
 * renamed pomdp namespace -> zmdp
 *
 * Revision 1.9  2006/01/28 03:02:14  trey
 * increased flexibiilty for use with mdps
 *
 * Revision 1.8  2005/11/03 20:23:22  trey
 * removed bounds information in inc.plot
 *
 * Revision 1.7  2005/10/28 03:50:32  trey
 * simplified license
 *
 * Revision 1.6  2005/10/28 02:51:40  trey
 * added copyright headers
 *
 * Revision 1.5  2005/10/27 22:11:43  trey
 * cleaned out cruft
 *
 * Revision 1.4  2005/10/21 20:06:32  trey
 * added shortcut for reusing actions if the belief has not changed
 *
 * Revision 1.4  2005/03/29 16:56:51  trey
 * added shortcut for reusing actions if the belief has not changed
 *
 * Revision 1.3  2005/03/28 18:10:50  trey
 * added debug statement during simulation
 *
 * Revision 1.2  2005/01/26 04:08:42  trey
 * switched to use sparseRep in debug print
 *
 * Revision 1.1  2004/11/13 23:29:44  trey
 * moved many files from hsvi to common
 *
 * Revision 1.2  2004/11/09 21:31:59  trey
 * got pomdp source tree into a building state again
 *
 * Revision 1.1.1.1  2004/11/09 16:18:56  trey
 * imported hsvi into new repository
 *
 * Revision 1.12  2003/09/22 16:57:57  trey
 * added tracking of success rate, and ensured we test simulation performance at the end of the run
 *
 * Revision 1.11  2003/09/20 02:26:09  trey
 * found a major problem in F_a_o_transpose, now fixed; added command-line options for experiments
 *
 * Revision 1.10  2003/09/18 21:00:29  trey
 * upper bound self-update seems to be working
 *
 * Revision 1.9  2003/09/17 20:54:24  trey
 * seeing good performance on tagAvoid (but some mods since run started...)
 *
 * Revision 1.8  2003/09/17 18:30:16  trey
 * seems to show best performance so far
 *
 * Revision 1.7  2003/09/16 00:57:02  trey
 * lots of performance tuning, mostly fixed rising upper bound problem
 *
 * Revision 1.6  2003/09/11 01:46:42  trey
 * completed conversion to compressed matrices
 *
 * Revision 1.5  2003/09/06 21:51:53  trey
 * many changes
 *
 * Revision 1.4  2003/07/24 15:33:43  trey
 * working test configuration for self-update
 *
 * Revision 1.3  2003/07/22 19:59:37  trey
 * several minor fixes; still observing discrepancy between sim and solver lower bound
 *
 * Revision 1.2  2003/07/17 22:19:53  trey
 * fixed problems with timing early in the solution run, added upperBoundQ
 *
 * Revision 1.1  2003/07/16 16:09:36  trey
 * initial check-in
 *
 *
 ***************************************************************************/
<commit_msg>now ensure simulation is performed at the end of the run if it ends because the target precision was achieved<commit_after>/********** tell emacs we use -*- c++ -*- style comments *******************
 $Revision: 1.12 $  $Author: trey $  $Date: 2006-02-15 16:21:16 $

 @file    Interleave.cc
 @brief   No brief

 Copyright (c) 2002-2005, <NAME>
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:

 * The software may not be sold or incorporated into a commercial
   product without specific prior written permission.
 * The above copyright notice and this permission notice shall be
   included in all copies or substantial portions of the software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 ***************************************************************************/

/***************************************************************************
 * INCLUDES
 ***************************************************************************/

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <iostream>
#include <fstream>

#include "zmdpCommonTime.h"
#include "Interleave.h"
#include "zmdpCommonDefs.h"
#include "MatrixUtils.h"

using namespace std;
using namespace MatrixUtils;

namespace zmdp {

#define NUM_SIM_ITERATIONS_TO_LOG (1)

void Interleave::interleave(int numIterations,
			    AbstractSim* _sim,
			    Solver& solver,
			    int numSteps,
			    double minPrecision,
			    double minWait,
			    const string& scatterFileName,
			    const string& boundsFileNameFmt,
			    const string& simFileNameFmt)
{
  int action;
  belief_vector last_belief, diff;
  ofstream scatterFile, boundsFile, simFile;
  char boundsFileName[PATH_MAX], simFileName[PATH_MAX];
  double deltaTime, timeSoFar, episodeTimeSoFar;
  bool achievedPrecision, achievedTerminalState;

  sim = _sim;

  scatterFile.open( scatterFileName.c_str() );
  if (! scatterFile) {
    cerr << "ERROR: couldn't open " << scatterFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  system("mkdir -p plots");

  FOR (i, numIterations) {
    cout << "=-=-=-=-= interleave: trial " << (i+1) << " / " << numIterations << endl;

    // reset the planner
    solver.planInit(sim->getModel(), minPrecision);

    // set up a new bounds file and sim file for each iteration
    snprintf( boundsFileName, sizeof(boundsFileName), boundsFileNameFmt.c_str(), i );
    boundsFile.open( boundsFileName );
    if (! boundsFile) {
      cerr << "ERROR: couldn't open " << boundsFileName << " for writing: "
	   << strerror(errno) << endl;
      exit(EXIT_FAILURE);
    }
    solver.setBoundsFile(&boundsFile);
    
    snprintf( simFileName, sizeof(simFileName), simFileNameFmt.c_str(), i );
    simFile.open( simFileName );
    if (! simFile) {
      cerr << "ERROR: couldn't open " << simFileName << " for writing: "
	   << strerror(errno) << endl;
      exit(EXIT_FAILURE);
    }
    sim->simOutFile = &simFile;

    // restart the sim
    sim->restart();
    timeSoFar = 0;
    achievedTerminalState = false;

    // run in interleaved mode
    FOR (t, numSteps) {
      cout << "#-#-#-#-#-#-# interleave: trial " << (i+1) << " / " << numIterations
	   << ", time step " << (t+1) << " / " << numSteps << endl;
      // iterate the planner until it achieves the desired precision
      episodeTimeSoFar = 0.0;
      do {
	timeval plan_start = getTime();
	achievedPrecision =
	  solver.planFixedTime(sim->getModel()->getInitialState(),
			       /* maxTime = */ -1, /* minPrecision = */ minPrecision);
	deltaTime = timevalToSeconds(getTime() - plan_start);
	timeSoFar += deltaTime;
	episodeTimeSoFar += deltaTime;
      } while ( !(achievedPrecision && episodeTimeSoFar >= minWait) );

      // take one action
      action = solver.chooseAction(sim->getInformationState());
      sim->performAction(action);
      
      // check if we reached a terminal state
      if (sim->terminated) {
	achievedTerminalState = true;
	break;
      }
    }

    // record the total planning time and reward from this interleaved run
    scatterFile << timeSoFar << " "
		<< sim->rewardSoFar << " "
		<< achievedTerminalState << endl;

    boundsFile.close();
    simFile.close();
  }
  scatterFile.close();
}

void Interleave::batchTestIncremental(int numIterations,
				      AbstractSim* _sim,
				      Solver& solver,
				      int numSteps,
				      double minPrecision,
				      double minOrder, double maxOrder,
				      double ticksPerOrder,
				      const string& outFileName,
				      const string& boundsFileName,
				      const string& simFileName)
{
  int action, last_action;
  belief_vector last_belief, diff;
  bool can_reuse_last_action;

  sim = _sim;
  solver.planInit(sim->getModel(), minPrecision);

  ofstream out( outFileName.c_str() );
  if (! out) {
    cerr << "ERROR: couldn't open " << outFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  ofstream boundsFile( boundsFileName.c_str() );
  if (! boundsFile) {
    cerr << "ERROR: couldn't open " << boundsFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }
  solver.setBoundsFile(&boundsFile);
  
  ofstream simOutFile( simFileName.c_str() );
  if (! simOutFile) {
    cerr << "ERROR: couldn't open " << simFileName << " for writing: "
	 << strerror(errno) << endl;
    exit(EXIT_FAILURE);
  }

  double timeSoFar = 1e-20;
  double logLastSimTime = -99;
  bool achieved_precision = false;
  bool achieved_terminal_state;
  while (!achieved_precision && timeSoFar < pow(10,maxOrder)) {
    timeval plan_start = getTime();
    achieved_precision =
      solver.planFixedTime(sim->getModel()->getInitialState(),
			   /* maxTime = */ -1, minPrecision);
    double deltaTime = timevalToSeconds(getTime() - plan_start);
    timeSoFar += deltaTime;

    sim->simOutFile = &simOutFile;

    if ((timeSoFar > pow(10,minOrder)
	 && log(timeSoFar) - logLastSimTime > ::log(10) / ticksPerOrder)
	// ensure we do a simulation after the last iteration
	|| timeSoFar >= pow(10,maxOrder)
	// or when the run ends because we achieved the desired precision
	|| achieved_precision) {
      logLastSimTime = ::log(timeSoFar);

      // repeatedly simulate, reusing the initial solution
      simOutFile << "----- time " << timeSoFar << endl;
      rewardRecord.clear();
      cout << endl;
      int num_successes = 0;
      FOR (i, numIterations) {
	cout << "#-#-#-#-#-#-# batchTest " << (i+1) << " / " << numIterations;
	cout.flush();
	if (i >= NUM_SIM_ITERATIONS_TO_LOG) {
	  sim->simOutFile = NULL;
	}
	sim->restart();
	last_action = -1;
	achieved_terminal_state = false;
	FOR (j, numSteps) {
	  can_reuse_last_action = false;
	  if (-1 != last_action) {
	    diff = sim->getInformationState();
	    diff -= last_belief;
	    if (norm_inf(diff) < 1e-10) {
	      can_reuse_last_action = true;
	    }
	  }
	  if (can_reuse_last_action) {
	    action = last_action;
	  } else {
	    action = solver.chooseAction(sim->getInformationState());
	  }

	  last_action = action;
	  last_belief = sim->getInformationState();

	  sim->performAction(action);

	  if (sim->terminated) {
	    num_successes++;
	    achieved_terminal_state = true;
	    break;
	  }
	}
	cout << " (reward " << sim->rewardSoFar << ")" << endl;
	rewardRecord.push_back(sim->rewardSoFar);
	if (!achieved_terminal_state) {
	  cout << "(time ran out in simulation)" << endl;
	}
      }
      
      // collect statistics and write a line to the output file
      double avg, stdev;
      calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);
      
      double success_rate = ((double) num_successes) / numIterations;

#if 0
      ValueInterval val = solver.getValueAt(model->getInitialState());
      // for some reason, if i use sqrt() instead of ::sqrt(), it's ambiguous
      out << timeSoFar << " " << avg << " "
	  << (stdev/::sqrt(numIterations)*1.96) << " "
	  << val.l << " " << val.u << " " << success_rate << endl;
#else
      out << timeSoFar
	  << " " << avg
	  << " " << (stdev/::sqrt(numIterations)*1.96)
	  << " " << success_rate << endl;
#endif
     
      out.flush();
    }
  }
  out.close();
  boundsFile.close();
  simOutFile.close();
}
  
void Interleave::printRewards(void) {
  cout << "rewards: ";
  FOR_EACH( reward, rewardRecord ) {
    cout << (*reward) << " ";
  }
  cout << endl;
  double avg, stdev;
  calc_avg_stdev_collection(rewardRecord.begin(), rewardRecord.end(), avg, stdev);
  cout << "reward avg stdev: " << avg << " " << stdev << endl;
}

}; // namespace zmdp

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.11  2006/02/06 19:28:55  trey
 * now make a sim trace only for the first simulation run in each batch, saves much time and disk space
 *
 * Revision 1.10  2006/02/01 01:09:37  trey
 * renamed pomdp namespace -> zmdp
 *
 * Revision 1.9  2006/01/28 03:02:14  trey
 * increased flexibiilty for use with mdps
 *
 * Revision 1.8  2005/11/03 20:23:22  trey
 * removed bounds information in inc.plot
 *
 * Revision 1.7  2005/10/28 03:50:32  trey
 * simplified license
 *
 * Revision 1.6  2005/10/28 02:51:40  trey
 * added copyright headers
 *
 * Revision 1.5  2005/10/27 22:11:43  trey
 * cleaned out cruft
 *
 * Revision 1.4  2005/10/21 20:06:32  trey
 * added shortcut for reusing actions if the belief has not changed
 *
 * Revision 1.4  2005/03/29 16:56:51  trey
 * added shortcut for reusing actions if the belief has not changed
 *
 * Revision 1.3  2005/03/28 18:10:50  trey
 * added debug statement during simulation
 *
 * Revision 1.2  2005/01/26 04:08:42  trey
 * switched to use sparseRep in debug print
 *
 * Revision 1.1  2004/11/13 23:29:44  trey
 * moved many files from hsvi to common
 *
 * Revision 1.2  2004/11/09 21:31:59  trey
 * got pomdp source tree into a building state again
 *
 * Revision 1.1.1.1  2004/11/09 16:18:56  trey
 * imported hsvi into new repository
 *
 * Revision 1.12  2003/09/22 16:57:57  trey
 * added tracking of success rate, and ensured we test simulation performance at the end of the run
 *
 * Revision 1.11  2003/09/20 02:26:09  trey
 * found a major problem in F_a_o_transpose, now fixed; added command-line options for experiments
 *
 * Revision 1.10  2003/09/18 21:00:29  trey
 * upper bound self-update seems to be working
 *
 * Revision 1.9  2003/09/17 20:54:24  trey
 * seeing good performance on tagAvoid (but some mods since run started...)
 *
 * Revision 1.8  2003/09/17 18:30:16  trey
 * seems to show best performance so far
 *
 * Revision 1.7  2003/09/16 00:57:02  trey
 * lots of performance tuning, mostly fixed rising upper bound problem
 *
 * Revision 1.6  2003/09/11 01:46:42  trey
 * completed conversion to compressed matrices
 *
 * Revision 1.5  2003/09/06 21:51:53  trey
 * many changes
 *
 * Revision 1.4  2003/07/24 15:33:43  trey
 * working test configuration for self-update
 *
 * Revision 1.3  2003/07/22 19:59:37  trey
 * several minor fixes; still observing discrepancy between sim and solver lower bound
 *
 * Revision 1.2  2003/07/17 22:19:53  trey
 * fixed problems with timing early in the solution run, added upperBoundQ
 *
 * Revision 1.1  2003/07/16 16:09:36  trey
 * initial check-in
 *
 *
 ***************************************************************************/

{'fraction_non_alphanumeric': 0.15320548413274676, 'fraction_numerical': 0.04070388245846325, 'mean_word_length': 3.2977239353891337, 'pattern_counts': {'":': 0, '<': 393, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1161316', 'n_tokens_mistral': 8435, 'n_tokens_neox': 7376, 'n_words': 2114}