File: SystemProcessor.h

package info (click to toggle)
lammps 0~20181211.gitad1b1897d%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 318,860 kB
  • sloc: cpp: 729,569; python: 40,508; xml: 14,919; fortran: 12,142; ansic: 7,454; sh: 5,565; perl: 4,105; f90: 2,700; makefile: 2,117; objc: 238; lisp: 163; tcl: 61; csh: 16; awk: 14
file content (283 lines) | stat: -rw-r--r-- 13,173 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
 *_________________________________________________________________________*
 *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
 *      DESCRIPTION: SEE READ-ME                                           *
 *      FILE NAME: SystemProcessor.h                                       *
 *      AUTHORS: See Author List                                           * 
 *      GRANTS: See Grants List                                            *
 *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
 *      LICENSE: Please see License Agreement                              *
 *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
 *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
 *                     Computational Dynamics Lab                          *
 *                     Rensselaer Polytechnic Institute                    *
 *                     110 8th St. Troy NY 12180                           * 
 *      CONTACT:        anderk5@rpi.edu                                    *
 *_________________________________________________________________________*/

#ifndef _SYS_PROCESSOR_H_
#define _SYS_PROCESSOR_H_
#include "poemslist.h"
#include "poemstree.h"
#include "POEMSChain.h"


struct POEMSNode {
	List<POEMSNode> links;
	List<bool> taken;
	int idNumber;
	bool visited;
	
	~POEMSNode(){
		for(int i = 0; i < taken.GetNumElements(); i++)
		{
			delete taken(i);
		}
	};	
};


class SystemProcessor{
private:
	Tree nodes;
//	List<POEMSNode> forDeletion;
	List<POEMSChain> headsOfSystems;
	List<List<int> > ringsInSystem;
	POEMSNode * findSingleLink(TreeNode * aNode);
	POEMSChain * AddNewChain(POEMSNode * currentNode);
	bool setLinkVisited(POEMSNode * firstNode, POEMSNode * secondNode);
public:
	SystemProcessor(void);
	
	~SystemProcessor(void)	{
		headsOfSystems.DeleteValues();
		for(int i = 0; i < ringsInSystem.GetNumElements(); i++)
		{
			for(int k = 0; k < ringsInSystem(i)->GetNumElements(); i++)
			{
				delete (*ringsInSystem(i))(k);
			}
		}
	};
	void processArray(int** links, int numLinks);
	List<POEMSChain> * getSystemData();
	int getNumberOfHeadChains();
};

SystemProcessor::SystemProcessor(void){
}

void SystemProcessor::processArray(int** links, int numLinks)
{
	bool * false_var;					//holds the value false; needed because a constant cannot be put into a list; the list requires a
										//reference.
	for(int i = 0; i < numLinks; i++)	//go through all the links in the input array
	{
		if(!nodes.Find(links[i][0]))	//if the first node in the pair is not found in the storage tree
		{
			POEMSNode * newNode = new POEMSNode;	//make a new node
//			forDeletion.Append(newNode);
			newNode->idNumber = links[i][0];		//set its ID to the value
			newNode->visited = false;				//set it to be unvisited
			nodes.Insert(links[i][0], links[i][0], (void *) newNode);	//and add it to the tree storage structure
		}
		if(!nodes.Find(links[i][1]))				//repeat process for the other half of each link
		{
			POEMSNode * newNode = new POEMSNode;
//			forDeletion.Append(newNode);
			newNode->idNumber = links[i][1];
			newNode->visited = false;
			nodes.Insert(links[i][1], links[i][1], (void *) newNode);
		}
		POEMSNode * firstNode = (POEMSNode *)nodes.Find(links[i][0]);	//now that we are sure both nodes exist,
		POEMSNode * secondNode = (POEMSNode *)nodes.Find(links[i][1]);	//we can get both of them out of the tree
		firstNode->links.Append(secondNode);							//and add the link from the first to the second...
		false_var = new bool;
		*false_var = false;												//make a new false boolean to note that the link between these two
		firstNode->taken.Append(false_var);								//has not already been taken, and append it to the taken list
		secondNode->links.Append(firstNode);							//repeat process for link from second node to first
		false_var = new bool;
		*false_var = false;
		secondNode->taken.Append(false_var);
	}	
	
	TreeNode * temp = nodes.GetRoot();							//get the root node of the node storage tree
	POEMSNode * currentNode;
	do
	{
		currentNode = findSingleLink(temp);						//find the start of the next available chain
		if(currentNode != NULL)
		{
			headsOfSystems.Append(AddNewChain(currentNode));							//and add it to the headsOfSystems list of chains
		}
	} 
	while(currentNode != NULL);									//repeat this until all chains have been added		
}

