https://github.com/cran/BoolNet
Raw File
Tip revision: 6ba6fe7cd3c694a7f485e66ec014b1da01f3d32c authored by Hans Kestler on 13 January 2012, 00:00:00 UTC
version 1.46
Tip revision: 6ba6fe7
boolean_network.c
/**
 * C code to identify attractors in Boolean networks
 *
 * This is part of the BooleanNetwork R package.
 *
 * Copyright 2009/2010 by Christoph Müssel and Zhou Dao
 *
 * Contact christoph.muessel@uni-ulm.de
 *
 */

#include <R.h>
#include <Rinternals.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include "random.h"
#include "common.h"

/**
 * Identification of attractors
 */

#define SYNC_MODE 0
#define ASYNC_MODE_RANDOM 1

/**
 * Internal structure describing a Boolean network
 */
typedef struct
{
	// the number of genes in the network
	unsigned int numGenes;

	// a vector specifying whether the genes are fixed:
	// -1 means the gene is not fixed, 1 and 0 means the
	// genes are fixed to the corresponding values
	int * fixedGenes;

	// an index array with the <i>-th entry
	// specifying the bit position of the <i>-th gene
	// in a state array - this is not always equal to <i>,
	// as fixed genes are not stored
	unsigned int * nonFixedGeneBits;

	// a vector encoding the input genes for all transition functions.
	int * inputGenes;

	// a vector of indices to split up <inputGenes> for the single
	// gene transition functions.
	int * inputGenePositions;

	// a vector encoding the return values of all transition functions
	int * transitionFunctions;

	// a vector of indices to split up <transitionFunctions> for the single
	// genes.
	int * transitionFunctionPositions;

} BooleanNetwork;


typedef struct TTE
{
	unsigned int * initialState;
	unsigned int * nextState;
	struct TTE * next;
} TransitionTableEntry;

/**
 * Structure that internally describes an attractor
 */
typedef struct Attractor
{

	// an array of states the attractor consists of
	unsigned int *involvedStates;

	// if this is a complex attractor,
	// the transitions of the attractor are stored here
	TransitionTableEntry * table;

	// the number of elements in <table>
	unsigned int transitionTableSize;

	// the number of array elements for one entry of <involvedStates>
	// - i.e. for more than 32 genes, <numElementsPerEntry> successive
	// array elements form one entry.
	unsigned int numElementsPerEntry;

	// the number of states in <involvedStates>
	int length;

	// the number of states in the basin of attraction
	unsigned int basinSize;

	// list pointer to the next element
	struct Attractor *next;
} Attractor, *pAttractor;


/**
 * A structure holding all information
 * retrieved by the algorithms in this file
 */
typedef struct
{
	// the number of elements in the following three arrays
	unsigned long long tableSize;

	// the states before the transition - can be NULL
	unsigned int *initialStates;


	// the resulting states of the transition table
	unsigned int *table;

	// the number of array elements for one entry of the table
	// - i.e. for more than 32 genes, <numElementsPerEntry> successive
	// array elements in <table> and <originalStates> form one table entry.
	unsigned int numElementsPerEntry;

	// the attractors the corresponding states belong to
	unsigned int *attractorAssignment;

	// the number of transitions needed to go from the original state
	// (before transition, not stored here as it is defined by the order)
	// to the attractor
	unsigned int *stepsToAttractor;

	// the list of attractors
	pAttractor attractorList;
} AttractorInfo, *pAttractorInfo;

/**
 * A structure saving search trees for states.
 * State trees are employed if a non-exhaustive search is
 * conducted to provide an efficient method to lookup
 * states that have already been visited.
 */
typedef struct STN
{
	// The left child node (containing "smaller" states)
	struct STN * leftChild;

	// The right child node (containing "larger" states)
	struct STN * rightChild;

	union
	{
		// In case of synchronous networks:
		struct
		{
			// The node holding the next state after a transition has
			// been applied to the current state
			struct STN * successor;

			// The basin of attraction to which the state belongs
			unsigned int attractorAssignment;

			// The number of transitions required to enter the attractor
			unsigned int stepsToAttractor;
		} sync;

		// In case of asynchronous networks:
		struct
		{
			// An array of all successor nodes
			struct STN ** successors;

			// The number of successor states
			unsigned int numSuccessors;

			// Dummy variable
			unsigned int unused;

		} async;
	} type;

	// The state itself - a set of binary-encoded integers with
	// <ceil(number of Genes / 32)> elements
	unsigned int * data;

} StateTreeNode;

void stateTransition(unsigned int * currentState, unsigned int * nextState, BooleanNetwork * net);

unsigned int nodeCount = 0;


/**
 * Allocate a new AttractorInfo structure for <tableSize> states
 */
pAttractorInfo allocAttractorInfo(unsigned long long tableSize, unsigned int numGenes)
{
	pAttractorInfo res = (pAttractorInfo)calloc(1,sizeof(AttractorInfo));
	if ((numGenes % BITS_PER_BLOCK_32) == 0)
		res->numElementsPerEntry = numGenes/BITS_PER_BLOCK_32;
	else
		res->numElementsPerEntry = numGenes/BITS_PER_BLOCK_32 + 1;
	res->table = NULL;
	res->tableSize = tableSize;
	res->initialStates = NULL;
	res->table = (unsigned int*) calloc(tableSize * res->numElementsPerEntry,sizeof(unsigned int));
	res->attractorAssignment = (unsigned int*) calloc(tableSize,sizeof(unsigned int));
	res->stepsToAttractor = (unsigned int*) calloc(tableSize,sizeof(unsigned int));
	return res;
}

/**
 * Free a list of attractor structures
 */
void freeAttractorList(pAttractor p)
{
	do
	{
		pAttractor next = p->next;
		free(p->involvedStates);
		free(p);
		p = next;
	}
	while(p != NULL);
}

/**
 * Free an AttractorInfo structure including
 * all sub-elements and the attractor list
 */
void freeAttractorInfo(pAttractorInfo p)
{
	if (p->initialStates != 0)
		free(p->initialStates);
	free(p->table);
	free(p->attractorAssignment);
	free(p->stepsToAttractor);
	freeAttractorList(p->attractorList);
	free(p);
}

/**
 * Insert a new transition from <initialState> to <nextState> into <table>.
 * <numElements> is the number of array elements occupied by a state.
 */
TransitionTableEntry * insertNewTransition(TransitionTableEntry ** table,
										   unsigned int * initialState,
										   unsigned int * nextState,
										   unsigned int numElements)
{
	TransitionTableEntry * entry = (TransitionTableEntry *)calloc(1,sizeof(TransitionTableEntry));
	entry->initialState = calloc(numElements,sizeof(unsigned int));
	entry->nextState = calloc(numElements,sizeof(unsigned int));
	memcpy(entry->initialState,initialState,numElements*sizeof(unsigned int));
	memcpy(entry->nextState,nextState,numElements*sizeof(unsigned int));
	entry->next = *table;
	*table = entry;
	return entry;
}

