string Relation::tuplesToString()
{
    string out;
    for(set<Tuple>::iterator it = tuples->begin(); it != tuples->end(); it++)
    {
        Tuple thisTuple = (*it);
        if(thisTuple.toString() != "")
        {
            out += "\n";
        }
        out += "  " + thisTuple.toString();
    }
    return out;
}
string Relation::solvedQueryToString(vector<Token>& inputTokens)
{
    string out;
    vector<Token> noStrings = removeStrings(inputTokens);
    vector<std::pair<Token, vector<int> > > myMap;
    for(int i = 0; i < noStrings.size(); i++)
    {
        bool inserted = false;
        for(int j = 0; j < myMap.size(); j++)
        {
            if(myMap[j].first.getTokensValue() == noStrings[i].getTokensValue())
            {
                myMap[j].second.push_back(i);
                inserted = true;
            }
        }
        if(!inserted && noStrings[i].getTokenType() == ID)
        { 
            vector<int> newVec;
            newVec.push_back(i);
            myMap.push_back(pair<Token, vector<int> >(noStrings[i], newVec) );
        }
    }

    for(set<Tuple>::iterator it = tuples->begin(); it != tuples->end(); it++)
    {
        int firstInMapVector = 0;
        Tuple thisTuple = (*it);
        if(thisTuple.toString() != "")
        {
            out += "\n  ";
        }
        for(int i = 0; i < myMap.size(); i++)
        {
            if(myMap[i].first.getTokenType() == ID)
            {
                out += myMap[i].first.getTokensValue() + "=";
                out += thisTuple.getTokenFromPairAt(myMap[i].second[firstInMapVector]).getTokensValue();
                if(i + 1 != myMap.size())
                {
                    out += ", ";
                }
            }
        }
    }
    return out;
}
string Relation::toString()
{
    string out = "";
    out += Id->getTokensValue();
    out += ":";
    out += schema->toString() + "\n";
    for(set<Tuple>::iterator it = tuples->begin(); it != tuples->end(); it++)
    {
        for(int i = 0; i < Id->getTokensValue().length(); i++)
        {
            out += " ";
        }
        Tuple thisTuple = (*it);
        out += "  " + thisTuple.toString() + "\n";
    }
    return out;
}
RCP<EpetraExt::ModelEvaluator> ReducedOrderModelFactory::create(const RCP<EpetraExt::ModelEvaluator> &child)
{
  RCP<EpetraExt::ModelEvaluator> result = child;

  if (useReducedOrderModel()) {
    const RCP<ParameterList> romParams = extractReducedOrderModelParams(params_);

    const Tuple<std::string, 2> allowedProjectionTypes = tuple<std::string>("Galerkin Projection", "Minimum Residual");
    const std::string projectionType = romParams->get("System Reduction", allowedProjectionTypes[0]);
    TEUCHOS_TEST_FOR_EXCEPTION(!contains(allowedProjectionTypes, projectionType),
                               std::out_of_range,
                               projectionType + " not in " + allowedProjectionTypes.toString());

    const RCP<const ReducedSpace> reducedSpace = spaceFactory_->create(romParams);
    const RCP<const Epetra_MultiVector> basis = spaceFactory_->getBasis(romParams);

    if (projectionType == allowedProjectionTypes[0]) {
      const RCP<const Epetra_MultiVector> projector = spaceFactory_->getProjector(romParams);
      const RCP<ReducedOperatorFactory> opFactory(new PetrovGalerkinOperatorFactory(basis, projector));
      result = rcp(new ReducedOrderModelEvaluator(child, reducedSpace, opFactory));
    } else if (projectionType == allowedProjectionTypes[1]) {
      RCP<ReducedOperatorFactory> opFactory;

      const RCP<const Epetra_Operator> collocationOperator =
        spaceFactory_->getSamplingOperator(romParams, *child->get_x_map());
      if (nonnull(collocationOperator)) {
        opFactory = rcp(new GaussNewtonMetricOperatorFactory(basis, collocationOperator));
      } else {
        opFactory = rcp(new GaussNewtonOperatorFactory(basis));
      }

      result = rcp(new ReducedOrderModelEvaluator(child, reducedSpace, opFactory));
    } else {
      TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "Should not happen");
    }
  }

  return result;
}