LO27/report.md

8.6 KiB

% Cellular Automaton LO27 % Bartuccio Antoine \cr Porée De Ridder Jean % Autumn 2016

\newpage

Introduction

The goal of this project is to provide a library containing a new abstract data type called Matrix with associated function to manipulate them. The final program have to enable a user to test the library in an interactive and practical way.

Since we decided to not store false value \footnote{cellElement does not contains values anymore, their existence is their value}in our matrix and to not store the colElement and rowElement \footnote{they are unified and renamed as listElement}that are empty, we decided not to worry too much about performances and we encapsulated all access to stored data in the Matrix structure to avoid too much complexity and allow more modularity, readability and re-usability. We created high level tools to manipulate our matrix and used it all along the project.

For compilation we didn't used the -ansi flag since we had to deal with both clang and gcc for compilation and clang didn't accept this flag. Instead, we used the -std=c89 flag witch contains the same rules but is accepted on both softwares. Compiling with -ansi still works.

We decided to create two different library. One for the graphical interface (which require SDL2) and the other with the Matrix data type) so this way you may just have to compile one lib if you don't need the gui.

Description of abstract data types

Every function and data type are described in the documentation given with the project. This documentation is generated with doxygen.

Algorithmic

The most interesting function are getCellValue and setCellValue. Those are the one we rely on the most. They are our way of dealing with our complex data structure allowing us to avoid to store false values. They are the functions that need the more computational power on the long run but are really useful due to their level of abstraction and their high level.

getCellValue is a simple function based on findMatrixElem :

getCellValue(matrix:Matrix, ColPos:integer , RowPos:integer ) : bool
BEGIN
	if ( colCount(matrix) <= ColPos OR rowCount(matrix) <= RowPos)
		getCellValue <- ERROR
	endif

	if (findMatrixElem( matrix , ColPos , RowPos ) = NULL)
		getCellValue <- false
	endif

	getCellValue <- true
END

findMatrixElem( matrix:Matrix , ColPos:integer, RowPos:integer ) : *cellElement
BEGIN	
	Row:ListElement <- NULL
	elem:*cellElement <- NULL

	Row <- getElementPos(rows(matrix),RowPos)
	if (Row = NULL)
		findMatrixElem <- NULL
	endif

	elem <- data(Row)

	while (elem != NULL AND colIndex(elem) != ColPos)
		elem <- nextCol(elem)
	endwhile

	findMatrixElem <- elem
END

setCellValue is a simple function based on createMatrixElem and deleteMatrixElement :

setCellValue(matrix:Matrix, ColPos:integer, RowPos:integer,value:bool):bool
BEGIN
	if (value = true)
		setCellValue <- createMatrixElem(matrix,ColPos,RowPos)
	else
		if ( deleteMatrixElem(matrix,ColPos,RowPos) >= 0 )
			setCellValue <- true
		else
			setCellValue <- false
		endif
	endif
END

createMatrixElem( matrix:Matrix, ColPos:integer, RowPos:integer):bool
	Row:*ListElement <-NULL
	Col:*Listelemnt <- NULL

	error:integer <- 0
	
	elem: *cellElement <- NULL
	tmp: *cellElement<- NULL

	if (colCount(matrix) <= ColPos OR rowCount(matrix) <= RowPos )
		createMatrixElem <- ERROR /* out of bounds */
	endif

	elem <- createCellElem()
	setPositionIndex(elem,ColPos,RowPos)

	Row <- getElementPos(rows(matrix),RowPos)
	if (Row != NULL AND data(Row) != NULL)

		if (colIndex(data(Row)) = ColPos)
			error ++ /* the element already exists */
		else 
			if (colIndex(data(Row)) > ColPos)
				nextCol(elem) <- data(Row)
				data(Row) <- elem
			endif
		else 
			tmp <- data(Row)
			/* searching the previous element */
			while ( nextCol(tmp) != NULL AND nextCol(colIndex(tmp)) < ColPos) do
				tmp <- nextCol(tmp)
			endwhile

			if ( nextCol(tmp) = NULL OR colIndex(nextCol(tmp)) > ColPos)
				nextCol(elem) <- nextCol(tmp)
				nextCol(tmp) <- elem
			else 
				error ++ /* the element already exists */
			endif
		endif

	else 
		/* if the list is empty */
		push(rows(matrix),elem)
		pos(tail(rows(matrix))) <- RowPos
	endif

	Col <- getElementPos(cols(matrix),ColPos)
	if (Col != NULL AND data(Col) != NULL)

		if (rowIndex(data(Col)) = RowPos)
			error ++ /* the element already exists */
		else 
			if (rowIndex(data(Col)) > RowPos)
				nextRow(elem) <- data(Col)
				data(Col) <- elem
			endif
		else 
			tmp <- data(Col)
			/* searching the previous element */
			while (nextRow(tmp) != NULL AND rowIndex(nextRow(tmp)) < RowPos) do
				tmp <- nextRow(tmp)
			endwhile

			if (nextRow(tmp) = NULL OR rowIndex(nextRow(tmp)) > RowPos)
				nexRow(elem) <- nextRow(tmp)
				newRow(tmp) <- elem
			else 
				error ++ /* the element already exists */
			endif
		endif

	else 
		/* if the list is empty */
		push(cols(matrix),elem)
		pos(tail(cols(matrix))) <- ColPos
	endif


	if (error != 0)
		/* if the element already exists, free it */
		freeCellElement(elem)
		createMatrixElem <- true
	else
		createMatrixElem <- false
	endif