/**
 * Free a list-type transition table as used in complex attractors
 */
void freeTransitionTableEntry(TransitionTableEntry * t)
{
	do
	{
		TransitionTableEntry * next = t->next;
		free(t->initialState);
		free(t->nextState);
		free(t);
		t = next;
	}
	while (t != NULL);
}

/**
 * Allocate a new node of a state tree.
 * <leftChild> and <rightChild> are pointers to the
 * left and right subtrees.
 * <successor> is the state reached after a state transition.
 * <data> is an array of binary-encoded integers of length <numElements>
 * describing the state.
 * <attractorAssignment> is the basin of attraction the state belongs to,
 * and <stepsToAttractor> is the number of transitions required to enter
 * the attractor.
 *
 * Returns a state tree node with the supplied values.
 */
StateTreeNode * allocTreeNode(StateTreeNode * leftChild,
							  StateTreeNode * rightChild,
							  StateTreeNode * successor,
							  unsigned int * data,
							  unsigned int numElements,
							  unsigned int attractorAssignment,
							  unsigned int stepsToAttractor)
{
	StateTreeNode * res = calloc(1,sizeof(StateTreeNode));
	res->leftChild = leftChild;
	res->rightChild = rightChild;
	res->type.sync.successor = successor;
	res->data = calloc(numElements,sizeof(unsigned int));
	memcpy(res->data,data,numElements*sizeof(unsigned int));

	res->type.sync.attractorAssignment = attractorAssignment;
	res->type.sync.stepsToAttractor = stepsToAttractor;
	++nodeCount;
	return res;
}

/**
 * Recursive helper function for findNode()
 */
StateTreeNode * findNodeRec(StateTreeNode * parent, unsigned int * data, unsigned int numElements, bool * found)
{
	unsigned int direction = 0;
	int i;
	for (i = numElements - 1; i >= 0; --i)
	{
		if (data[i] > parent->data[i])
		{
			direction = 1;
			break;
		}
		if (data[i] < parent->data[i])
		{
			direction = 2;
		  break;
		}  
	}
	switch(direction)
	{
		case 0:
			*found = true;
			return parent;
		case 1:
			if (parent->rightChild == 0)
			{
				parent->rightChild =  allocTreeNode(0,0,0,data,numElements,0,0);
				*found = false;
				return parent->rightChild;
			}
			else
				return findNodeRec(parent->rightChild,data,numElements,found);
		case 2:
			if (parent->leftChild == 0)
			{
				parent->leftChild =  allocTreeNode(0,0,0,data,numElements,0,0);
				*found = false;
				return parent->leftChild;
			}
			else
				return findNodeRec(parent->leftChild,data,numElements,found);
	}
	// should never be reached
	return 0;
}

/**
 * Recursively find the node corresponding to state <data> in the state tree <root>,
 * or insert the node if it does not exist.
 * <numElements> is the size of the state vector <data>.
 * The return value of <found> indicates whether the element previously existed in the tree
 *
 * Returns the (possibly newly created) node belonging to <data>. If the tree is empty,
 * <root> is set to this node.
 */
StateTreeNode * findNode(StateTreeNode ** root, unsigned int * data, unsigned int numElements, bool * found)
{
	if (*root == 0)
	{
		*root = allocTreeNode(0,0,0,data,numElements,0,0);
		*found = false;
		return *root;
	}
	return findNodeRec(*root,data,numElements, found);
}

/**
 * Returns the successor of the supplied state node <current>.
 * If the state transition has not yet been calculated,
 * a new node is inserted into the tree <root>.
 * <numElementsPerEntry> is the number of array elements required to store one state.
 * <net> describes the network for which a state transition is performed.
 * <basinCounter> is a counter to be increased when a new state is identified
 */
StateTreeNode * findSuccessor(StateTreeNode ** root, StateTreeNode * current,
							 unsigned int numElementsPerEntry, BooleanNetwork * net, unsigned int * basinCounter)
{
	bool found;
	if (current->type.sync.successor == 0)
	// the state does not exist => calculate state transition and insert it
	{
		unsigned int nextState[numElementsPerEntry];
		stateTransition(current->data,nextState,net);
		current->type.sync.successor = findNode(root,nextState,numElementsPerEntry, &found);
 		++ *basinCounter;
	}
	return current->type.sync.successor;
}

/**
 * Traverse the tree supplied by <root> in-order, and write the values
 * of the tree nodes to the corresponding arrays <initialStates>,
 * <table>, <attractorAssignment>, and <stepsToAttractor>.
 * <numElements> is the number of array elements allocated by one state.
 * <nodeNo> is the current value of the node counter used for the array indices
 * and increased during recursion. This should be initially set to 0.
 */
void inOrderSerializeTree(StateTreeNode * root,
						  unsigned int * initialStates,
						  unsigned int * table,
						  unsigned int * attractorAssignment,
						  unsigned int * stepsToAttractor,
						  unsigned int numElements,
						  unsigned int * nodeNo)
{
	if (root->leftChild != 0)
	// recursive descent of left subtree
		inOrderSerializeTree(root->leftChild,initialStates,table,attractorAssignment,
							 stepsToAttractor,numElements,nodeNo);

	// write the state itself
	memcpy(&initialStates[numElements* (*nodeNo)],root->data,numElements*sizeof(unsigned int));
	memcpy(&table[numElements* (*nodeNo)],root->type.sync.successor->data,numElements*sizeof(unsigned int));
	attractorAssignment[*nodeNo] = root->type.sync.attractorAssignment;
	stepsToAttractor[*nodeNo] = root->type.sync.stepsToAttractor;
	*nodeNo = *nodeNo + 1;

	if (root->rightChild != 0)
	// recursive descent of right subtree
		inOrderSerializeTree(root->rightChild,initialStates,table,attractorAssignment,
							 stepsToAttractor,numElements,nodeNo);
}

/**
 * Free a state tree supplied by <node> recursively.
 * If <freeSuccessorArray>, <successors> is assumed to be an array and freed
 */
void freeTreeNode(StateTreeNode * node, bool freeSuccessorArray)
{
	if (node->leftChild != 0)
		freeTreeNode(node->leftChild, freeSuccessorArray);
	if (node->rightChild != 0)
		freeTreeNode(node->rightChild, freeSuccessorArray);
	if (freeSuccessorArray)
		free(node->type.async.successors);
	free(node->data);
	free(node);
	--nodeCount;
}