POEMSChain * SystemProcessor::AddNewChain(POEMSNode * currentNode){
	if(currentNode == NULL)	//Termination condition; if the currentNode is null, then return null
	{
		return NULL;
	}
	int * tmp;
	POEMSNode * nextNode = NULL;	//nextNode stores the proposed next node to add to the chain.  this will be checked to make sure no backtracking is occuring before being assigned as the current node.
	POEMSChain * newChain = new POEMSChain;	//make a new POEMSChain object.  This will be the object returned

	if(currentNode->links.GetNumElements() == 0)	//if we have no links from this node, then the whole chain is only one node.  Add this node to the chain and return it; mark node as visited for future reference
	{
		currentNode->visited = true;
		tmp = new int;
		*tmp = currentNode->idNumber;
		newChain->listOfNodes.Append(tmp);
		return newChain;
	}
	while(currentNode->links.GetNumElements() <= 2)	//we go until we get to a node that branches, or both branches have already been taken both branches can already be taken if a loop with no spurs is found in the input data
	{
		currentNode->visited = true;
		tmp = new int;
		*tmp = currentNode->idNumber;
		newChain->listOfNodes.Append(tmp);	//append the current node to the chain & mark as visited
		//cout << "Appending node " << currentNode->idNumber << " to chain" << endl;
		nextNode = currentNode->links.GetHeadElement()->value;	//the next node is the first or second value stored in the links array
																//of the current node.  We get the first value...
		if(!setLinkVisited(currentNode, nextNode))					//...and see if it points back to where we came from. If it does...
		{														//either way, we set this link as visited
			if(currentNode->links.GetNumElements() == 1)		//if it does, then if that is the only link to this node, we're done with the chain, so append the chain to the list and return the newly created chain
			{
//				headsOfSystems.Append(newChain);
				return newChain;
			}
			nextNode = currentNode->links.GetHeadElement()->next->value;//follow the other link if there is one, so we go down the chain
			if(!setLinkVisited(currentNode, nextNode))				//mark link as followed, so we know not to backtrack			
			{
	//			headsOfSystems.Append(newChain);
				return newChain;								//This condition, where no branches have occurred but both links have already
																//been taken can only occur in a loop with no spurs; add this loop to the
																//system (currently added as a chain for consistency), and return.
			}
		}
		currentNode = nextNode;									//set the current node to be the next node in the chain
	}
	currentNode->visited = true;
	tmp = new int;
	*tmp = currentNode->idNumber;
	newChain->listOfNodes.Append(tmp);		//append the last node before branch (node shared jointly with branch chains)
																//re-mark as visited, just to make sure
	ListElement<POEMSNode> * tempNode = currentNode->links.GetHeadElement();	//go through all of the links, one at a time that branch
	POEMSChain * tempChain = NULL;								//temporary variable to hold data 
	while(tempNode != NULL)										//when we have followed all links, stop
	{
		if(setLinkVisited(tempNode->value, currentNode))		//dont backtrack, or create closed loops
		{
			tempChain = AddNewChain(tempNode->value);			//Add a new chain created out of the next node down that link
			tempChain->parentChain = newChain;					//set the parent to be this chain
			newChain->childChains.Append(tempChain);			//append the chain to this chain's list of child chains
		}
		tempNode = tempNode->next;								//go to process the next chain
	}
	//headsOfSystems.Append(newChain);							//append this chain to the system list		
	return newChain;	
}

