/*!
 *  \brief Main routine for the even-6 parity problem.
 *  \param argc Number of arguments on the command-line.
 *  \param argv Arguments on the command-line.
 *  \return Return value of the program.
 *  \ingroup Parity
 */
int main(int argc, char *argv[])
{
	try {

		// Build primitives
		GP::PrimitiveSuperSet::Handle lSuperSet = new GP::PrimitiveSuperSet;
		lSuperSet->addPrimitive(new GP::BitwiseAnd("AND"), true);
		lSuperSet->addPrimitive(new GP::BitwiseOr("OR"), true);
		lSuperSet->addPrimitive(new GP::BitwiseNand("NAND"), true);
		lSuperSet->addPrimitive(new GP::BitwiseNor("NOR"), true);
		lSuperSet->addPrimitive(new GP::BitwiseNot("NOT"), true);
		lSuperSet->addPrimitive(new GP::BitwiseXor("XOR"), true);
		lSuperSet->addPrimitive(new GP::ADF(GP::Invoker::eGenerator, GP::Primitive::eAny, "ADFP", "ARGP"));
		lSuperSet->addPrimitive(new GP::ArgumentT<Int>(GP::Argument::eCaching, GP::Argument::eGenerator, "ARGP"));
		GP::PrimitiveSet::Handle lSet = new GP::PrimitiveSet;
		lSet->insert(new GP::BitwiseAnd("AND"));
		lSet->insert(new GP::BitwiseOr("OR"));
		lSet->insert(new GP::BitwiseNand("NAND"));
		lSet->insert(new GP::BitwiseNor("NOR"));
		for (unsigned int i=0; i<ParitySizeM; i++) {
			lSet->insert(new GP::TokenT<Int>(std::string("IN")+uint2str(i)));
		}
		lSuperSet->insert(lSet);

		// Build a system
		System::Handle lSystem = new System;

		// Set GP package
		lSystem->addPackage(new GP::PackageBase(lSuperSet));
		lSystem->addPackage(new GP::PackageConstrained);

		// Set fitness evaluation operator allocator
		lSystem->setEvaluationOp("ParityEvalOp", new ParityFastEvalOp::Alloc);

		// Initialize the evolver
		Evolver::Handle lEvolver = new Evolver;
		lEvolver->initialize(lSystem, argc, argv);

		// Create population
		Vivarium::Handle lVivarium = new Vivarium;

		// Launch evolution
		lEvolver->evolve(lVivarium, lSystem);

	} catch(Exception& inException) {
		inException.terminate();
	} catch(exception& inException) {
		cerr << "Standard exception caught:" << endl;
		cerr << inException.what() << endl << flush;
		return 1;
	} catch(...) {
		cerr << "Unknown exception caught!" << endl << flush;
		return 1;
	}
	return 0;
}
/*!
 *  \brief Main routine for the function symbolic regression problem.
 *  \param argc Number of arguments on the command-line.
 *  \param argv Arguments on the command-line.
 *  \return Return value of the program.
 *  \ingroup SymbReg
 */