/**
 * Make a transition from <currentState> to the next state.
 * <currentState> is a binary-coded integer with <numberOfGenes> used bits.
 * <fixedGenes> is an array of values specifying whether gene <i> is fixed (0 or 1) or not (-1).
 * <inputGenes> provides the input genes for all transition functions and can be split up
 * for a single function according to <inputGenePositions>.
 * <transitionFunctions> provides the truth tables for all transition functions and can be split up
 * for a single function according to <transitionFunctionPositions>.
 *
 * The return value is the next state, encoded in a single integer.
 */
void stateTransition(unsigned int * currentState, unsigned int * nextState, BooleanNetwork * net)
{
	unsigned int i = 0, k = 0, idx = 0;

	unsigned int elementsPerEntry;

	if (net->numGenes % BITS_PER_BLOCK_32 == 0)
	{
		elementsPerEntry = net->numGenes / BITS_PER_BLOCK_32;
	}
	else
	{
		elementsPerEntry = net->numGenes / BITS_PER_BLOCK_32 + 1;
	}

	for (i = 0; i < elementsPerEntry; ++i)
		nextState[i] = 0;

	for (i = 1; i <= net->numGenes; ++i)
	{
		if (net->fixedGenes[i-1] == -1)
		// the gene is not fixed
		{
			unsigned long long inputdec = 0;

			for (k = net->inputGenePositions[i-1]; k < net->inputGenePositions[i]; k++)
			{
				if (net->inputGenes[k])
				// if the input of the function is not 0 (constant gene), take input bit
				{
					unsigned int gene = net->inputGenes[k] - 1;
					unsigned int bit;

					if (net->fixedGenes[gene] == -1)
						bit = (GET_BIT(currentState[net->nonFixedGeneBits[gene] / BITS_PER_BLOCK_32],
							   net->nonFixedGeneBits[gene] % BITS_PER_BLOCK_32));
					else
						// fixed genes are not encoded in the states
						// => take them from fixedGenes vector
						bit = net->fixedGenes[gene];
					inputdec |= bit	<< (net->inputGenePositions[i] - k - 1);
				}
			}
			// determine transition function
			int transition = net->transitionFunctions[net->transitionFunctionPositions[i-1] + inputdec];

			if(transition != -1)
				// apply transition function
				nextState[idx / BITS_PER_BLOCK_32] |= (transition << (idx % BITS_PER_BLOCK_32));
			else
				// this is a dummy function for a constant gene
				// => value does not change
				nextState[idx / BITS_PER_BLOCK_32] |= (GET_BIT(currentState[idx / BITS_PER_BLOCK_32],
															idx % BITS_PER_BLOCK_32) << (idx % BITS_PER_BLOCK_32));

													//(GET_BIT(currentState[(i-1) / BITS_PER_BLOCK_32],
				                                     //   		 (i-1) % BITS_PER_BLOCK_32) << (idx % BITS_PER_BLOCK_32));
			++idx;
		}
	}
}

/**
 * Retrieves the result column of the state transition table.
 * <numberOfGenes> specifies the total number of genes.
 * <fixedGenes> is an array of values specifying whether gene <i> is fixed (0 or 1) or not (-1).
 * <inputGenes> provides the input genes for all transition functions and can be split up
 * for a single function according to <inputGenePositions>.
 * <transitionFunctions> provides the truth tables for all transition functions and can be split up
 * for a single function according to <transitionFunctionPositions>.
 */
unsigned long long * getTransitionTable(BooleanNetwork * net)
{
	unsigned long long i = 0;

	// determine number of fixed genes
	int numFixed = 0;
	for( i = 0; i < net->numGenes; i++)
		if(net->fixedGenes[i] != -1)
			++numFixed;

	int numNonFixed = net->numGenes - numFixed;

	// allocate truth table with 2^(non-fixed genes) elements
	unsigned long long numberOfElements = pow(2,numNonFixed);
	unsigned long long * table = calloc(numberOfElements,sizeof(unsigned long long));
	if (table == 0)
	{
		Rf_error("Too few memory available!");
	}

	unsigned long long initialState = 0;

	// calculate state transitions
	for(initialState = 0; initialState < numberOfElements; ++initialState)
	{
		//state is simply the binary encoding of the counter
		//calculate transition
		table[initialState] = 0;
		stateTransition((unsigned int *)&initialState,
						(unsigned int *)&table[initialState],
						net);
	}
	return table;
}

/**
 * Retrieves attractors from a given transition table <table> with <numberOfStates> entries.
 * 
 * Returns a list of attractors - the last element of this list is empty!
 */
pAttractorInfo getAttractors(unsigned long long * table, unsigned int numberOfStates, unsigned int numberOfGenes)
{
	unsigned long long i;
	unsigned int current_attractor = 0, elementsPerEntry;

	if (numberOfGenes <= 32)
	{
		elementsPerEntry = 1;
	}
	else
	{
		elementsPerEntry = 2;
	}

	pAttractorInfo result = allocAttractorInfo(numberOfStates,numberOfGenes);

	for (i = 0; i < numberOfStates; ++i)
	{
		memcpy(&result->table[i],&table[i],sizeof(unsigned int) * elementsPerEntry);
	}

	pAttractor attractorHead, attractorList,tmpList;
	attractorHead = attractorList = (pAttractor) calloc(1,sizeof(Attractor));
	attractorList->next = NULL;

	for(i = 0; i < numberOfStates; i++)
	{
		if(!result->attractorAssignment[i])
		// the current state has not yet been visited
		{

			// first attractor has number 1
			current_attractor++;

			unsigned long long begin = i;
			unsigned int steps = 0;

			while(!result->attractorAssignment[begin])
			// iterate while no attractor has been assigned
			{
				++steps;

				// first simply count steps until attractor is reached
				// - to get the distance to the attractor, this number is
				// later subtracted from the maximum distance
				result->stepsToAttractor[begin] = steps;
				result->attractorAssignment[begin] = current_attractor;

				// perform a state transition
				begin = table[begin];
			}
			if(current_attractor == result->attractorAssignment[begin])
			//calculate length and basin size of new attractor
			{
				attractorList->basinSize = steps;

				// fix the number of steps to the attractor by calculating
				// the maximum distance and subtracting the current value from it
				int maxstep = result->stepsToAttractor[begin];

				int rec = 0;
				unsigned long long tmp = i;
				while(tmp != begin)
				{
					rec++;
					result->stepsToAttractor[tmp] = maxstep - result->stepsToAttractor[tmp];
					tmp = table[tmp];
				}

				attractorList->length = steps - rec;

				attractorList->involvedStates = (unsigned int *) calloc(attractorList->length * elementsPerEntry,sizeof(unsigned int));
				attractorList->numElementsPerEntry = elementsPerEntry;

				int a=0;
				do
				{
					result->stepsToAttractor[tmp] = 0;
					//attractorList->involvedStates[a++] = tmp;
					memcpy(&attractorList->involvedStates[a],&tmp,elementsPerEntry*sizeof(unsigned int));
					tmp = table[tmp];
					a += elementsPerEntry;
				}
				while(tmp != begin); /* set steps of attractors to 0; add attractor stub information */

				//generate a next attractor space
				attractorList->next = (pAttractor)calloc(1,sizeof(Attractor));
				attractorList = attractorList->next;
				attractorList->next = NULL;
			}
			else
			//update existing attractor
			{
				// reset attractor number
				current_attractor--;

				// assign states to attractor basin, and
				// correct the numbers of steps to the attractor
				unsigned long long tmp = i;
				int maxstp = result->stepsToAttractor[begin] + steps;
				while(tmp != begin)
				{
					result->attractorAssignment[tmp] = result->attractorAssignment[begin];
					result->stepsToAttractor[tmp] = maxstp - result->stepsToAttractor[tmp] + 1;
					tmp = table[tmp];
				}

				// update basin size in attractor record
				tmpList = attractorHead;
				for (tmp = 1; tmp < result->attractorAssignment[begin]; tmp++)
					tmpList = tmpList->next;

				tmpList->basinSize = tmpList->basinSize + steps;
			}
		}
	}

	result->attractorList = attractorHead;

	free(table);

	return result;
}