POEMSNode * SystemProcessor::findSingleLink(TreeNode * aNode)
//This function takes the root of a search tree containing POEMSNodes and returns a POEMSNode corresponding to the start of a chain in the
//system.  It finds a node that has not been visited before, and only has one link; this node will be used as the head of the chain.
{
	if(aNode == NULL)	
	{
		return NULL;
	}
	POEMSNode * returnVal =  (POEMSNode *)aNode->GetAuxData();	//get the poemsnode data out of the treenode
	POEMSNode * detectLoneLoops = NULL;							//is used to handle a loop that has no protruding chains
	if(returnVal->visited == false)
	{
		detectLoneLoops = returnVal;							//if we find any node that has not been visited yet, save it
	}
	if(returnVal->links.GetNumElements() == 1 && returnVal->visited == false)	//see if it has one element and hasnt been visited already
	{
		return returnVal;														//return the node is it meets this criteria
	}
	returnVal = findSingleLink(aNode->Left());									//otherwise, check the left subtree
	if(returnVal == NULL)														//and if we find nothing...
	{
		returnVal = findSingleLink(aNode->Right());								//check the right subtree
	}
	if(returnVal == NULL)														//if we could not find any chains
	{
		returnVal = detectLoneLoops;											//see if we found any nodes at all that havent been processed
	}
	return returnVal;															//return what we find (will be NULL if no new chains are 
																				//found)
}

bool SystemProcessor::setLinkVisited(POEMSNode * firstNode, POEMSNode * secondNode)
//setLinkVisited sets the links between these two nodes as visited. If they are already visited, it returns false.  Otherwise, it sets
//them as visited and returns true.  This function is used to see whether a certain path has been taken already in the graph structure.
//If it has been, then we need to know so we dont follow it again; this prevents infinite recursion when there is a loop, and prevents
//backtracking up a chain that has already been made.  The list of booleans denoting if a link has been visited is called 'taken' and is
//part of the POEMSNode struct.  The list is the same size as the list of pointers to other nodes, and stores the boolean visited/unvisited
//value for that particular link.  Because each link is represented twice, (once at each node in the link), both of the boolean values need
//to be set in the event that the link has to be set as visited.
{
	//cout << "Checking link between nodes " << firstNode->idNumber << " and " << secondNode->idNumber << "... ";
	ListElement<POEMSNode> * tmp = firstNode->links.GetHeadElement();	//get the head element of the list of pointers for node 1
	ListElement<bool> * tmp2 = firstNode->taken.GetHeadElement();		//get the head element of the list of bool isVisited flags for node 1
	while(tmp->value != NULL || tmp2->value != NULL)					//go through untill we reach the end of the lists
	{
		if(tmp->value == secondNode)							//if we find the link to the other node
		{
			if(*(tmp2->value) == true)							//if the link has already been visited
			{
				 //cout << "visited already" << endl;
				return false;									//return false to indicate that the link has been visited before this attempt
			}
			else												//otherwise, visit it
			{
				*tmp2->value = true;
			}
			break;
		}
		tmp = tmp->next;										//go check next link
		tmp2 = tmp2->next;
	}

	tmp = secondNode->links.GetHeadElement();			//now, if the link was unvisited, we need to go set the other node's list such that
														//it also knows this link is being visited
	tmp2 = secondNode->taken.GetHeadElement();
	while(tmp->value != NULL || tmp2->value != NULL)	//go through the list
	{
		if(tmp->value == firstNode)						//if we find the link
		{
			if(*(tmp2->value) == true)					//and it has already been visited, then signal an error; this shouldnt ever happen
			{
				cout << "Error in parsing structure! Should never reach this condition! \n" << 
						"Record of visited links out of synch between two adjacent nodes.\n";
				return false;
			}
			else
			{
				*tmp2->value = true;					//set the appropriate value to true to indicate this link has been visited
			}
			break;
		}
		tmp = tmp->next;
		tmp2 = tmp2->next;
	}
	//cout << "not visited" << endl;
	return true;										//return true to indicate that this is the first time the link has been visited
}

List<POEMSChain> * SystemProcessor::getSystemData(void)	//Gets the list of POEMSChains that comprise the system.  Might eventually only
														//return chains linked to the reference plane, but currently returns every chain
														//in the system.
{
	return &headsOfSystems;
}

int SystemProcessor::getNumberOfHeadChains(void) //This function isnt implemented yet, and might be taken out entirely; this was a holdover
												//from when I intended to return an array of chain pointers, rather than a list of chains
												//It will probably be deleted once I finish figuring out exactly what needs to be returned
{
	return 0;
}
#endif