#include <iostream>
#include <cstdlib>
#include <vector>
#include <ctime>
#include <random>
#define TRUE 1
#define FALSE 0
using namespace std;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine e(seed);
class Coordinate
{
public:
Coordinate( Coordinate *);
Coordinate( double, double );
Coordinate(){x=0;y=0;};
void set(double, double);
void set(Coordinate *);
double getx(){return x;};
double gety(){return y;};
double distancefrom(Coordinate*);
double distancefrom(double,double);
friend ostream &operator << (ostream &out, const Coordinate &c);
//friend istream &operator >> (istream &input, Coordinate &c );
bool operator==(const Coordinate& c) const{return ( (c.x == x) && (c.y == y)) ;}
~Coordinate();
private:
double x;
double y;
};
ostream & operator << (ostream &out, const Coordinate &c)
{
out << "(" << c.x << "," << c.y << ")";
return out;
}
//istream & operator >> (istream &input, Coordinate &c)
//{
// input >> c.x >> c.y;
// return input;
//}
Coordinate::~Coordinate()
{
#ifdef DEBUG
cerr << "Deleteing coordinate " << *this << endl;
#endif
}
void Coordinate::set( Coordinate * c )
{
x=c->getx();
y=c->gety();
return;
}
Coordinate::Coordinate( double x, double y )
{
#ifdef DEBUG
cerr << "[ Coordinate Constructor(" << x << "," << y << ") ]" << endl;
#endif
this->x = x;
this->y = y;
return;
}
Coordinate::Coordinate( Coordinate * c )
{
#ifdef DEBUG
cerr << "[ Coordinate Constructor(Coordinate * c) ]" << endl;
#endif
this->x = c->getx();
this->y = c->gety();
return;
}
void Coordinate::set(double x, double y)
{
#ifdef DEBUG
cerr << "[ Coordinate::set(double,double) ]" << endl;
#endif
this->x = x;
this->y = y;
return;
}
double Coordinate::distancefrom(Coordinate* c)
{
#ifdef DEBUG
cerr << "[calculate distance from " << *c << " to " << *this << "]" << endl;
#endif
double x1 = c->getx();
double y1 = c->gety();
return sqrt( ( x1 - this->x )*( x1 - this->x ) + ( y1 - this->y)*( y1 - this->y) );
}
double Coordinate::distancefrom(double x1, double y1)
{
#ifdef DEBUG
cerr << "[calculate distance from (" << x1 << "," << y1 << ") to " << *this << "]" << endl;
#endif
return sqrt( ( x1 - this->x )*( x1 - this->x ) + ( y1 - this->y)*( y1 - this->y) );
}
class NeuralNode
{
public:
NeuralNode(NeuralNode*);
NeuralNode(double,double);
NeuralNode(Coordinate*);
~NeuralNode();
void addLink(NeuralNode*);
void addOneWayLink(NeuralNode*);
vector<NeuralNode*> getLinks(){ return pLinks; };
void removeLink(NeuralNode*);
int howManyLinks(){ return pLinks.size(); };
string getName(){ return name; };
void setName( string s ){ name = s;};
Coordinate * getCoordinate(){ return pCoordinate; };
void setCoordinate(double x, double y);
void setCoordinate( Coordinate * c );
friend ostream &operator << (ostream &out, const NeuralNode &n);
NeuralNode * getParent(){ return pParent; };
void setParent( NeuralNode * N ){ pParent = N; };
void shuffle(){ std::shuffle( pLinks.begin(), pLinks.end(), e ); };
private:
NeuralNode(void);
vector<NeuralNode*> pLinks;
string name;
Coordinate * pCoordinate;
NeuralNode * pParent;
};
NeuralNode::~NeuralNode()
{
#ifdef DEBUG
cerr << "Deleting Node: " << *pCoordinate << endl;
#endif
delete pCoordinate;
}
void NeuralNode::removeLink( NeuralNode* N )
{
Coordinate * tmpCoord = N->getCoordinate();
for( int i=0; i<pLinks.size(); i++ )
{
if( *tmpCoord == *pLinks[i]->getCoordinate() )
{
#ifdef DEBUG
cerr << "removing " << *pLinks[i] << " from " << name << endl;
#endif
pLinks.erase(pLinks.begin()+i);
}
}
}
void NeuralNode::addLink( NeuralNode* N )
{
bool okaytoadd = TRUE;
// if link already exists then don't add it
for( int i=0; i<pLinks.size(); i++ )
{
if( pLinks[i]->getCoordinate() == N->getCoordinate() )
{
cerr << "not okay to add link from " << *N << " to " << *pLinks[i] << " because one already exists" << endl;
okaytoadd = FALSE;
}
}
if( *N->getCoordinate() == *pCoordinate )
{
cerr << "cannot link to one's self!" << endl;
}
else
{
if( okaytoadd )
{
pLinks.push_back(N);
N->addOneWayLink(this);
}
}
return;
}
void NeuralNode::addOneWayLink( NeuralNode* N )
{
bool okaytoadd = TRUE;
// if link already exists then don't add it
for( int i=0; i<pLinks.size(); i++ )
{
if( pLinks[i]->getCoordinate() == N->getCoordinate() )
{
cerr << "not okay to add this link because one already exists" << endl;
okaytoadd = FALSE;
}
}
if( *N->getCoordinate() == *pCoordinate )
{
cerr << "cannot link to one's self!" << endl;
}
else
{
if( okaytoadd ) pLinks.push_back(N);
}
return;
}
NeuralNode::NeuralNode(double x, double y)
{
pCoordinate=new Coordinate(x,y);
pParent=NULL;
return;
}
NeuralNode::NeuralNode(Coordinate * c)
{
// make a copy of c -- this allows c to be deleted w/o modifying Neural Node
if(pCoordinate != NULL) delete pCoordinate;
pCoordinate=new Coordinate( c->getx(), c->gety() );
pParent=NULL;
return;
}
NeuralNode::NeuralNode()
{
pCoordinate=new Coordinate( 0, 0 );
pParent=NULL;
return;
}
NeuralNode::NeuralNode(NeuralNode* N)
{
if( pCoordinate == NULL )
{
pCoordinate = new Coordinate( N->getCoordinate() );
}
else
{
pCoordinate->set( N->getCoordinate() );
}
name = "";
pParent = N->getParent();
return;
}
void NeuralNode::setCoordinate( Coordinate * c )
{
if( pCoordinate != NULL ) delete pCoordinate;
pCoordinate = new Coordinate( c->getx(), c->gety() );
// pCoordinate->setname( c->getName() );
return;
}
ostream & operator << (ostream &out, const NeuralNode &c)
{
out << *c.pCoordinate << " [ ";
for( int i=0; i<c.pLinks.size(); i++ )
{
out << *c.pLinks[i]->getCoordinate();
}
out << " ] (" << c.name << ")";
return out;
}
class Path
{
public:
Path(){};
~Path(){};
double getLength(){ return length; };
void setLength( double l ){ length=l; };
vector<NeuralNode*> getPath(){ return pPath; };
void addNode( NeuralNode* N){pPath.push_back(N);};
void clear(){ pPath.clear();};
int size(){ return pPath.size(); };
void reverse(){ std::reverse( pPath.begin(), pPath.end());};
private:
vector<NeuralNode*> pPath;
double length;
};
vector<NeuralNode*> breadcrumbs;
vector<NeuralNode*> viewableworld;
vector<NeuralNode*> path;
Path * mypath;
double path_length=0;
int MODE=0;
void explore( NeuralNode * N)
{
#ifdef DEBUG
cerr << "exploring: " << *N << " which has " << N->howManyLinks() << " links" << endl;
#endif
breadcrumbs.push_back( N );
if( viewableworld.size() == 0 ) viewableworld.push_back( N );
// Explore Links from 0 to how Many There Are
// *********************
if( MODE == 0 )
{
for( int i=0; i< N->howManyLinks(); i++ )
{
bool alreadyexplored=false;
// check to make sure that N->getLinks[i] is not in breadcrumbs yet.
for( int j=0; j<breadcrumbs.size(); j++ )
{
if( *breadcrumbs[j]->getCoordinate() == *N->getLinks()[i]->getCoordinate() )
{
#ifdef DEBUG
cerr << "found " << *N->getLinks()[i]->getCoordinate() << " in breadcrumbs - don't re-explore" << endl;
#endif
alreadyexplored=true;
}
}
if( !alreadyexplored )
{
// add the new one to the viewable world list
N->getLinks()[i]->setParent(N);
//cerr << endl << *N << endl << endl;
viewableworld.push_back( N->getLinks()[i] );
explore( N->getLinks()[i] );
}
}
}
else if (MODE==1 )
//************************** EXPLORE MODE = 1;
{
for( int i=N->howManyLinks()-1; i>=0; i-- )
{
bool alreadyexplored=false;
// check to make sure that N->getLinks[i] is not in breadcrumbs yet.
for( int j=0; j<breadcrumbs.size(); j++ )
{
if( *breadcrumbs[j]->getCoordinate() == *N->getLinks()[i]->getCoordinate() )
{
#ifdef DEBUG
cerr << "found " << *N->getLinks()[i]->getCoordinate() << " in breadcrumbs - don't re-explore" << endl;
#endif
alreadyexplored=true;
}
}
if( !alreadyexplored )
{
// add the new one to the viewable world list
N->getLinks()[i]->setParent(N);
//cerr << endl << *N << endl << endl;
viewableworld.push_back( N->getLinks()[i] );
explore( N->getLinks()[i]);
}
}
}
// ************************************
else if ( MODE==2 )
//************************** EXPLORE MODE = 2;
{
N->shuffle();
for( int i=0; i< N->howManyLinks(); i++ )
{
bool alreadyexplored=false;
// check to make sure that N->getLinks[i] is not in breadcrumbs yet.
for( int j=0; j<breadcrumbs.size(); j++ )
{
if( *breadcrumbs[j]->getCoordinate() == *N->getLinks()[i]->getCoordinate() )
{
#ifdef DEBUG
cerr << "found " << *N->getLinks()[i]->getCoordinate() << " in breadcrumbs - don't re-explore" << endl;
#endif
alreadyexplored=true;
}
}
if( !alreadyexplored )
{
// add the new one to the viewable world list
N->getLinks()[i]->setParent(N);
viewableworld.push_back( N->getLinks()[i] );
explore( N->getLinks()[i] );
}
}
}
// ************************************
return;
}
bool reachable( NeuralNode * StartNode, NeuralNode * GoalNode )
{
#ifdef DEBUG
cerr << "looking for: " << *GoalNode << " from " << *StartNode << endl;
#endif
bool retVal = false;
explore( StartNode);
for( int i=0; i<viewableworld.size(); i++ )
{
if(*viewableworld[i]->getCoordinate() == *GoalNode->getCoordinate())
{
retVal = TRUE;
}
}
return retVal;
}
Path * getPath( NeuralNode * start, NeuralNode * goal)
{
Path * retVal = new Path();
retVal->clear();
path_length=0;
breadcrumbs.clear();
path.clear();
viewableworld.clear();
if( reachable( start, goal ) )
{
NeuralNode * n = goal;
Coordinate * a = n->getCoordinate();
while( n != start )
{
path.push_back( n );
n = n->getParent();
Coordinate * b = n->getCoordinate();
path_length+=a->distancefrom(b);
a=b;
}
path.push_back( n );
}
reverse( path.begin(), path.end() );
for( int i=0; i<path.size(); i++ )
{
retVal->addNode( path[i] );
}
retVal->setLength( path_length);
return retVal;
}
void dumpPath( Path p )
{
vector<NeuralNode *> myPath = p.getPath();
if( p.size() == 0 ) cerr << "NO ROUTE" << endl << endl;
for( int i=0; i< p.size()-1; i++ )
{
cerr << /* *myPath[i]->getCoordinate() << */ "(" << myPath[i]->getName() << ")->";
}
cerr << /* *myPath[p.size()-1]->getCoordinate() << */ "(" << myPath[p.size()-1]->getName() << ")" << endl;
}
// -------------------------------------------------------
int main()
{
mypath=new Path();
vector<NeuralNode*> nodes;
// Map of Prospect Hill Street Intersections and bends
// Beverly, Mass.
nodes.push_back( new NeuralNode(0,0));
nodes.push_back( new NeuralNode(58,19));
nodes.push_back( new NeuralNode(95,48));
nodes.push_back( new NeuralNode(126,76));
nodes.push_back( new NeuralNode(159,106));
nodes.push_back( new NeuralNode(166,3));
nodes.push_back( new NeuralNode(195,34));
nodes.push_back( new NeuralNode(213,69));
nodes.push_back( new NeuralNode(228,101));
nodes.push_back( new NeuralNode(185,124));
nodes.push_back( new NeuralNode(214,124));
nodes.push_back( new NeuralNode(60,105));
nodes.push_back( new NeuralNode(175,154));
nodes.push_back( new NeuralNode(59,145));
nodes.push_back( new NeuralNode(22,163));
nodes.push_back( new NeuralNode(31,202));
nodes.push_back( new NeuralNode(25,254));
nodes.push_back( new NeuralNode(75,269));
nodes.push_back( new NeuralNode(115,288));
nodes.push_back( new NeuralNode(162,182));
nodes.push_back( new NeuralNode(141,220));
nodes.push_back( new NeuralNode(164,226));
nodes.push_back( new NeuralNode(181,281));
nodes.push_back( new NeuralNode(152,310));
nodes.push_back( new NeuralNode(189,216));
nodes.push_back( new NeuralNode(236,281));
nodes.push_back( new NeuralNode(210,195));
nodes.push_back( new NeuralNode(247,261));
nodes.push_back( new NeuralNode(215,167));
nodes.push_back( new NeuralNode(286,173));
nodes.push_back( new NeuralNode(297,214));
nodes.push_back( new NeuralNode(280,236));
nodes.push_back( new NeuralNode(268,303));
nodes.push_back( new NeuralNode(194,311));
nodes.push_back( new NeuralNode(176,350));
nodes.push_back( new NeuralNode(105,368));
nodes.push_back( new NeuralNode(5,410));
nodes.push_back( new NeuralNode(41,428));
nodes.push_back( new NeuralNode(76,448));
nodes.push_back( new NeuralNode(153,484));
nodes.push_back( new NeuralNode(100,411));
nodes.push_back( new NeuralNode(182,455));
nodes.push_back( new NeuralNode(142,381));
nodes.push_back( new NeuralNode(190,392));
nodes.push_back( new NeuralNode(203,432));
nodes.push_back( new NeuralNode(218,409));
nodes.push_back( new NeuralNode(187,140));
// *******
nodes[1]->addLink( nodes[2]);
nodes[1]->addLink( nodes[11]);
nodes[2]->addLink( nodes[3]);
nodes[3]->addLink( nodes[4]);
nodes[4]->addLink( nodes[7]);
nodes[5]->addLink( nodes[6]);
nodes[8]->addLink( nodes[10]);
nodes[9]->addLink( nodes[10]);
nodes[10]->addLink( nodes[28]);
nodes[11]->addLink( nodes[12]);
nodes[12]->addLink( nodes[19]);
nodes[13]->addLink( nodes[14]);
nodes[14]->addLink( nodes[15]);
nodes[15]->addLink( nodes[16]);
nodes[16]->addLink( nodes[17]);
nodes[17]->addLink( nodes[18]);
nodes[18]->addLink( nodes[20]);
nodes[21]->addLink( nodes[22]);
nodes[22]->addLink( nodes[23]);
nodes[25]->addLink( nodes[27]);
nodes[26]->addLink( nodes[28]);
nodes[28]->addLink( nodes[31]);
nodes[30]->addLink( nodes[31]);
nodes[32]->addLink( nodes[45]);
nodes[33]->addLink( nodes[34]);
nodes[35]->addLink( nodes[42]);
nodes[36]->addLink( nodes[37]);
nodes[38]->addLink( nodes[39]);
nodes[39]->addLink( nodes[41]);
nodes[43]->addLink( nodes[45]);
nodes[2]->addLink( nodes[5]);
nodes[3]->addLink( nodes[6]);
nodes[4]->addLink( nodes[9]);
nodes[6]->addLink( nodes[7]);
nodes[7]->addLink( nodes[8]);
nodes[11]->addLink( nodes[13]);
nodes[12]->addLink( nodes[46]);
nodes[13]->addLink( nodes[19]);
nodes[15]->addLink( nodes[20]);
nodes[16]->addLink( nodes[36]);
nodes[17]->addLink( nodes[37]);
nodes[18]->addLink( nodes[23]);
nodes[19]->addLink( nodes[24]);
nodes[20]->addLink( nodes[21]);
nodes[21]->addLink( nodes[24]);
nodes[22]->addLink( nodes[25]);
nodes[23]->addLink( nodes[34]);
nodes[24]->addLink( nodes[26]);
nodes[25]->addLink( nodes[32]);
nodes[27]->addLink( nodes[31]);
nodes[29]->addLink( nodes[30]);
nodes[33]->addLink( nodes[43]);
nodes[34]->addLink( nodes[42]);
nodes[35]->addLink( nodes[40]);
nodes[37]->addLink( nodes[38]);
nodes[38]->addLink( nodes[40]);
nodes[40]->addLink( nodes[41]);
nodes[41]->addLink( nodes[44]);
nodes[42]->addLink( nodes[44]);
nodes[44]->addLink( nodes[45]);
nodes[18]->addLink( nodes[35]);
nodes[22]->addLink( nodes[33]);
nodes[24]->addLink( nodes[27]);
// *******
nodes[1]->setName("1");
nodes[2]->setName("2");
nodes[3]->setName("3");
nodes[4]->setName("4");
nodes[5]->setName("5");
nodes[6]->setName("6");
nodes[7]->setName("7");
nodes[8]->setName("8");
nodes[9]->setName("9");
nodes[10]->setName("10");
nodes[11]->setName("11");
nodes[12]->setName("12");
nodes[13]->setName("13");
nodes[14]->setName("14");
nodes[15]->setName("15");
nodes[16]->setName("16");
nodes[17]->setName("17");
nodes[18]->setName("18");
nodes[19]->setName("19");
nodes[20]->setName("20");
nodes[21]->setName("21");
nodes[22]->setName("22");
nodes[23]->setName("23");
nodes[24]->setName("24");
nodes[25]->setName("25");
nodes[26]->setName("26");
nodes[27]->setName("27");
nodes[28]->setName("28");
nodes[29]->setName("29");
nodes[30]->setName("30");
nodes[31]->setName("31");
nodes[32]->setName("32");
nodes[33]->setName("33");
nodes[34]->setName("34");
nodes[35]->setName("35");
nodes[36]->setName("36");
nodes[37]->setName("37");
nodes[38]->setName("38");
nodes[39]->setName("39");
nodes[40]->setName("40");
nodes[41]->setName("41");
nodes[42]->setName("42");
nodes[43]->setName("43");
nodes[44]->setName("44");
nodes[45]->setName("45");
nodes[46]->setName("46");
//nodes[]->addLink( nodes[] );
int start_node = 1;
int goal_node = 39;
cerr << "Mode: First First" << endl;
MODE=0;
Path p = *getPath( nodes[start_node], nodes[goal_node] );
dumpPath(p);
cerr << "Path 1 distance travelled: " << p.getLength() << endl << endl;
MODE=1;
cerr << "Mode: First Last" << endl;
Path q = *getPath( nodes[start_node], nodes[goal_node] );
dumpPath(q);
cerr << "Path 2 distance travelled: " << q.getLength() << endl << endl;
double minimum_length = 0;
int minimum_attempt = 0;
MODE=2;
cerr << "Mode: Brute Force" << endl;
vector<Path> paths;
for( int i=0; i<500; i++ )
{
paths.push_back( *getPath( nodes[start_node], nodes[goal_node] ) );
if( minimum_length==0 ) minimum_length = paths[i].getLength();
if( paths[i].getLength() < minimum_length )
{
minimum_length = paths[i].getLength();
minimum_attempt = i;
};
}
dumpPath( paths[minimum_attempt] );
cerr << "Path 3 distance travelled: " << minimum_length << endl << "Attempt #: " << minimum_attempt << endl;
cerr << endl << endl << endl;
return( 0 );
}