/**
 * Retrieves attractors only for a given set of input states supplied in <selectedStates>.
 * Here, <ceil(net->numGenes / 32)> consecutive array entries describe one state, thus
 * the array size is <ceil(net->numGenes / 32) * numberOfStates>
 * <net> describes the network structure.
 */
pAttractorInfo getAttractorsForStates(unsigned int * selectedStates, unsigned int numberOfStates,
									  BooleanNetwork * net)
{
  unsigned long long i;
	unsigned int current_attractor = 0, elementsPerEntry;
	bool found;

	// calculate the number of array elements required for one state
	// (depending on the number of genes)
	if (net->numGenes % (sizeof(unsigned int) * 8) == 0)
	{
		elementsPerEntry = net->numGenes / BITS_PER_BLOCK_32;
	}
	else
	{
		elementsPerEntry = net->numGenes / BITS_PER_BLOCK_32 + 1;
	}
	
	// all states are stored in a tree for fast search
	StateTreeNode * stateTree = 0;

	pAttractor attractorHead, attractorList,tmpList;
	attractorHead = attractorList = (pAttractor) calloc(1,sizeof(Attractor));
	attractorList->next = NULL;
	
	for(i = 0; i < numberOfStates; i++)
	{
	  // check whether the current state is already in the state tree, otherwise insert it
		StateTreeNode * currentState = findNode(&stateTree,&selectedStates[i*elementsPerEntry],elementsPerEntry,&found);
		if(!currentState->type.sync.attractorAssignment)
		// the current state has not yet been visited
		{

			// first attractor has number 1
			current_attractor++;

			unsigned int steps = 0;
			unsigned int basinSize = 0;

			while(!currentState->type.sync.attractorAssignment)
			// iterate while no attractor has been assigned
			{
				++steps;

				// first simply count steps until attractor is reached
				// - to get the distance to the attractor, this number is
				// later subtracted from the maximum distance
				currentState->type.sync.stepsToAttractor = steps;
				currentState->type.sync.attractorAssignment = current_attractor;

				// perform a state transition
				currentState = findSuccessor(&stateTree,currentState,elementsPerEntry,net,&basinSize);
			}
			if(current_attractor == currentState->type.sync.attractorAssignment)
			//calculate length and basin size of new attractor
			{
				attractorList->basinSize = steps;

				// fix the number of steps to the attractor by calculating
				// the maximum distance and subtracting the current value from it
				int maxstep = currentState->type.sync.stepsToAttractor;

				int rec = 0;
				StateTreeNode * tmp = findNode(&stateTree,&selectedStates[i*elementsPerEntry],elementsPerEntry,&found);

				while(memcmp(tmp->data,currentState->data,elementsPerEntry*sizeof(unsigned int)))
				{
					rec++;
					tmp->type.sync.stepsToAttractor = maxstep - tmp->type.sync.stepsToAttractor;

					// perform a state transition
					tmp = findSuccessor(&stateTree,tmp,elementsPerEntry,net,&basinSize);
				}

				attractorList->length = steps - rec;

				attractorList->involvedStates = (unsigned int *) calloc(attractorList->length * elementsPerEntry,sizeof(unsigned int));
				attractorList->numElementsPerEntry = elementsPerEntry;

				int a=0;
				do
				{
					tmp->type.sync.stepsToAttractor = 0;
					memcpy(&attractorList->involvedStates[a],tmp->data,elementsPerEntry*sizeof(unsigned int));
					tmp = findSuccessor(&stateTree,tmp,elementsPerEntry,net,&basinSize);
					a += elementsPerEntry;
				}
				while(memcmp(tmp->data,currentState->data,elementsPerEntry*sizeof(unsigned int)));

				//generate a next attractor space
				attractorList->next = (pAttractor)calloc(1,sizeof(Attractor));
				attractorList = attractorList->next;
				attractorList->next = NULL;
			}
			else
			//update existing attractor
			{
				// reset attractor number
				current_attractor--;

				// assign states to attractor basin, and
				// correct the numbers of steps to the attractor
				StateTreeNode * tmp = findNode(&stateTree,&selectedStates[i*elementsPerEntry],elementsPerEntry,&found);
				int maxstp = currentState->type.sync.stepsToAttractor + steps;

				while(memcmp(tmp->data,currentState->data,elementsPerEntry*sizeof(unsigned int)))
				{
					tmp->type.sync.attractorAssignment = currentState->type.sync.attractorAssignment;
					tmp->type.sync.stepsToAttractor = maxstp - tmp->type.sync.stepsToAttractor + 1;

					//perform a state transition
					tmp = findSuccessor(&stateTree,tmp,elementsPerEntry,net,&basinSize);
				}

				// update basin size in attractor record
				tmpList = attractorHead;

				unsigned int i;
				for (i = 1; i < currentState->type.sync.attractorAssignment; ++i)
					tmpList = tmpList->next;

				tmpList->basinSize = tmpList->basinSize + basinSize;
			}
		}
	}

	pAttractorInfo result = allocAttractorInfo(nodeCount,net->numGenes);
	result->attractorList = attractorHead;
	result->initialStates = calloc(result->tableSize * elementsPerEntry,sizeof(unsigned int));

	unsigned int nodeNo = 0;

	// build a series of arrays by in-order traversing the tree
	inOrderSerializeTree(stateTree,
						 result->initialStates,
						 result->table,
						 result->attractorAssignment,
						 result->stepsToAttractor,
						 elementsPerEntry,
						 &nodeNo);
	freeTreeNode(stateTree,false);
	return result;
}

/**
 * Identification of attractors in asynchronous networks
 */

typedef struct SSE
{
	unsigned int * state;
	struct SSE * next;
} StateStackElement;