END

deleteMatrixElem(matrix:Matrix,ColPos:integer, RowPos:integer ):integer
BEGIN
	elem : *cellElement <- NULL
	tmp  : *cellElement <- NULL

	Row  : *ListElement <- NULL
	Col  : *ListElement <- NULL

	elem <- findMatrixElem(matrix,ColPos,RowPos)
	if (elem = NULL)
		/* if the element does not exists */
		deleteMatrixElem <- 0
	endif

	Row <- getElementPos(rows(matrix),RowPos)
	if (Row = NULL)
		/* this shouldn't happend */
		deleteMatrixElem <- -1
	endif

	if (data(Row) = NULL)
		/* this shouldn't happend too */
		removeElementPos(rows(matrix),RowPos)
		deleteMatrixElem <- -1
	endif

	if (colIndex(data(Row)) = ColPos)
		/* the element is the first element */
		data(Row) <- nextCol(elem)
	else 
		tmp <- data(Row)
		/* finding prefious element */
		while (nextCol(tmp) != NULL AND nextCol(tmp) != elem) do
			tmp <- nextCol(tmp)
		endwhile

		if (nextCol(tmp) != NULL)
			/* linking correctly the previous element */
			nextCol(tmp) <- nextCol(elem)
		endif
	
	endif

	if (data(Row) = NULL)
		/* if the row is empty now we delete it to save memory */
		removeElementPos(rows(matrix),RowPos)
	endif


	Col <- getElementPos(cols(matrix),ColPos)
	if (Col = NULL)
		/* this shouldn't happend */
		deleteMatrixElem <- -2
	endif

	if (data(Col) = NULL)
		/* this shouldn't happend too */
		removeElementPos(cols(matrix),ColPos)
		deleteMatrixElem <- -1
	endif

	if (rowIndex(data(Col)) = RowPos)
		/* the element is the first element */
		data(Col) <- nextRow(elem)
	else
		tmp <- data(Col)
		/* finding prefious element */
		while (nextRow(tmp) != NULL AND nextRow(tmp) != elem) do
			tmp <- nextRow(tmp)
		endwhile

		if (nextRow(tmp) != NULL)
			/* linking correctly the previous element */
			nextRow(tmp) <- nextRow(elem)
		endif

	endif

	if (data(Col) = NULL)
		/* if the col is empty now we delete it to save memory */
		removeElementPos(cols(matrix),ColPos)
	endif

	freeCellElement(elem)
	deleteMatrixElem <- 1

END

Functions andColSequenceOnMatrix and orColSequenceOnMatrix are implemented with colSequenceOnMatrix and are really not interesting so we're gonna provide the algorithm of the last one :


This is the same thing for andRowSequenceOnMatrix and orRowSequenceOnMatrix :

colSequenceOnMatrix(m:Matrix, operator:(function(bool, bool):bool)): Matrix
BEGIN
	a:integer
	b:integer
	i:integer
	j:integer
	newM:Matrix <- createMatrix()

	rowCount(newM) <- rowCount(m)
	if (colCount(m) <= 1) then
		colCount(newM) <- 0
		colSequenceOnMatrix <- newM
	endif
	colCount(newM) <- colCount(m) - 1

	for i from 0 to colCount(m) - 2 do
		for j from 0 to rowCount(m) - 2 do
			a <- getCellValue(m, i, j)
			b <- getCellValue(m, i + 1, j)
			if operator(a, b) then
				setCellValue(newM, i, j, true)
			endif
		endfor
	endfor
	colSequenceOnMatrix <- newM
END

Here are the algorithm of the function applyRules and all the one related to it :

applyRules ( matrix:Matrix, Rules:integer, N:integer):Matrix
BEGIN
	RulesMatrix :integer[9] /* the size is the number of fundamental rules */
	i:integer <- 0
	power:integer <- 2
	sum:integer <- 0
	j:integer <- 0

	tempMatrix1:Matrix
	tempMatrix2:Matrix

	if (Rules <= 0 OR N < 1)
		applyRules <- matrix
	endif

	/* decompotition of the rule in basic rules */ 
	while(power <= 512) do

		RulesMatrix[i] <- Rules%power - sum
		sum <- Rules%power

		if (RulesMatrix[i]!=0)
			i++
		endif

		power <- power*2

	endwhile

	/* application of the rule */

	tempMatrix1 <- matrixFromRules(matrix, i, RulesMatrix)

	for j from 0 to N do
		tempMatrix2 <- matrixFromRules(tempMatrix1 ,i, RulesMatrix)
		freeMatrix(tempMatrix1)

		tempMatrix1 <- tempMatrix2
	endfor

	applyRules <- tempMatrix1

END

Conclusion