From 1785e4285af1a0fbc6970ab68494be2b423d59a6 Mon Sep 17 00:00:00 2001 From: Love Billenius Date: Mon, 16 Sep 2024 13:18:17 +0200 Subject: [PATCH] init --- .gitignore | 12 ++ Event.cpp | 136 ++++++++++++ Event.h | 80 ++++++++ Fish.cpp | 92 +++++++++ Fish.h | 45 ++++ MyException.h | 16 ++ MyPriorityQueue.h | 81 ++++++++ MyVector.h | 128 ++++++++++++ README.md | 2 + Simulation.cpp | 120 +++++++++++ Simulation.h | 63 ++++++ answers.txt | 0 config.h | 29 +++ fisher.pro | 8 + main.cpp | 77 +++++++ test-harness-myprio.cpp | 322 +++++++++++++++++++++++++++++ test-harness-myvector.cpp | 422 ++++++++++++++++++++++++++++++++++++++ 17 files changed, 1633 insertions(+) create mode 100755 .gitignore create mode 100755 Event.cpp create mode 100755 Event.h create mode 100755 Fish.cpp create mode 100755 Fish.h create mode 100755 MyException.h create mode 100755 MyPriorityQueue.h create mode 100755 MyVector.h create mode 100755 README.md create mode 100755 Simulation.cpp create mode 100755 Simulation.h create mode 100755 answers.txt create mode 100755 config.h create mode 100755 fisher.pro create mode 100755 main.cpp create mode 100755 test-harness-myprio.cpp create mode 100755 test-harness-myvector.cpp diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..cfa84e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*~ + +.DS_Store + +*.pro.user.* +*.pro.user + +build-*/ +*.app +*.exe + +build diff --git a/Event.cpp b/Event.cpp new file mode 100755 index 0000000..bd6d6a6 --- /dev/null +++ b/Event.cpp @@ -0,0 +1,136 @@ +#include "Event.h" +#include "Simulation.h" +#include +#include + +void hatchEvent::processEvent (Simulation& sim) { + double total = sim.getJuvenilePopulation() + sim.getAdultPopulation(); + double saturation = min(total/STARVE_THRESHOLD, 1.0); + unsigned ageAverage = MAX_AGE * (1 - saturation); + uniform_int_distribution ageDist(0.1 * ageAverage, 1.9 * ageAverage); + unsigned ageExpectancy = ageDist(generator); + + Fish* afish = new Fish(eventTime, ageExpectancy); + sim.decEggPopulation(); + sim.incJuvenilePopulation(); + sim.addFish(afish); + + uniform_int_distribution juvDist(0.8* AVG_MATURATION_TM, 1.2* AVG_MATURATION_TM); + unsigned juvenileFor = juvDist(generator); + + if( ageExpectancy < juvenileFor){ + sim.scheduleEvent(new deathEvent(eventTime + ageExpectancy, afish)); + }else{ + sim.scheduleEvent(new matureEvent(eventTime + juvenileFor, afish, generator)); + } +} + + +void spawnEvent::processEvent (Simulation& sim) { + if(afish->isCaught()){ + delete afish; + afish = nullptr; + return; + } + double concentration = min(sim.getAdultPopulation() / (double)SPAWN_THRESHOLD, 1.0); + unsigned avg_max_egg_num = + (concentration < MIN_SPAWN_CONC ? 0 : concentration * MAX_AVG_EGGS_NUM); + uniform_int_distribution eggDist(0.8 * avg_max_egg_num, 1.2 * avg_max_egg_num); + unsigned eggs_num = eggDist(generator); + + sim.incEggPopulation(eggs_num); + + uniform_int_distribution hatchDist(0.6 * HATCH_TM, 1.4 * HATCH_TM); + for(unsigned e=0; e < eggs_num; e++){ + unsigned hatchIn = hatchDist(generator); + sim.scheduleEvent(new hatchEvent(eventTime + hatchIn, generator)); + } + unsigned nextSeasonIn = round((eventTime + 365)/(double)365)*365 - eventTime; + uniform_int_distribution spawnDist(nextSeasonIn - 30, nextSeasonIn + 30); + unsigned spawningIn = spawnDist(generator); + + if(afish->getRemainingLifeExpectancy(eventTime) < spawningIn){ + sim.scheduleEvent(new deathEvent(eventTime + afish->getRemainingLifeExpectancy(eventTime), afish)); + }else{ + sim.scheduleEvent(new spawnEvent(eventTime + spawningIn, afish, generator)); + } +} + +void spawnEvent::withdrawEvent () { + if(afish->isCaught()){ + delete afish; + afish = nullptr; + } +} + + +void matureEvent::processEvent (Simulation& sim) { + if(afish->isCaught()){ + delete afish; + afish = nullptr; + return; + } + afish->makeAdult(eventTime); + sim.decJuvenilePopulation(); + sim.incAdultPopulation(); + + unsigned nextSeasonIn = round((eventTime + 365)/(double)365)*365 - eventTime; + uniform_int_distribution spawnDist(nextSeasonIn - 30, nextSeasonIn + 30); + unsigned spawningIn = spawnDist(generator); + + if(afish->getRemainingLifeExpectancy(eventTime) < spawningIn) + sim.scheduleEvent(new deathEvent(eventTime + afish->getRemainingLifeExpectancy(eventTime), afish)); + else + sim.scheduleEvent(new spawnEvent(eventTime + spawningIn, afish, generator)); +} + +void matureEvent::withdrawEvent () { + if(afish->isCaught()){ + delete afish; + afish= nullptr; + } +} + +void deathEvent::processEvent (Simulation& sim){ + if(afish->isCaught()){ + delete afish; + afish = nullptr; + return; + } + if(afish->isJuvenile()){ + sim.decJuvenilePopulation(); + } else if(afish->isAdult()) { + sim.decAdultPopulation(); + } + afish->makeDead(); +} + +void deathEvent::withdrawEvent (){ + if(afish->isCaught()){ + delete afish; + afish=nullptr; + } +} + +void harvestEvent::processEvent (Simulation& sim) { + sim.harvestTonnageNow(LANDING,generator); + sim.scheduleEvent(new harvestEvent(eventTime + HARVEST_PERIOD, generator)); +} + +void printEvent::processEvent (Simulation& sim) { + file << eventTime + << '\t' << sim.getEggPopulation() + << '\t' << sim.getJuvenilePopulation() + << '\t' << sim.getAdultPopulation() + << '\t' << sim.getJuvenilePopulation() + sim.getAdultPopulation() + << endl; + + cout << eventTime + << '\t' << sim.getEggPopulation() + << '\t' << sim.getJuvenilePopulation() + << '\t' << sim.getAdultPopulation() + << '\t' << sim.getJuvenilePopulation() + sim.getAdultPopulation() + << endl; + + sim.scheduleEvent(new printEvent(eventTime + PRINT_PERIOD, file)); +} diff --git a/Event.h b/Event.h new file mode 100755 index 0000000..f13c1b3 --- /dev/null +++ b/Event.h @@ -0,0 +1,80 @@ +#ifndef EVENT_H +#define EVENT_H + +#include "Fish.h" +#include "config.h" +#include +#include + +using namespace std; + +class Simulation; + +class Event { +public: + Event (unsigned t) : eventTime(t){ } + virtual ~Event(){} + virtual void processEvent (Simulation&) = 0; + virtual void withdrawEvent() = 0; + const unsigned eventTime; +}; + +struct EventComparator { + bool operator() (const Event * left, const Event * right) const { + return left->eventTime > right->eventTime; + } +}; + + +class hatchEvent : public Event { + mt19937& generator; +public: + hatchEvent (unsigned t, mt19937& gen) : Event(t), generator(gen) {} + virtual void processEvent (Simulation& sim); + virtual void withdrawEvent(){} +}; + +class spawnEvent : public Event { + Fish* afish; + mt19937& generator; +public: + spawnEvent (unsigned t, Fish* _afish, mt19937& gen) : Event(t), afish(_afish), generator(gen){} + virtual void processEvent (Simulation& sim); + virtual void withdrawEvent(); +}; + +class matureEvent : public Event { + Fish* afish; + mt19937& generator; +public: + matureEvent (unsigned t, Fish* _afish, mt19937& gen) : Event(t), afish(_afish),generator(gen){} + virtual void processEvent (Simulation& sim); + virtual void withdrawEvent(); +}; + + +class deathEvent : public Event { + Fish* afish; +public: + deathEvent (unsigned t, Fish* _afish) : Event(t), afish(_afish) {} + virtual void processEvent (Simulation& sim); + virtual void withdrawEvent(); +}; + +class harvestEvent : public Event { + mt19937& generator; +public: + harvestEvent (unsigned t, mt19937& gen): Event(t), generator(gen) {} + virtual void processEvent (Simulation& sim); + virtual void withdrawEvent() {} +}; + +class printEvent : public Event { + ofstream& file; +public: + printEvent (unsigned t, ofstream& f) : Event(t), file(f){} + virtual void processEvent (Simulation& sim); + virtual void withdrawEvent() {} +}; + +#endif // EVENT_H diff --git a/Fish.cpp b/Fish.cpp new file mode 100755 index 0000000..de268cf --- /dev/null +++ b/Fish.cpp @@ -0,0 +1,92 @@ +#include "Fish.h" +#include +#include + +unsigned Fish::counter= 0; + +Fish::Fish(unsigned time, unsigned _lifeExpectancy): + hatchedTime(time),lifeExpectancy(_lifeExpectancy), id(++counter){ +} + +void Fish::makeAdult(unsigned t){ + assert(phase==JuvenilePhase && " making a non juvenile fish adult"); + adultTime = t; + phase = AdultPhase; +} + +void Fish::makeDead(){ + bool aliveFree = isJuvenile() || isAdult(); + assert(aliveFree && " killing a dead or caught fish"); + phase = DeadPhase; +} + +void Fish::makeCaught(){ + bool aliveFree = isJuvenile() || isAdult(); + assert(aliveFree && " catching a dead or caught fish"); + phase = CaughtPhase; +} + + +bool Fish::isJuvenile()const{ + return phase == JuvenilePhase; +} + +bool Fish::isAdult()const{ + return phase == AdultPhase; +} + +bool Fish::isCaught()const{ + return phase == CaughtPhase; +} + +bool Fish::isDead()const{ + return phase == DeadPhase; +} + +unsigned Fish::getRemainingLifeExpectancy(unsigned now)const{ + if (now > (lifeExpectancy + hatchedTime)) + return 0; + return lifeExpectancy + hatchedTime - now; +} + +bool Fish::catchableNow(unsigned now)const{ + return (now - hatchedTime) > MIN_CATCHABLE_AGE; +} + + +unsigned Fish::getWeightOnCatch(unsigned tm)const{ + unsigned age = tm - hatchedTime; + return(age < MIN_KEPT_AGE? 0 : age); +} + +std::string Fish::print()const{ + std::stringstream rslt; + rslt << "fish"; + switch(phase){ + case JuvenilePhase: + rslt << "j("; + break; + case AdultPhase: + rslt << "a("; + break; + case DeadPhase: + rslt << "d("; + break; + case CaughtPhase: + rslt << "c("; + break; + default: + rslt << "x("; + break; + } + rslt << id << ")(le=" << lifeExpectancy; + rslt << ", ht=" << hatchedTime; + rslt << ", at=" << adultTime << ")" ; + return rslt.str(); +} + + +std::ostream& operator<<(std::ostream& out, const Fish& fish){ + out << fish.print(); + return out; +} diff --git a/Fish.h b/Fish.h new file mode 100755 index 0000000..898cccd --- /dev/null +++ b/Fish.h @@ -0,0 +1,45 @@ +#ifndef FISH_H +#define FISH_H + +#include "config.h" +#include + +class Fish { + +public: + enum Phase {JuvenilePhase, AdultPhase, DeadPhase, CaughtPhase}; + Phase phase=JuvenilePhase; + + unsigned hatchedTime=0; + unsigned adultTime=0; + unsigned lifeExpectancy=0; + unsigned id = 0; + static unsigned counter; + + + +public: + Fish(unsigned time, unsigned _lifeExpectancy); + + void makeAdult(unsigned); + void makeDead(); + void makeCaught(); + + + bool isJuvenile() const; + bool isAdult()const; + bool isCaught()const; + bool isDead()const; + + + + std::string print()const; + + bool catchableNow(unsigned)const; + unsigned getWeightOnCatch(unsigned tm)const; + unsigned getRemainingLifeExpectancy(unsigned tm)const; +}; + +std::ostream& operator<<(std::ostream& out, const Fish& fish); + +#endif // FISH_H diff --git a/MyException.h b/MyException.h new file mode 100755 index 0000000..37de199 --- /dev/null +++ b/MyException.h @@ -0,0 +1,16 @@ +#ifndef MYEXCEPTION_H +#define MYEXCEPTION_H + +#include + +#define MYEXCEPTION(msg) MyException(msg, __FILE__, __LINE__) + +inline void MyException(const std::string& msg, + char* file, + unsigned line){ + std::stringstream ss; + ss << msg << " at " << file << ":" << line; + throw std::runtime_error(ss.str()); +} + +#endif // MYEXCEPTION_H diff --git a/MyPriorityQueue.h b/MyPriorityQueue.h new file mode 100755 index 0000000..3ba61b6 --- /dev/null +++ b/MyPriorityQueue.h @@ -0,0 +1,81 @@ +// This is the second .h file you will edit +// We have provided a skeleton for you, +// but you must finish it as described in the spec. +// Also remove these comments here and add your own, as well as on the members. +// TODO: remove this comment header + +#ifndef MY_PRIORITY_QUEUE_H +#define MY_PRIORITY_QUEUE_H + +#include "MyVector.h" +#include "MyException.h" + + +template +class MyPriorityQueue +{ + MyVector vector_array; + C strictly_larger_operator; + +public: + MyPriorityQueue(); + + ~MyPriorityQueue(); + + void push(const T& t); + + T top()const; + + void pop(); + + bool empty()const; + + unsigned size() const; + +private: + // Other private members? +}; + +template +MyPriorityQueue::MyPriorityQueue(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +MyPriorityQueue::~MyPriorityQueue(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +void MyPriorityQueue::push(const T& t){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +T MyPriorityQueue::top()const{ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +void MyPriorityQueue::pop(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +bool MyPriorityQueue::empty()const{ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +unsigned MyPriorityQueue::size()const{ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +#endif // MY_PRIORITY_QUEUE_H diff --git a/MyVector.h b/MyVector.h new file mode 100755 index 0000000..1044faf --- /dev/null +++ b/MyVector.h @@ -0,0 +1,128 @@ +// This is the first .h file you will edit +// We have provided a skeleton for you, +// but you must finish it as described in the spec. +// Also remove these comments here and add your own, as well as on the members. +// TODO: remove this comment header + +#ifndef MY_VECTOR_H +#define MY_VECTOR_H + +#include "MyException.h" + +template +class MyVector +{ + +public: + MyVector(); + + ~MyVector(); + + MyVector(const MyVector& other); + + MyVector& operator =(const MyVector& other); + + + void push_back(const T&); + + void pop_back(); + + T& operator[](unsigned i); + + const T& operator[](unsigned i)const; + + bool empty()const; + + T* begin(); + + T* end(); + + void clear(); + + unsigned size()const; + +private: + + // private members? + +}; + +template +MyVector::MyVector(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +MyVector::~MyVector(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +MyVector::MyVector(const MyVector& other){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +MyVector& MyVector::operator =(const MyVector& other){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +void MyVector::push_back(const T& e){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +void MyVector::pop_back(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +T& MyVector::operator[](unsigned i){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +const T& MyVector::operator[](unsigned i)const{ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +bool MyVector::empty()const{ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +void MyVector::clear(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +unsigned MyVector::size()const{ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +T* MyVector::begin(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +template +T* MyVector::end(){ + // TODO: replace the code below with your code for this member + MYEXCEPTION("unimplemented method"); +} + +#endif // MY_VECTOR_H diff --git a/README.md b/README.md new file mode 100755 index 0000000..d276bdc --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +See: labb 6 @ https://www.ida.liu.se/~TDDD86/info/labs.sv.shtml + diff --git a/Simulation.cpp b/Simulation.cpp new file mode 100755 index 0000000..9754751 --- /dev/null +++ b/Simulation.cpp @@ -0,0 +1,120 @@ +#include "Simulation.h" +#include +#include + +#include + + +Simulation::Simulation(): + simulationTime(0),eggPopulation(0), + juvenilePopulation(0),adultPopulation(0){ +} + + +Simulation::~Simulation(){ + assert(eventQueue.empty()); + for(unsigned i=0; i < allTheFish.size(); ++i){ + assert(! allTheFish[i]->isCaught()); + delete allTheFish[i]; + } +} + + + +void Simulation::run (){ + while (! eventQueue.empty ()){ + Event * nextEvent = eventQueue.top (); + eventQueue.pop (); + if(simulationTime < SIMULATION_HORIZON){ + simulationTime = nextEvent->eventTime; + nextEvent->processEvent(*this); + }else{ + nextEvent->withdrawEvent(); + } + delete nextEvent; + } +} + + +void Simulation::scheduleEvent (Event * newEvent){ + eventQueue.push(newEvent); +} + + +void Simulation::harvestTonnageNow(unsigned target, mt19937& generator){ +// MyVector stillAlive; + std::vector stillAlive; + for(unsigned i=0; i < allTheFish.size(); ++i){ + assert(! allTheFish[i]->isCaught()); + if (allTheFish[i]->isDead()){ + delete allTheFish[i]; + } else{ + stillAlive.push_back(allTheFish[i]); + } + } + allTheFish.clear(); + shuffle(stillAlive.begin(),stillAlive.end(),generator); + unsigned landing =0; + unsigned fish=0; + for(; fish < stillAlive.size() && landing < target; ++fish){ + if(stillAlive[fish]->catchableNow(simulationTime)){ + //fish is large enough to be caught + landing += stillAlive[fish]->getWeightOnCatch(simulationTime); + if(stillAlive[fish]->isJuvenile()){ + juvenilePopulation--; + }else if(stillAlive[fish]->isAdult()){ + adultPopulation--; + }else{ + assert(false && "should not get here"); + } + stillAlive[fish]->makeCaught(); + }else{ + allTheFish.push_back(stillAlive[fish]); + } + } + for(; fish < stillAlive.size(); ++fish){ + allTheFish.push_back(stillAlive[fish]); + } +} + +void Simulation::addFish(Fish* afish){ + allTheFish.push_back(afish); +} + +unsigned Simulation::getEggPopulation()const{ + return eggPopulation; +} + +void Simulation::incEggPopulation(unsigned c){ + eggPopulation+=c; +} + +void Simulation::decEggPopulation(unsigned c){ + eggPopulation-=c; +} + +unsigned Simulation::getJuvenilePopulation()const{ + return juvenilePopulation; +} + +void Simulation::incJuvenilePopulation(unsigned c){ + juvenilePopulation+=c; +} + +void Simulation::decJuvenilePopulation(unsigned c){ + juvenilePopulation-=c; +} + +unsigned Simulation::getAdultPopulation()const{ + return adultPopulation; +} + +void Simulation::incAdultPopulation(unsigned c){ + adultPopulation+=c; +} + +void Simulation::decAdultPopulation(unsigned c){ + adultPopulation-=c; +} + + diff --git a/Simulation.h b/Simulation.h new file mode 100755 index 0000000..7e0a414 --- /dev/null +++ b/Simulation.h @@ -0,0 +1,63 @@ +#ifndef SIMULATION_H +#define SIMULATION_H + +#include "config.h" +#include "Event.h" +#include "MyPriorityQueue.h" +#include "MyVector.h" +#include +#include +#include + +class Fish; + +class Simulation { + +public: + Simulation(); + + ~Simulation(); + + void run (); + + void scheduleEvent (Event*); + + void harvestTonnageNow(unsigned, mt19937&); + + void addFish(Fish*); + + unsigned getEggPopulation()const; + void incEggPopulation(unsigned c=1); + void decEggPopulation(unsigned c=1); + + unsigned getJuvenilePopulation()const; + void incJuvenilePopulation(unsigned c=1); + void decJuvenilePopulation(unsigned c=1); + + unsigned getAdultPopulation()const; + void incAdultPopulation(unsigned c=1); + void decAdultPopulation(unsigned c=1); + + +private: +// MyPriorityQueue eventQueue; + + std::priority_queue >, + EventComparator> eventQueue; + +// MyVector allTheFish; + std::vector allTheFish; + + + unsigned simulationTime; + + unsigned eggPopulation; + unsigned juvenilePopulation; + unsigned adultPopulation; + + + +}; + +#endif // SIMULATION_H diff --git a/answers.txt b/answers.txt new file mode 100755 index 0000000..e69de29 diff --git a/config.h b/config.h new file mode 100755 index 0000000..a900fff --- /dev/null +++ b/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_H +#define CONFIG_H + +//life expectancy +const unsigned MAX_AGE = 2000; +const unsigned STARVE_THRESHOLD=20000; + +const unsigned HATCH_TM = 40; +const unsigned AVG_MATURATION_TM = 500; + +// spawning +const unsigned MAX_AVG_EGGS_NUM = 100; +const double MIN_SPAWN_CONC = 0.05; +const unsigned SPAWN_THRESHOLD= 0.05 * STARVE_THRESHOLD; + + +// Harvesting +const unsigned HARVEST_START= 1000; +const unsigned HARVEST_PERIOD= 366; +const unsigned MIN_CATCHABLE_AGE = 550; +const unsigned MIN_KEPT_AGE = 600; +const unsigned LANDING = 70000; + +// Simulation: duration and printing +const unsigned SIMULATION_HORIZON=8000; +const unsigned PRINT_PERIOD=20; + + +#endif // CONFIG_H diff --git a/fisher.pro b/fisher.pro new file mode 100755 index 0000000..44e9c5d --- /dev/null +++ b/fisher.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES = Event.cpp Fish.cpp main.cpp Simulation.cpp + +HEADERS = $$files(*.h,true) diff --git a/main.cpp b/main.cpp new file mode 100755 index 0000000..6d5e98b --- /dev/null +++ b/main.cpp @@ -0,0 +1,77 @@ + +#include "Event.h" +#include "Fish.h" +#include "Simulation.h" + +#include +#include +#include +#include +#include + + +using namespace std; + + +void show(); + +int main() +{ + ofstream file("output.dat"); + + random_device rd; + mt19937 generator(rd()); + + + Simulation sim; + sim.scheduleEvent(new printEvent (0,file)); + for(unsigned i=0; i < 100; ++i){ + Event* e = new hatchEvent(0,generator); + sim.scheduleEvent(e); + } + sim.incEggPopulation(100); + sim.scheduleEvent(new harvestEvent(HARVEST_START,generator)); + auto comp_start_time = chrono::high_resolution_clock::now(); + sim.run(); + auto comp_end_time = chrono::high_resolution_clock::now(); + std::cout << "simulation took: " + << chrono::duration_cast(comp_end_time - comp_start_time).count() + << " seconds." + << std::endl; + file.close(); + + show(); + + return 0; +} + +void show(){ + ofstream driver; + driver.open("output.driver", ofstream::out); + driver << "set terminal wxt size 410,250 enhanced font 'Verdana,9' persist\n" + << "set style line 11 lc rgb '#808080' lt 1\n" + << "set border 3 back ls 11\n" + << "set tics nomirror \n" + << "set style line 12 lc rgb '#808080' lt 0 lw 1\n" + << "set grid back ls 12\n" + << "set style line 1 lc rgb '#000000' pt 0 ps 1 lt 1 lw 1 # --- red\n" + << "set style line 2 lc rgb '#5e9c36' pt 0 ps 1 lt 1 lw 1 # --- green\n" + << "set style line 3 lc rgb '#0000ff' pt 0 ps 1 lt 1 lw 1 # --- blue\n" + << "set style line 4 lc rgb '#99004c' pt 0 ps 1 lt 1 lw 1 # --- purple\n" + << "set key top left\n" + << "set xlabel 'time in days'\n" + << "set ylabel 'population'\n" + << "set xrange [0:" << SIMULATION_HORIZON <<"]\n" + << "set yrange [0:" << int(STARVE_THRESHOLD * 1.3) << "]\n" + << "plot 'output.dat' u 1:3 t 'juvenile' w lp ls 2, \\\n" + << " 'output.dat' u 1:4 t 'adult' w lp ls 3"; + driver.close(); + +#ifdef WIN32 + const string exe = "C:\\Progra~1\\gnuplot\\bin\\gnuplot.exe"; +#else + const string exe = "gnuplot"; +#endif + const string cmd = exe + " " + "output.driver"; + system(cmd.c_str()); +} diff --git a/test-harness-myprio.cpp b/test-harness-myprio.cpp new file mode 100755 index 0000000..3679ea4 --- /dev/null +++ b/test-harness-myprio.cpp @@ -0,0 +1,322 @@ +/************************************************* + * File: test-harness-myprio.cpp + * + * File containing several test cases that can be + * used to verify the correctness of the MyPriorityQueue + * implementation. You should make sure to do your + * own testing in addition to ensuring that the test + * cases here pass. + */ +#include +#include +#include +#include +#include +#include +#include +#include "MyPriorityQueue.h" +using namespace std; + +/* These flags control which tests will be run. Initially, only the + * basic test will be executed. As you complete more and more parts + * of the implementation, you will want to turn more and more of these + * flags on. + */ +#define BasicMyPriorityQueueTestEnabled 1 +#define ModerateMyPriorityQueueTestEnabled 1 + +#define BasicCopyTestEnabled 0 +#define ModerateCopyTestEnabled 0 + + +/* Utility function that pauses until the user hits ENTER. */ +void pressEnterToContinue() { + /* Use getline to stall until receiving input. */ + string line; + getline(cin, line); +} + +/* This function is what the test suite uses to ensure that the MyPriorityQueue works + * correctly. It takes as parameters an expression and description, along + * with a file and line number, then checks whether the condition is true. + * If so, it prints that the test passed. Otherwise, it reports that the + * test fails and points the caller to the proper file and line. + */ +void doCheckCondition(bool expr, const string& rationale, const string& file, int line) { + /* It worked! Congrats. */ + if (expr) { + cout << "PASS: " << rationale << endl; + return; + } + + /* Uh oh! The test failed! */ + cout << "FAIL: " << rationale << endl; + cout << " Error at " << file << ", line " << line << endl; + cout << " (ENTER to continue)" << endl; + + /* Pause so that the test fail stands out. */ + pressEnterToContinue(); +} + +/* Reports that an unexpected error occurred that caused a test to fail. */ +void failTest(const exception& e) { + cerr << "TEST FAILED: Unexpected exception: " << e.what() << endl; + pressEnterToContinue(); +} + +/* This macro takes in an expression and a string, then invokes + * doCheckCondition passing in the arguments along with the file + * and line number on which the macro was called. This makes it + * easier to track down the source of bugs if a test case should + * fail. + */ +#define checkCondition(expr, rationale) doCheckCondition(expr, rationale, __FILE__, __LINE__) + +/* Utility function to delimit the start and end of test cases. */ +void printBanner(const string& header) { + cout << "\nBeginning test: " << header << endl; + cout << setw(40) << setfill('-') << "" << setfill(' ') << endl; +} + +/* Utility function to signal that a test isn't begin run. */ +void testDisabled(const string& header) { + cout << "== Test " << header << " NOT RUN: press ENTER to continue ==" << endl; + + /* Pause for the user to hit enter. */ + pressEnterToContinue(); +} + +/* Utility function to signal the end of a test. */ +void endTest() { + cout << "== end of test: press ENTER to continue ==" << endl; + pressEnterToContinue(); +} + +struct comp{ + bool operator()(int l, int r) const{ + return l > r; + } +}; + +/* Basic test: Can we build an empty priority queue? */ +void basicMyPriorityQueueTest() try { +#if BasicMyPriorityQueueTestEnabled + printBanner("Basic MyPriorityQueue Test"); + + /* Construct the MyPriorityQueue. */ + MyPriorityQueue prio; + checkCondition(true, "MyPriorityQueue construction completed."); + + /* Check basic properties of the MyPriorityQueue. */ + checkCondition(prio.size() == 0, "New prio queue has no elements."); + checkCondition(prio.empty(), "prio queue is empty."); + + endTest(); +#else + testDisabled("BasicMyPriorityQueueTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* A trickier test that involves a data set . + */ +void moderateMyPriorityQueueTest() try { +#if ModerateMyPriorityQueueTestEnabled + printBanner("Moderate MyPriorityQueue Test"); + + MyPriorityQueue prio; + for (size_t i = 0; i < 8; ++i) + prio.push(i); + for (size_t i = 0; i < 8; ++i) + prio.push(7-i); + + /* Check that basic properties hold. */ + checkCondition(prio.size() == 16, "New prio has the right number of elements."); + checkCondition(!prio.empty(), "prio queue is nonempty."); + + /* Make sure that the values of these points are correct. */ + for (size_t i = 0; i < 16; ++i){ + checkCondition(prio.size() == 16-i, "prio has the right number of elements."); + int current = prio.top(); + checkCondition(current == i/2, "top prio element is correct."); + prio.pop(); + } + + checkCondition(prio.empty(), "prio is empty."); + + + endTest(); +#else + testDisabled("moderateMyPriorityQueueTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + + + +/* Tests basic behavior of the copy constructor and assignment operator. */ +void basicCopyTest() try { +#if BasicCopyTestEnabled + printBanner("Basic Copy Test"); + + /* For simplicity, we'll use one-dimensional MyPriorityQueues in this step. */ + MyPriorityQueue one; + for (size_t i = 0; i < 10; ++i) + one.push(i); + for (size_t i = 0; i < 10; ++i) + one.push(9 - i); + + + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the copy constructor. + */ + MyPriorityQueue clone = one; + + /* Basic checks. */ + checkCondition(one.size() == clone.size(), "clone has the same number of elements as original one."); + checkCondition(one.empty() == clone.empty(), "clone and one agree on emptiness."); + + /* Check that everything in one is there. */ + for (size_t i = 0; i < 20; ++i){ + checkCondition(clone.size() == 20-i, "clone has the right number of elements."); + int current = clone.top(); + checkCondition(current == i/2, "top clone element is correct."); + clone.pop(); + } + + checkCondition(clone.empty(), "clone is empty."); + + } + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the assignment operator. + */ + MyPriorityQueue clone; + clone = one; + + /* Check that everything in one is there. */ + for (size_t i = 0; i < 20; ++i){ + checkCondition(clone.size() == 20-i, "clone has the right number of elements."); + int current = clone.top(); + checkCondition(current == i/2, "top clone element is correct."); + clone.pop(); + } + + checkCondition(clone.empty(), "clone is empty."); + + + } + + /* Check that everything in one is there. */ + for (size_t i = 0; i < 20; ++i){ + checkCondition(one.size() == 20-i, "After clone destructor, one has the right number of elements."); + int current = one.top(); + checkCondition(current == i/2, "After clone destructor, top one element is correct."); + one.pop(); + } + + checkCondition(one.empty(), "one is empty."); + + + endTest(); +#else + testDisabled("BasicCopyTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* A more merciless test of copy behavior.. */ +void moderateCopyTest() try { +#if BasicCopyTestEnabled + printBanner("Moderate Copy Test"); + + MyPriorityQueue one; + for (size_t i = 0; i < 10; ++i) + one.push(i); + for (size_t i = 0; i < 10; ++i) + one.push(9 - i); + + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the copy constructor. + */ + MyPriorityQueue clone = one; + + for (size_t i = 0; i < 10; ++i) + clone.push(2*(10+i)); + + /* Confirm that they didn't appear in one. */ + checkCondition(one.size() == 20, "Adding to clone does not change original one size."); + } + + /* Check the integrity of the original out here as well to see that the destructor didn't hose things. */ + checkCondition(one.size() == 20, "After destructor, one has original size."); + + + + { + /*Create a clone of one and confirm that everything copied correctly. + * This uses the assignment operator.*/ + MyPriorityQueue clone; + clone = one; + + /* Do awful, awful things to the copy.*/ + clone = clone = (clone = clone); + (clone = one) = clone; + clone = clone = clone = clone = clone; + + /* Check that everything in one is there.*/ + for (size_t i = 0; i < 20; ++i){ + checkCondition(clone.size() == 20-i, "clone has the right number of elements."); + int current = clone.top(); + checkCondition(current == i/2, "top clone element is correct."); + clone.pop(); + } + + checkCondition(clone.empty(), "clone is empty."); + + } + +/* Check that everything in one is there.*/ + for (size_t i = 0; i < 20; ++i){ + checkCondition(one.size() == 20-i, "one has the right number of elements."); + int current = one.top(); + checkCondition(current == i/2, "top one element is correct."); + one.pop(); + } + + checkCondition(one.empty(), "one is empty."); + + + endTest(); +#else + testDisabled("ModerateCopyTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* Main entry point simply runs all the tests. Note that these functions might be no-ops + * if they are disabled by the configuration settings at the top of the program. + */ +int main() { + basicMyPriorityQueueTest(); + moderateMyPriorityQueueTest(); + basicCopyTest(); + moderateCopyTest(); + +#if (BasicMyPriorityQueueTestEnabled && \ + ModerateMyPriorityQueueTestEnabled && \ + BasicCopyTestEnabled && \ + ModerateCopyTestEnabled) + cout << "All tests completed! If they passed, you should be good to go!" << endl << endl; +#else + cout << "Not all tests were run. Enable the rest of the tests, then run again." << endl << endl; +#endif + + pressEnterToContinue(); +} diff --git a/test-harness-myvector.cpp b/test-harness-myvector.cpp new file mode 100755 index 0000000..d392e33 --- /dev/null +++ b/test-harness-myvector.cpp @@ -0,0 +1,422 @@ +/************************************************* + * File: test-harness-myvector.cpp + * + * File containing several test cases that can be + * used to verify the correctness of the MyVector + * implementation. You should make sure to do your + * own testing in addition to ensuring that the test + * cases here pass. + */ +#include +#include +#include +#include +#include +#include +#include +#include "MyVector.h" +using namespace std; + +/* These flags control which tests will be run. Initially, only the + * basic test will be executed. As you complete more and more parts + * of the implementation, you will want to turn more and more of these + * flags on. + */ +#define BasicMyVectorTestEnabled 1 +#define ModerateMyVectorTestEnabled 1 +#define HarderMyVectorTestEnabled 1 +#define MutatingMyVectorTestEnabled 1 + +#define ConstMyVectorTestEnabled 0 +#define BasicCopyTestEnabled 0 +#define ModerateCopyTestEnabled 0 + + +/* Utility function that pauses until the user hits ENTER. */ +void pressEnterToContinue() { + /* Use getline to stall until receiving input. */ + string line; + getline(cin, line); +} + +/* This function is what the test suite uses to ensure that the MyVector works + * correctly. It takes as parameters an expression and description, along + * with a file and line number, then checks whether the condition is true. + * If so, it prints that the test passed. Otherwise, it reports that the + * test fails and points the caller to the proper file and line. + */ +void doCheckCondition(bool expr, const string& rationale, const string& file, int line) { + /* It worked! Congrats. */ + if (expr) { + cout << "PASS: " << rationale << endl; + return; + } + + /* Uh oh! The test failed! */ + cout << "FAIL: " << rationale << endl; + cout << " Error at " << file << ", line " << line << endl; + cout << " (ENTER to continue)" << endl; + + /* Pause so that the test fail stands out. */ + pressEnterToContinue(); +} + +/* Reports that an unexpected error occurred that caused a test to fail. */ +void failTest(const exception& e) { + cerr << "TEST FAILED: Unexpected exception: " << e.what() << endl; + pressEnterToContinue(); +} + +/* This macro takes in an expression and a string, then invokes + * doCheckCondition passing in the arguments along with the file + * and line number on which the macro was called. This makes it + * easier to track down the source of bugs if a test case should + * fail. + */ +#define checkCondition(expr, rationale) doCheckCondition(expr, rationale, __FILE__, __LINE__) + +/* Utility function to delimit the start and end of test cases. */ +void printBanner(const string& header) { + cout << "\nBeginning test: " << header << endl; + cout << setw(40) << setfill('-') << "" << setfill(' ') << endl; +} + +/* Utility function to signal that a test isn't begin run. */ +void testDisabled(const string& header) { + cout << "== Test " << header << " NOT RUN: press ENTER to continue ==" << endl; + + /* Pause for the user to hit enter. */ + pressEnterToContinue(); +} + +/* Utility function to signal the end of a test. */ +void endTest() { + cout << "== end of test: press ENTER to continue ==" << endl; + pressEnterToContinue(); +} + +/* Basic test: Can we build an empty vector and clear it? */ +void basicMyVectorTest() try { +#if BasicMyVectorTestEnabled + printBanner("Basic MyVector Test"); + + /* Construct the MyVector. */ + MyVector vect; + checkCondition(true, "New MyVector construction completed."); + + /* Check basic properties of the MyVector. */ + checkCondition(vect.size() == 0, "vector has no elements."); + checkCondition(vect.empty(), "vector is empty."); + + /* Clear the MyVctor and check basic properties again. */ + vect.clear(); + checkCondition(vect.size() == 0, "vector has no elements."); + checkCondition(vect.empty(), "vector is empty."); + + endTest(); +#else + testDisabled("BasicMyVectorTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* A trickier test that involves a data set and iterating through the vector with pointers. + */ +void moderateMyVectorTest() try { +#if ModerateMyVectorTestEnabled + printBanner("Moderate MyVector Test"); + + /* Build a palindrome. */ + MyVector vect; + for (size_t i = 0; i < 8; ++i) + vect.push_back(i); + for (size_t i = 0; i < 8; ++i) + vect.push_back(7-i); + + /* Check that basic properties hold. */ + checkCondition(vect.size() == 16, "New vector has the right number of elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + /* Make sure that the values of these points are correct. */ + int* fwd = vect.begin(); + int* bwd = vect.end(); + while(fwd != bwd){ + --bwd; + checkCondition(*fwd == *bwd, "vector has correct values."); + ++fwd; + } + + for (size_t i = 0; i < 8; ++i) + vect.pop_back(); + + /* Check basic properties again. */ + checkCondition(vect.size() == 8, "vector has 8 elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + + for (size_t i = 0; i < 8; ++i) + vect.pop_back(); + + /* Check basic properties again. */ + checkCondition(vect.size() == 0, "vector has no elements."); + checkCondition(vect.empty(), "vector is empty."); + + endTest(); +#else + testDisabled("moderateMyVectorTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* This test still uses just the basic functionality, but uses larger + * data set and index based access + */ +void harderMyVectorTest() try { +#if HarderMyVectorTestEnabled + printBanner("Harder MyVector Test"); + + MyVector vect; + for (size_t i = 0; i < 4096; ++i) + vect.push_back(i); + + /* Check that basic properties hold. */ + checkCondition(vect.size() == 4096, "New vector has 4096 elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + for (size_t i = 0; i < 2048; ++i) + vect.pop_back(); + + /* Check basic properties again. */ + checkCondition(vect.size() == 2048, "vector has now 2048 elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + + for (size_t i = 0; i < 2048; ++i) + vect.push_back(-i); + + /* Check that basic properties hold. */ + checkCondition(vect.size() == 4096, "vector has now 4096 elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + /* Clear the MyVctor and check basic properties again. */ + vect.clear(); + checkCondition(vect.size() == 0, "vector has no elements."); + checkCondition(vect.empty(), "vector is empty."); + + for (size_t i = 0; i < 4096; ++i) + vect.push_back(i); + + /* Check that basic properties hold. */ + checkCondition(vect.size() == 4096, "vector has again 4096 elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + + endTest(); +#else + testDisabled("HarderMyVectorTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + + +/* This test actively mutates the elements of the MyVector using + * operator[]. If you are failing this test, check to make sure + * that your implementation of operator[] correctly allows for + * mutation. + */ +void mutatingMyVectorTest() try { +#if MutatingMyVectorTestEnabled + printBanner("Mutating MyVector Test"); + + MyVector vect; + for (size_t i = 0; i < 16; ++i) + vect.push_back(i); + + /* Check that basic properties hold. */ + checkCondition(vect.size() == 16, "New vector has 16 elements."); + checkCondition(!vect.empty(), "vector is nonempty."); + + for (size_t i = 0; i < 16; ++i) + vect[i] = vect[i] + 1; + + for (size_t i = 0; i < 16; ++i) + checkCondition(vect[i] == i + 1, "updated vector has correct values."); + + endTest(); +#else + testDisabled("mutatingMyVectorTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + + +/* A basic test that creates a const MyVector and a non-const MyVector to ensure + * the class still compiles properly. It also tests the const version of + * [] is working correctly on the basic MyVector tests. + */ +void constMyVectorTest() try { +#if ConstMyVectorTestEnabled + printBanner("Const MyVector Test"); + + MyVector vect; + for (size_t i = 0; i < 4; ++i) + vect.push_back(i); + + /* Check that the code compiles for the non-const version. */ + vect.size(); + vect.empty(); + vect[3]=10; + + const MyVector& const_vect = vect; + + /* Check that the code compiles for the const version. */ + const_vect.size(); + const_vect.empty(); + const_vect[3]; + + checkCondition(true, "Const code compiles."); + + /* Run the basic vect tests using a const vect. */ + checkCondition(const_vect[0]==0, "const_vect has element zero."); + checkCondition(const_vect[1]==1, "const_vect has element one."); + checkCondition(const_vect[2]==2, "const_vect has element two."); + checkCondition(const_vect[3]==10, "const_vect has element ten."); + + endTest(); +#else + testDisabled("ConstMyVectorTest"); +#endif +} catch (const exception& e) { + cout << "Note: vect lookup failed, but const code compiles." << endl; + failTest(e); +} + + +/* Tests basic behavior of the copy constructor and assignment operator. */ +void basicCopyTest() try { +#if BasicCopyTestEnabled + printBanner("Basic Copy Test"); + + MyVector one; + for (size_t i = 0; i < 10; ++i) + one.push_back(2*i); + + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the copy constructor. + */ + MyVector clone = one; + + /* Basic checks. */ + checkCondition(one.size() == clone.size(), "clone has the same number of elements as one."); + checkCondition(one.empty() == clone.empty(), "clone and one agree on emptiness."); + + /* Check that everything in one is there. */ + for (size_t i = 0; i < 10; ++i) + checkCondition(clone[i]==2*i, "Element from one present in clone."); + + } + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the assignment operator. + */ + MyVector clone; + clone = one; + + /* Basic checks. */ + checkCondition(one.size() == clone.size(), "clone has the same number of elements as the one."); + checkCondition(one.empty() == clone.empty(), "clone and one agree on emptiness."); + + /* Check that everything in one is there. */ + for (size_t i = 0; i < 10; ++i) + checkCondition(clone[i]==2*i, "Element from one present in clone."); + } + + endTest(); +#else + testDisabled("BasicCopyTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* A more merciless test of copy behavior.. */ +void moderateCopyTest() try { +#if BasicCopyTestEnabled + printBanner("Moderate Copy Test"); + + MyVector one; + for (size_t i = 0; i < 10; ++i) + one.push_back(2*i); + + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the copy constructor. + */ + MyVector clone = one; + + /* Add odd numbers to the clone. */ + for (size_t i = 0; i < 10; ++i) + clone.push_back(2*(10+i)); + + checkCondition(one.size() == 10, "Adding to clone did not change one size."); + } + + /* Check the integrity of the original out here as well to see that the destructor didn't hose things. */ + checkCondition(one.size() == 10, "After clone destructor, one has original size."); + for (size_t i = 0; i < 10; ++i) { + checkCondition(one[i]==2*i, "After clone destructor, one contains same as original."); + } + + { + /* Create a clone of one and confirm that everything copied correctly. + * This uses the assignment operator. + */ + MyVector clone; + clone = one; + + /* Do awful, awful things to the copy. */ + clone = clone = (clone = clone); + (clone = one) = clone; + clone = clone = clone = clone = clone; + } + + endTest(); +#else + testDisabled("ModerateCopyTest"); +#endif +} catch (const exception& e) { + failTest(e); +} + +/* Main entry point simply runs all the tests. Note that these functions might be no-ops + * if they are disabled by the configuration settings at the top of the program. + */ +int main() { + basicMyVectorTest(); + moderateMyVectorTest(); + harderMyVectorTest(); + mutatingMyVectorTest(); + constMyVectorTest(); + + basicCopyTest(); + moderateCopyTest(); + +#if (BasicMyVectorTestEnabled && \ + ModerateMyVectorTestEnabled && \ + HarderMyVectorTestEnabled && \ + MutatingMyVectorTestEnabled && \ + ConstMyVectorTestEnabled && \ + BasicCopyTestEnabled && \ + ModerateCopyTestEnabled) + cout << "All tests completed! If they passed, you should be good to go!" << endl << endl; +#else + cout << "Not all tests were run. Enable the rest of the tests, then run again." << endl << endl; +#endif + + pressEnterToContinue(); +}