/**
 * Push a new element on top of the stack <stack>.
 * <state> is the state to push onto the stack and has <numElements> elements.
 * Returns the new stack element.
 */
static inline StateStackElement * pushStateStackElement(StateStackElement ** stack,
												 unsigned int * state,
												 unsigned int numElements)
{
	StateStackElement * el = calloc(1,sizeof(StateStackElement));


	el->state = calloc(numElements,sizeof(unsigned int));
	memcpy(el->state,state,sizeof(unsigned int) * numElements);

	el->next = *stack;
	*stack = el;
	return el;
}

/**
 * Remove the top-level element from <stack>.
 */
static inline void deleteStateStackElement(StateStackElement ** stack)
{
	StateStackElement * el = *stack;
	*stack = (*stack)->next;
	free(el->state);
	free(el);
}


/**
 * Applies the transition function belonging to gene <geneIdx> to state <currentState>.
 * <net> holds the network information.
 * The result is returned in <currentState>.
 */
static inline void applySingleFunction(unsigned int * currentState, unsigned int geneIdx, BooleanNetwork * net)
{
	unsigned int k = 0;


	if (net->fixedGenes[geneIdx] == -1)
	// the gene is not fixed
	{
		unsigned long long inputdec = 0;

		for (k = net->inputGenePositions[geneIdx]; k < net->inputGenePositions[geneIdx+1]; k++)
		{
			if (net->inputGenes[k])
			// if the input of the function is not 0 (constant gene), take input bit
			{
				unsigned int gene = net->inputGenes[k] - 1;
				unsigned int bit;

				if (net->fixedGenes[gene] == -1)
					bit = (GET_BIT(currentState[gene / BITS_PER_BLOCK_32],
						   gene % BITS_PER_BLOCK_32));
				else
					// fixed genes are not encoded in the states
					// => take them from fixedGenes vector
					bit = net->fixedGenes[gene];
				inputdec |= bit	<< (net->inputGenePositions[geneIdx+1] - k - 1);
			}
		}
		// determine transition function
		int transition = net->transitionFunctions[net->transitionFunctionPositions[geneIdx] + inputdec];

		currentState[geneIdx / BITS_PER_BLOCK_32] = CLEAR_BIT(currentState[geneIdx / BITS_PER_BLOCK_32],
															  geneIdx % BITS_PER_BLOCK_32);

		if(transition != -1)
			// apply transition function
			currentState[geneIdx / BITS_PER_BLOCK_32] |= (transition << (geneIdx % BITS_PER_BLOCK_32));
		else
			// this is a dummy function for a constant gene
			// => value does not change
			currentState[geneIdx / BITS_PER_BLOCK_32] |= (GET_BIT(currentState[geneIdx / BITS_PER_BLOCK_32],
														geneIdx % BITS_PER_BLOCK_32) << (geneIdx % BITS_PER_BLOCK_32));

	}
}

/**
 * Calculate a random asynchronous state transition for <currentState>.
 * If <probabilities> is not NULL, this is a vector specifying
 * the cumulative distribution function of the probabilities of genes
 * to be chosen for a transition. Otherwise, each gene has equal probability.
 */
static inline void asynchronousStateTransition(unsigned int * currentState, double * probabilities,
										BooleanNetwork * net)
{
	unsigned int numElts, i;
	if (net->numGenes % BITS_PER_BLOCK_32 == 0)
		numElts = net->numGenes / BITS_PER_BLOCK_32;
	else
		numElts = net->numGenes / BITS_PER_BLOCK_32 + 1;

	if (probabilities == NULL)
	// uniform gene selection
	{
		unsigned int r;
		// ensure that no fixed gene is chosen
		do
		{
			r = intrand(net->numGenes);
		}
		while (net->fixedGenes[r] != -1);
		// make a transition with the chosen gene
		applySingleFunction(currentState,r,net);
	}
	else
	{
		double r = doublerand_1();

		// find the last index in the cumulative distribution that
		// is less than <r>
		for (i = 0; i < net->numGenes; ++i)
		{
			if (probabilities[i] < r && probabilities[i+1] >= r)
				break;
		}
		// make a transition with the chosen gene
		applySingleFunction(currentState,i,net);
	}
}

/**
 * Calculate the forward reachable set of <startState>.
 * <numElements> is the number of array elements used to represent one state.
 * If <avoidSelfLoops> is true, self loops are only considered if there are no other possible transitions.
 * <net> holds the network information.
 * <res> points to the root of the resulting state tree (set).
 * Returns the number of states in the set.
 */
unsigned int buildAsynchronousStateSet(unsigned int * startState, unsigned int numElements,
									   bool avoidSelfLoops, BooleanNetwork * net, StateTreeNode ** res)
{
	unsigned int startNodeCount = nodeCount;
	StateStackElement * stack = NULL;
	unsigned int i;
	bool found=false, newNodes=false;

	// push the start state onto the stack
	pushStateStackElement(&stack,startState,numElements);
	do
	// iterate while stack is not empty (depth-first search)
	{
		unsigned int origstate[numElements];

		memcpy(origstate,stack->state,sizeof(unsigned int) * numElements);

		// remove the top-level stack element
		deleteStateStackElement(&stack);

		StateTreeNode * current = findNode(res,origstate,numElements,&found);

		StateTreeNode ** successors;
		unsigned int numSuccessors;

		if (avoidSelfLoops)
		// try to find successor states that do not lead to the initial state
		{
			unsigned int successorStates[net->numGenes*numElements];
			for (i = 0; i < net->numGenes; ++i)
			// first, calculate all successors
			{
				memcpy(&successorStates[i*numElements],origstate,sizeof(unsigned int) * numElements);
				applySingleFunction(&successorStates[i*numElements],i,net);
			}

			unsigned int numNonSelfLoops = 0;
			bool noSelfLoop[net->numGenes];
			for (i = 0; i < net->numGenes; ++i)
			// now, check which of the successor states are the same as the initial state
			{
				if (memcmp(&successorStates[i*numElements],origstate,sizeof(unsigned int) * numElements) != 0)
				{
					++numNonSelfLoops;
					noSelfLoop[i] = true;
				}
				else
					noSelfLoop[i] = false;
			}
			if (numNonSelfLoops == 0)
			// all transitions are self loops
			// => accept self loop
			{
				successors = calloc(1,sizeof(StateTreeNode * ));
				numSuccessors = 1;
				successors[0] = findNode(res,successorStates,numElements,&found);
				if (!found)
					pushStateStackElement(&stack,successorStates,numElements);
			}
			else
			// there is at least one transition that is no self loop
			// => do not accept self loops
			{
				successors = calloc(numNonSelfLoops,sizeof(StateTreeNode * ));
				numSuccessors = numNonSelfLoops;
				unsigned int j;
				for (i = 0, j = 0; i < net->numGenes; ++i)
				{
					if (noSelfLoop[i])
					// create successor in tree
					{
						successors[j++] = findNode(res,&successorStates[i*numElements],numElements,&found);
						newNodes = newNodes | !found;
						if (!found)
							pushStateStackElement(&stack,&successorStates[i*numElements],numElements);
					}
				}
			}
		}
		else
		// self loops are allowed
		{
			unsigned int state[numElements];
			successors = calloc(net->numGenes,sizeof(StateTreeNode * ));
			numSuccessors = net->numGenes;
			for (i = 0; i < net->numGenes; ++i)
			// calculate all successors
			{
				memcpy(state,origstate,sizeof(unsigned int) * numElements);
				applySingleFunction(state,i,net);
				successors[i] = findNode(res,state,numElements,&found);
				newNodes = newNodes | !found;
				if (!found)
					pushStateStackElement(&stack,state,numElements);
			}
		}

		current->type.async.successors = successors;
		current->type.async.numSuccessors = numSuccessors;
	}
	while (stack != NULL);

	// return the number of elements in the state set
	return (nodeCount - startNodeCount);
}

