GillespieIntegrator::GillespieIntegrator(ExecutableModel* m,
        const SimulateOptions* o) :
        model(m),
        timeScale(1.0),
        stoichScale(1.0),
        stoichRows(0),
        stoichCols(0),
        stoichData(0),
        seed(defaultSeed()) // default value for mersene twister
{
    if (o)
    {
        this->options = *o;
    }

    nReactions = model->getNumReactions();
    reactionRates = new double[nReactions];
    reactionRatesBuffer = new double[nReactions];
    stateVectorSize = model->getStateVector(0);
    stateVector = new double[stateVectorSize];
    stateVectorRate = new double[stateVectorSize];

    floatingSpeciesStart = stateVectorSize - model->getNumIndFloatingSpecies();

    assert(floatingSpeciesStart >= 0);

    // get rows and columns
    model->getStoichiometryMatrix(&stoichRows, &stoichCols, 0);
    stoichData = new double[stoichRows * stoichCols];

    // fill stoichData
    model->getStoichiometryMatrix(&stoichRows, &stoichCols, &stoichData);

    setEngineSeed(seed);
}
	void GillespieIntegrator::setValue(string key, const Variant& val)
	{
		Integrator::setValue(key, val);

		/*	In addition to typically value-setting behavior, some settings require further changes
		within CVODE. */
		if (key == "seed")
		{
			try
			{
				unsigned long seed = val.convert<unsigned long>();
				setEngineSeed(seed);
			}
			catch (std::exception& e)
			{
				std::stringstream ss;
				ss << "Could not convert the value \"" << val.toString();
				ss << "\" to an unsigned long integer. " << endl;
				ss << "The seed must be a number between 0 and ";
				ss << std::numeric_limits<unsigned long>::max();
				ss << "; error message: " << e.what() << ".";
				throw std::invalid_argument(ss.str());
			}
		}
	}
void GillespieIntegrator::setSeed(const rr::Variant& value)
{
    try
    {
        unsigned long seed = value.convert<unsigned long>();
        this->seed = seed;
        setEngineSeed(seed);
    }
    catch(std::exception& e)
    {
        std::stringstream ss;
        ss << "Could not convert the value \"" << value.toString();
        ss << "\" to an unsigned long integer. " << endl;
        ss << "The seed must be a number between 0 and ";
        ss << std::numeric_limits<unsigned long>::max();
        ss << "; error message: " << e.what() << ".";
        throw std::invalid_argument(ss.str());
    }
}
	void GillespieIntegrator::initializeFromModel() {
        nReactions = model->getNumReactions();
        reactionRates = new double[nReactions];
        reactionRatesBuffer = new double[nReactions];
        stateVectorSize = model->getStateVector(0);
        stateVector = new double[stateVectorSize];
        stateVectorRate = new double[stateVectorSize];

        eventStatus = std::vector<unsigned char>(model->getEventTriggers(0, 0, 0), false);
        previousEventStatus = std::vector<unsigned char>(model->getEventTriggers(0, 0, 0), false);

        floatingSpeciesStart = stateVectorSize - model->getNumIndFloatingSpecies();

        assert(floatingSpeciesStart >= 0);

        // get rows and columns
        model->getStoichiometryMatrix(&stoichRows, &stoichCols, 0);
        stoichData = new double[stoichRows * stoichCols];

        // fill stoichData
        model->getStoichiometryMatrix(&stoichRows, &stoichCols, &stoichData);

        setEngineSeed(getValue("seed").convert<unsigned long>());
	}