int main(int argc, char *argv[]) {
	try {
		// 1: Build primitives.
		GP::PrimitiveSet::Handle lSet = new GP::PrimitiveSet;
		lSet->insert(new GP::Add);
		lSet->insert(new GP::Subtract);
		lSet->insert(new GP::Multiply);
		lSet->insert(new GP::Divide);
		//lSet->insert(new GP::Sin);
		//lSet->insert(new GP::Cos);
		//lSet->insert(new GP::Exp);
		//lSet->insert(new GP::Log);
		lSet->insert(new GP::TokenT<Double>("X"));
		//lSet->insert(new GP::TokenT<Double>("Pi", Double(M_PI)));
		//lSet->insert(new GP::EphemeralDouble);
		// 2: Build a system.
		GP::System::Handle lSystem = new GP::System(lSet);
		// 3: Build evaluation operator.
		SymbRegEvalOp::Handle lEvalOp = new SymbRegEvalOp;
		// 4: Build an evolver and a vivarium.
#ifdef WITHOUT_MPI
		GP::Evolver::Handle lEvolver = new GP::Evolver(lEvalOp);
#else
		MPI::GP::Evolver::Handle lEvolver = new MPI::GP::Evolver(lEvalOp);
#endif
		GP::Vivarium::Handle lVivarium = new GP::Vivarium;
		// 5: Initialize and evolve the vivarium.
		lEvolver->initialize(lSystem, argc, argv);
		lEvolver->evolve(lVivarium);
	}
	catch(Exception& inException) {
		inException.terminate();
	}
	catch(exception& inException) {
		cerr << "Standard exception catched:" << endl;
		cerr << inException.what() << endl << flush;
		return 1;
	}
	catch(...) {
		cerr << "Unknown exception catched!" << endl << flush;
		return 1;
	}
	return 0;
}
int main(int argc, char *argv[]) {
    try {

        // 1: Build primitives.
        GP::PrimitiveSet::Handle lSet = new GP::PrimitiveSet(&(typeid(RootReturn)));

        lSet->insert(new ThreeTanksEmbryo);

        lSet->insert(new ReplaceR);
        //		lSet->insert(new ReplaceC);
        //		lSet->insert(new ReplaceI);

        lSet->insert(new AddSwitch);
        lSet->insert(new AddR);
        //		lSet->insert(new AddC);
        //		lSet->insert(new AddI);

        lSet->insert(new InsertJ01);
        lSet->insert(new InsertJ10);

        lSet->insert(new EndBond);
        //lSet->insert(new EndEph);
        lSet->insert(new EndNode);
        lSet->insert(new EndJct);

        lSet->insert(new GP::MultiplyT<Double>);
        lSet->insert(new GP::DivideT<Double>);
        lSet->insert(new GP::AddT<Double>);
        lSet->insert(new GP::SubtractT<Double>);
        lSet->insert(new GP::EphemeralDouble);


        // 2: Build a system.
        BGContext::Alloc::Handle lContextAlloc = new BGContext::Alloc;

        GP::System::Handle lSystem = new GP::System(lSet,lContextAlloc);

        // 3: Build evaluation operator.
        ThreeTanksEvalOp::Handle lEvalOp = new ThreeTanksEvalOp;

        // 4: Build an evolver and a vivarium.
        TreeSTag::Alloc::Handle lTreeAlloc = new TreeSTag::Alloc;
        //GP::Tree::Alloc::Handle lTreeAlloc = new GP::Tree::Alloc;
        BGFitness::Alloc::Handle lFitAlloc = new BGFitness::Alloc;
        GP::Vivarium::Handle lVivarium = new GP::Vivarium(lTreeAlloc,lFitAlloc);

        GP::Evolver::Handle lEvolver = new GP::Evolver(lEvalOp);
        lEvolver->initialize(lSystem, argc, argv);

        //Read individual from file
        ostringstream lFilename;
        lFilename << "individual-best153.xml";

        GP::Individual::Handle lIndividual = new GP::Individual(lTreeAlloc);
        lIndividual->readFromFile(lFilename.str(), *lSystem);

        BGContext::Handle lContext = castHandleT<BGContext>(lSystem->getContextAllocator().allocate());
        lContext->setSystemHandle(lSystem);
        lContext->setIndividualHandle(lIndividual);
        lContext->setIndividualIndex(0);

        BGFitness::Handle lFitness = castHandleT<BGFitness>(lEvalOp->evaluate(*lIndividual,*lContext));

        //TreeSTag::Handle lTree = castHandleT<TreeSTag>((*lIndividual)[0]);
        GrowingHybridBondGraph::Handle lBondGraph = castHandleT<GrowingHybridBondGraph>(lFitness->getBondGraph());
        //lBondGraph->simplify();
        lBondGraph->plotGraph("bondgraph.svg",false);

        cout << "\nResulting fitness: " << endl;
        cout << lFitness->serialize() << endl;

    }

    catch(Exception& inException) {
        inException.terminate();
    }
    catch(exception& inException) {
        cerr << "Standard exception catched:" << endl;
        cerr << inException.what() << endl << flush;
        return 1;
    }
    catch(...) {
        cerr << "Unknown exception catched!" << endl << flush;
        return 1;
    }

    return 0;
}