/**
 * Recursively retrieve an array of states from a tree <root>
 * and store it to <states.
 * <numElements> is the number of array elements used to represent one state.
 * <nodeNo> is the current array entry to be written and should be initialized to 0.
 */
void getStateSet(StateTreeNode * root,
				 unsigned int * states,
				 unsigned int numElements,
				 unsigned int * nodeNo)
{

	if (root->leftChild != 0)
	// recursive descent of left subtree
		getStateSet(root->leftChild,states,numElements,nodeNo);

	// write the state itself
	memcpy(&states[numElements* (*nodeNo)],root->data,numElements*sizeof(unsigned int));
	*nodeNo = *nodeNo + 1;

	if (root->rightChild != 0)
	// recursive descent of right subtree
		getStateSet(root->rightChild,states,numElements,nodeNo);
}

/**
 * Recursively extract the transition table from a state set <root>
 * and store it to a list of transitions <table>.
 * <numElements> is the number of array elements used to represent one state.
 * <size> receives the size of the resulting table.
 */
void getLooseAttractorTransitionTable(StateTreeNode * root,
									 TransitionTableEntry ** table,
									unsigned int numElements,
									unsigned int * size)
{
	if (root->leftChild != 0)
	// recursive descent of left subtree
		getLooseAttractorTransitionTable(root->leftChild,table,numElements,size);

	bool duplicate[root->type.async.numSuccessors];
	memset(duplicate,0,sizeof(bool)*root->type.async.numSuccessors);

	unsigned int i, j;

	// check for duplicate transitions
	for (i = 0; i < root->type.async.numSuccessors; ++i)
	{
		for (j = i + 1; j < root->type.async.numSuccessors; ++j)
		{
			if (memcmp(&root->type.async.successors[i * numElements],
					   &root->type.async.successors[j * numElements],
					   sizeof(unsigned int) * numElements) == 0)
				duplicate[j] = true;
		}
	}

	// copy the unique transitions to the table
	for (i = 0; i < root->type.async.numSuccessors; ++i)
	{
		if (!duplicate[i])
		{
			insertNewTransition(table,root->data,root->type.async.successors[i]->data,numElements);
			++ *size;
		}
	}

	if (root->rightChild != 0)
	// recursive descent of right subtree
		getLooseAttractorTransitionTable(root->rightChild,table,numElements, size);
}

/**
 * Validate whether a set <attractor> with <attractorLength> states is a true attractor.
 * If <avoidSelfLoops> is true, self loops are only considered if there are no other possible transitions.
 * <net> holds the network information.
 */
bool validateAttractor(unsigned int * attractor, unsigned int attractorLength,
					   bool avoidSelfLoops,BooleanNetwork * net)
{
	unsigned int numElts, i;
	if (net->numGenes % BITS_PER_BLOCK_32 == 0)
		numElts = net->numGenes / BITS_PER_BLOCK_32;
	else
		numElts = net->numGenes / BITS_PER_BLOCK_32 + 1;

	for (i = 0; i < attractorLength; ++i)
	// iterate over states
	{
		StateTreeNode * set = NULL;

		// calculate forward reachable set of current state
		unsigned int size_set = buildAsynchronousStateSet(&attractor[i*numElts],numElts,avoidSelfLoops,net,&set);
		if (size_set != attractorLength)
		{
			freeTreeNode(set,true);
			return false;
		}

		unsigned int states_set[numElts * size_set];
		unsigned int nodeNo = 0;
		getStateSet(set,states_set,numElts,&nodeNo);
		freeTreeNode(set,true);

		// compare forward reachable set to original set
		if (memcmp(states_set,attractor,sizeof(unsigned int) * numElts * size_set) != 0)
			// no attractor
			return false;

	}
	return true;
}

/**
 * Calculate complex/loose attractors by performing <randomSteps> random transitions from
 * the <numberOfStates> states supplied in <selectedStates>.
 * If <avoidSelfLoops> is true, self loops are only considered if there are no other possible transitions.
 * If <probabilities> is not NULL, this vector holds the probabilities for each gene to be chosen
 * for a transition.
 */
pAttractorInfo getLooseAttractors(unsigned int * selectedStates, unsigned int numberOfStates,
					    BooleanNetwork * net, unsigned int randomSteps,
					    bool avoidSelfLoops, double * probabilities)
{
	// attractor list has empty dummy element at the end
	pAttractor attractorList = calloc(1,sizeof(Attractor));

	unsigned int numElts, i, j;
	if (net->numGenes % BITS_PER_BLOCK_32 == 0)
		numElts = net->numGenes / BITS_PER_BLOCK_32;
	else
		numElts = net->numGenes / BITS_PER_BLOCK_32 + 1;

	// if probabilities for the genes are supplied, exclude fixed genes (if any)
	// and recalculate probabilities
	double * pProbabilities = NULL;
	double convertedProbabilities[net->numGenes + 1];
	if (probabilities != NULL)
	{
		convertedProbabilities[0] = 0.0;
		double probabilitySum = 0.0;
		for (i = 0; i < net->numGenes; ++i)
		{
			if (net->fixedGenes[i] == -1)
				probabilitySum += probabilities[i];
		}
		for (i = 0; i < net->numGenes; ++i)
		{
			if (net->fixedGenes[i] == -1)
				convertedProbabilities[i+1] = convertedProbabilities[i]
				                               + probabilities[i]/probabilitySum;
			else
				convertedProbabilities[i+1] = convertedProbabilities[i];
		}
		pProbabilities = convertedProbabilities;
	}

	for (i = 0; i < numberOfStates; ++i)
	// iterate over supplied start states
	{
		unsigned int currentState[numElts];
		memcpy(currentState,&selectedStates[i*numElts],sizeof(unsigned int) * numElts);

		unsigned int t = 0;
		for (j = randomSteps; j > 0; --j)
		// perform <randomSteps> random state transitions
		// to reach a potential attractor
		{

			asynchronousStateTransition(currentState,pProbabilities,net);

			++t;
		}

		// calculate forward reachable set of end state
		StateTreeNode * set = NULL;
		unsigned int size_set = buildAsynchronousStateSet(currentState,numElts,avoidSelfLoops,net,&set);
		unsigned int states_set[numElts * size_set];

		unsigned int nodeNo = 0;
		getStateSet(set,states_set,numElts,&nodeNo);


		// search for the current potential attractor in the attractor list
		bool found = false;
		pAttractor current = attractorList;

		while (current != NULL && !found)
		{
			found = ((size_set == current->length)
					&& (memcmp(states_set,current->involvedStates,sizeof(unsigned int) * numElts * size_set) == 0));
			current = current->next;
		}


		if (!found)
		// the potential attractor does not yet exist in the result list
		{
			if (validateAttractor(states_set,size_set,avoidSelfLoops,net))
			// check whether this is a true attractor
			{
				pAttractor attractor = calloc(1,sizeof(Attractor));

				attractor->numElementsPerEntry = numElts;
				attractor->length = size_set;
				attractor->involvedStates = calloc(numElts * size_set,sizeof(unsigned int));
				memcpy(attractor->involvedStates,states_set,sizeof(unsigned int) * numElts * size_set);

				attractor->transitionTableSize = 0;

				if (size_set != 1)
				// if this is a steady-state attractor, no need to store transition table!
					getLooseAttractorTransitionTable(set,&attractor->table,numElts,&(attractor->transitionTableSize));

				attractor->next = attractorList;
				attractorList = attractor;
			}
		}
		freeTreeNode(set,true);
	}
	pAttractorInfo res = allocAttractorInfo(0,net->numGenes);
	res->attractorList = attractorList;
	return res;
}

/**
 * The R wrapper function for getAttractors.
 * Arguments:
 * inputGenes			An integer vector containing the concatenated input gene lists
 * 						of *all* transition functions
 * inputGenePositions	A vector of positions to split up <inputGenes> for each transition function
 * transitionFunctions	The concatenated truth table result columns of the transition functions of all genes.
 * transitionFunctionPositions	A vector of positions to split up <transitionFunctions> for each transition function.
 * fixedGenes			A vector that contains -1 for all genes that can be both ON and OFF, 1 for genes that are always ON,
 * 						and 0 for genes that are always OFF.
 * specialInitializations	A matrix of special initializations supplied by the user. The first row contains the genes,
 * 							the second row contains the corresponding initialization values.
 * startStates			An optional array of encoded states used to initialize the heuristics
 * 						(not needed for exhaustive search)
 * networkType			An integer that determines whether a synchronous or asynchronous search is performed
 * geneProbabilities	For asynchronous search, the probabilities of each gene to be chosen for update
 * randomSteps			For asynchronous search, the number of random transitions performed to reach a potential attractor
 * avoidSelfLoops		If set to true, self loops are only allowed if no other transitions are possible, which reduces the
 * 						number of edges in the attractors
 * returnTable			If set to true and networkType is synchronous, the transition table is included in the return value.
 */
SEXP getAttractors_R(SEXP inputGenes,
					 SEXP inputGenePositions,
					 SEXP transitionFunctions,
					 SEXP transitionFunctionPositions,
					 SEXP fixedGenes,
					 SEXP startStates,
					 SEXP networkType,
					 SEXP geneProbabilities,
					 SEXP randomSteps,
					 SEXP avoidSelfLoops,
					 SEXP returnTable)
{
  GetRNGstate();

	// decode information in SEXP for use in C

	BooleanNetwork network;
	network.numGenes = length(fixedGenes);

	network.inputGenes = INTEGER(inputGenes);
	network.inputGenePositions = INTEGER(inputGenePositions);
	network.transitionFunctions = INTEGER(transitionFunctions);
	network.transitionFunctionPositions = INTEGER(transitionFunctionPositions);
	network.fixedGenes = INTEGER(fixedGenes);
	network.nonFixedGeneBits = calloc(network.numGenes,sizeof(unsigned int));

	int _networkType = *INTEGER(networkType);
	int _randomSteps = *INTEGER(randomSteps);

	bool _returnTable = (bool)(*INTEGER(returnTable));
	bool _avoidSelfLoops = (bool)(*INTEGER(avoidSelfLoops));

	double * _probabilities = NULL;
	if (!isNull(geneProbabilities) && length(geneProbabilities) > 0)
		_probabilities = REAL(geneProbabilities);

	// count fixed genes, and create an index array for non-fixed genes:
	// <network.nonFixedGeneBits[i]> contains the bit positions in a state
	// at which the <i>-th gene is stored - this is different from <i>
	// as fixed genes are not stored
	unsigned int numNonFixed = 0, i;

	for(i = 0; i < network.numGenes; i++)
	{
		if(network.fixedGenes[i] == -1)
		{
			network.nonFixedGeneBits[i] = numNonFixed++;
		}
	}

	pAttractorInfo res;

	if (isNull(startStates) || length(startStates) == 0)
	// no start states supplied => perform exhaustive search
	{
		// calculate transition table
		unsigned long long * table = getTransitionTable(&network);

		if (table == 0)
		{
  		PutRNGstate();
			return R_NilValue;
    }

		unsigned long long numStates = pow(2,numNonFixed);

		// find attractors
		res = getAttractors(table, numStates, network.numGenes);
	}
	else
	// start states supplied => only identify attractors for these states
	{
		unsigned int numElts;
		if (network.numGenes % BITS_PER_BLOCK_32 == 0)
			numElts = network.numGenes / BITS_PER_BLOCK_32;
		else
			numElts = network.numGenes / BITS_PER_BLOCK_32 + 1;

		unsigned int* _startStates = (unsigned int*) INTEGER(startStates);
	
		if (_networkType == SYNC_MODE)
		{
		  for (unsigned int i = 0; i < length(startStates) / numElts; ++i)
		  {
		    removeFixedGenes(&_startStates[i*numElts],network.fixedGenes,network.numGenes);
		  }
			res = getAttractorsForStates(_startStates, length(startStates) / numElts,
										&network);
		}
		else
		{
			res = getLooseAttractors(_startStates, length(startStates) / numElts,
								     &network,_randomSteps,
								     _avoidSelfLoops,_probabilities);
		}
	}

	// pack results in SEXP structure for return value
	SEXP resSXP;
	SEXP stateInfoSXP;
	int* array;

	// create a result list with two elements (attractors and transition table)
	PROTECT(resSXP = allocList(2));
	SET_TAG(resSXP, install("stateInfo"));
	SET_TAG(CDR(resSXP), install("attractors"));

	if (res->tableSize != 0 && _returnTable)
	{
		// create a 3-element list for the transition table
		PROTECT(stateInfoSXP = allocList(4));
		SET_TAG(stateInfoSXP, install("table"));
		SET_TAG(CDR(stateInfoSXP), install("attractorAssignment"));
		SET_TAG(CDR(CDR(stateInfoSXP)), install("stepsToAttractor"));
		SET_TAG(CDR(CDR(CDR(stateInfoSXP))), install("initialStates"));

		// write transition table result column
		SEXP tableSXP;
		PROTECT(tableSXP = allocVector(INTSXP,res->tableSize * res->numElementsPerEntry));
		array = INTEGER(tableSXP);
		for (i = 0; i < res->tableSize; ++i)
		{
			// the transition table results do not contain fixed genes => insert them
			insertFixedGenes(&res->table[i*res->numElementsPerEntry],network.fixedGenes,network.numGenes);
			memcpy(&array[i*res->numElementsPerEntry],&res->table[i*res->numElementsPerEntry],
					res->numElementsPerEntry * sizeof(unsigned int));
		}
		SETCAR(stateInfoSXP,tableSXP);
		UNPROTECT(1);

		// write attractor assignment vector for states in transition table
		SEXP assignmentSXP;
		PROTECT(assignmentSXP = allocVector(INTSXP,res->tableSize));
		array = INTEGER(assignmentSXP);
		memcpy(array,res->attractorAssignment,res->tableSize * sizeof(int));
		SETCADR(stateInfoSXP,assignmentSXP);
		UNPROTECT(1);

		// write a vector with number of transitions from a state to an attractor
		SEXP stepSXP;
		PROTECT(stepSXP = allocVector(INTSXP,res->tableSize));
		array = INTEGER(stepSXP);
		memcpy(array,res->stepsToAttractor,res->tableSize * sizeof(int));
		SETCADDR(stateInfoSXP,stepSXP);
		UNPROTECT(1);

		// if available, write the original states
		SEXP initialStateSXP;
		if (res->initialStates == 0)
			initialStateSXP = R_NilValue;
		else
		// if start states are specified, the initial states for each transition have to be saved as well,
		// as they cannot be inferred by enumeration
		{
			PROTECT(initialStateSXP = allocVector(INTSXP,res->tableSize * res->numElementsPerEntry));
			array = INTEGER(initialStateSXP);
			for (i = 0; i < res->tableSize; ++i)
			{
				// the transition table results do not contain fixed genes => insert them
				insertFixedGenes(&res->initialStates[i*res->numElementsPerEntry],network.fixedGenes,network.numGenes);
				memcpy(&array[i*res->numElementsPerEntry],
						&res->initialStates[i*res->numElementsPerEntry],res->numElementsPerEntry * sizeof(unsigned int));
			}
			SETCADDDR(stateInfoSXP,initialStateSXP);
			UNPROTECT(1);
		}
	}
	else
	{
		stateInfoSXP = R_NilValue;
	}

	// assign to result list
	SETCAR(resSXP,stateInfoSXP);

	if (res->tableSize != 0 && _returnTable)
		UNPROTECT(1);

	// count attractors
	unsigned int numAttractors = 0;
	pAttractor el;

	for(el = res->attractorList; el->next != NULL; el = el->next)
		++numAttractors;

	// write attractors
	SEXP attractorsSXP;
	PROTECT(attractorsSXP = allocList(numAttractors));
	SEXP listPos = attractorsSXP;
	for(el = res->attractorList, i=0; el->next != NULL; el = el->next, ++i)
	{
		SEXP attractorSXP;
		// each attractor is a 2-element list with a list of states included
		// in the attractor and the size of the basin
		if (el->transitionTableSize == 0)
			PROTECT(attractorSXP = allocList(2));
		else
			PROTECT(attractorSXP = allocList(4));
		SET_TAG(attractorSXP, install("involvedStates"));
		SET_TAG(CDR(attractorSXP), install("basinSize"));

		if (el->transitionTableSize != 0)
		{
			SET_TAG(CDR(CDR(attractorSXP)), install("initialStates"));
			SET_TAG(CDR(CDR(CDR(attractorSXP))), install("nextStates"));
		}

		SEXP stateSXP;
		PROTECT(stateSXP = allocVector(INTSXP,el->length * el->numElementsPerEntry));
		array = INTEGER(stateSXP);
		for (i = 0; i < el->length; ++i)
		{
				if (_networkType == SYNC_MODE)
					// insert fixed gene values, as they are missing in the calculated results
					insertFixedGenes(&el->involvedStates[i*el->numElementsPerEntry],network.fixedGenes,network.numGenes);
				
				memcpy(&array[i*el->numElementsPerEntry],
					  &el->involvedStates[i*el->numElementsPerEntry],el->numElementsPerEntry*sizeof(unsigned int));
					  
		}
		SETCAR(attractorSXP,stateSXP);

		// write basin size
		SEXP basinSXP;
		PROTECT(basinSXP = allocVector(INTSXP,1));
		array = INTEGER(basinSXP);
		array[0] = el->basinSize;
		SETCADR(attractorSXP,basinSXP);
		SETCAR(listPos,attractorSXP);
		if (el->next != NULL)
			listPos = CDR(listPos);

		if (el->transitionTableSize != 0)
		{
			SEXP attrInitialStateSXP;
			SEXP attrNextStateSXP;
			PROTECT(attrInitialStateSXP = allocVector(INTSXP,el->numElementsPerEntry * el->transitionTableSize));
			PROTECT(attrNextStateSXP = allocVector(INTSXP,el->numElementsPerEntry * el->transitionTableSize));
			unsigned int * initial = (unsigned int*)INTEGER(attrInitialStateSXP);
			unsigned int * next = (unsigned int*)INTEGER(attrNextStateSXP);

			TransitionTableEntry * currentState = el->table;
			for (i = 0; i < el->transitionTableSize; ++i)
			{
				memcpy(&initial[i * el->numElementsPerEntry],currentState->initialState,
					   sizeof(unsigned int) * el->numElementsPerEntry);
				memcpy(&next[i * el->numElementsPerEntry],currentState->nextState,
					   sizeof(unsigned int) * el->numElementsPerEntry);
				currentState = currentState->next;
			}
			SETCADDR(attractorSXP,attrInitialStateSXP);
			SETCADDDR(attractorSXP,attrNextStateSXP);
			UNPROTECT(2);
		}

		UNPROTECT(3);
	}
	UNPROTECT(1);
	SETCADR(resSXP,attractorsSXP);

  PutRNGstate();
	UNPROTECT(1);

	// free resources
	freeAttractorInfo(res);
	free(network.nonFixedGeneBits);

	return(resSXP);
}
back to top