The project ‘nxnes’ (NxN Equalisations Solver) is the implementation of project 5 from the list of selected projects in the course “Operating Systems II – Laboratory” (Department of Informatics and Communications, T.E.I. of Central Macedonia). The objective of this project was the implementation of the Gauss Elimination Method to solve a NxN system of linear equations.

## Tag Archive: algorithm

The project “PGASystem” (Parallel Genetic Algorithms System) is an under development system based on the client / server architecture and can be used to implement and study of parallel genetic algorithms.

The following function is applied onto a graph and it specifically implements the method of breadth-first search. To visit all nodes connected to node k of a graph, we put the k in a FIFO queue and then go into a loop, during which we get the next node from the queue and, if we have not already visited it, we visit it and push into the queue all nodes belonging to the adjacency list of this node, continuing this process until we empty the queue.

The following program creates the syntax tree of a mathematical expression in prefix notation. For simplicity, we assume that the terms of the expression are individual characters (digits). Each time the recursive function parse() is called, a new node is created, whose value is the next character of the expression. If the value is a term (digit), we return the new node. However, if it is an operator, we set the left and right pointers to point the tree made (recursively) for the two operands.

The iterative (non-recursive) function preorderTreeTraverse() can perform preorder traversing of a binary tree with the help of a stack that can hold pointers to nodes of the tree.

Also, the iterative (non-recursive) function layerTreeTraverse() can perform level-order traversing of a binary tree with the help of a queue that can hold pointers to nodes of the tree.

To calculate a prefix expression, we either convert a number from ASCII to decimal (in the loop ‘while’ at the end of the program) or implement the operation indicated by the first character of the expressions to the two terms, with a recursive calculation. This function is recursive, but it uses a global array containing the expression and an index number for the current character of the expression. The index number goes beyond each sub-expression calculated.

The elegant recursive solution to a problem is most of the times invaluable. Although the iterative solution of that problem is likely to have a better space and time complexity, it is often preferred to use the recursive version for clarity and simplicity. It is remarkable how easily a problem can be solved by use of a recursive manner. In this article we will try to record a collection of useful recursive functions:

The following program converts an expression from infix to postfix notation. The conversion is carried out with the help of a stack. For example, to turn the expression (A + B) into the postfix form A B +, we ignore the left parenthesis, convert the A to postfix form, we store the + operator on the stack, we convert B to postfix form and then, when find the right parenthesis, we pop the + operator from the top of the stack. In particular, the following implementation works only for the addition and multiplication of integers.

The following program reads any postfix expression that includes integer multiplication and addition, evaluates the expression and displays the final result on the screen. The program stores the intermediate results in a stack of integers.

The terms (operands) are pushed onto the stack. The operators are applied to the two entries at the top of the stack (the two entries are popped from the stack); the result is pushed back into the stack. Because the order in which the two pop() functions are performed in the expression of this code is not specified in C++, the code for some non-commutative operators, such as the ones for subtraction and division, would be somewhat more complicated.

The following program demonstrates a significant processing operation on arrays of strings. More precisely, we present the re-sorting of a set of strings in order to classify them. So, we read the strings and place them in a temporary storage area (buffer) large enough to be able to store all, keeping in an array a pointer to each string. Then we re-sort the pointers (only pointers and not strings to increase the performance) to place the pointer to the “smallest” string at the first position of the array, the pointer to the next “largest” string at the second position of the array, and so on.

The following program reads a set of edges that define a graph and creates a representation of this graph with an adjacency list. The adjacency list of a graph is an array of lists, one for each vertex, where the j-th list contains a linked list of the nodes which are connected with the j-th vertex.

The following program reads a set of edges that define an undirected graph and creates a representation of this graph with an adjacency matrix, giving a[i][j] and a[j][i] the value of 1 if there is an edge from i to j or from j to i in the graph, or the value of 0 if it does not exist. Also, we assume that the number of vertices V is a constant known at compilation time. Otherwise, there should be dynamic memory allocation for the array that represents the adjacency matrix.

The following program finds all the occurrences of a word in a text string. We set the text string as an array of characters of fixed size (although we could, instead, use the operator ‘new’) and read it from the standard input using the function cin.get(). The memory allocation for the word entered in the command line and passed on as argument is done by the system before this program is called and we find the pointer to the string in argv[1]. For every starting position i in the array a, tries to associate the substring starting from this position with the p, checking character by character for equality. Each time we reach the end of p successfully, we display the starting position (i) of the word in the text on the screen.

**Taxonomy**

The Ant Colony System algorithm is an example of an Ant Colony Optimization method from the field of Swarm Intelligence, Metaheuristics and Computational Intelligence. Ant Colony System is an extension to the Ant System algorithm and is related to other Ant Colony Optimization methods such as Elite Ant System, and Rank-based Ant System.

**Taxonomy**

The Cultural Algorithm is an extension to the field of Evolutionary Computation and may be considered a Meta-Evolutionary Algorithm. It more broadly belongs to the field of Computational Intelligence and Metaheuristics. It is related to other high-order extensions of Evolutionary Computation such as the Memetic Algorithm.

**Taxonomy**

Harmony Search belongs to the fields of Computational Intelligence and Metaheuristics.

**Taxonomy**

Simulated Annealing is a global optimization algorithm that belongs to the field of Stochastic Optimization and Metaheuristics. Simulated Annealing is an adaptation of the Metropolis-Hastings Monte Carlo algorithm and is used in function optimization. Like the Genetic Algorithm, it provides a basis for a large variety of extensions and specialization’s of the general method not limited to Parallel Simulated Annealing, Fast Simulated Annealing, and Adaptive Simulated Annealing.

**Taxonomy**

Memetic Algorithms have elements of Metaheuristics and Computational Intelligence. Although they have principles of Evolutionary Algorithms, they may not strictly be considered an Evolutionary Technique. Memetic Algorithms have functional similarities to Baldwinian Evolutionary Algorithms, Lamarckian Evolutionary Algorithms, Hybrid Evolutionary Algorithms, and Cultural Algorithms. Using ideas of memes and Memetic Algorithms in optimization may be referred to as Memetic Computing.

I quote below a personal portable implementation (in C++) of a classic Differential Evolution algorithm used to maximize the function **f(x) = sin(x)** in the domain 0 <= x <= 2pi. You can compile the program with the g++ compiler.

I quote below a personal portable implementation (in C++) of a classic genetic algorithm (evolutionary algorithm) used to maximize the function **f(x, y) = sin(x) * sin(y)** in the domain 0 <= x, y <= 2pi. You can compile the program with the g++ compiler.

I quote below a personal portable implementation (in C++) of a classic genetic algorithm (evolutionary algorithm) used to maximize the function **f(x) = sin(x)** in the domain 0 <= x <= 2pi. You can compile the program with the g++ compiler.

I quote below a personal portable implementation (in C++) of a classic genetic algorithm (evolutionary algorithm) used to maximize the function **f(x) = sin(x)** in the domain 0 <= x <= 2pi. You can compile the program with the g++ compiler.

I quote below a personal portable implementation (in C++) of a classic genetic algorithm (evolutionary algorithm) used to maximize the function **f(x) = sin(x)** in the domain 0 <= x <= 2pi. You can compile the program with the g++ compiler.

**Taxonomy**

The Artificial Immune Recognition System belongs to the field of Artificial Immune Systems, and more broadly to the field of Computational Intelligence. It was extended early to the canonical version called the Artificial Immune Recognition System 2 (AIRS2) and provides the basis for extensions such as the Parallel Artificial Immune Recognition System [Watkins2004]. It is related to other Artificial Immune System algorithms such as the Dendritic Cell Algorithm, the Clonal Selection Algorithm, and the Negative Selection Algorithm.

**Taxonomy**

The Self-Organizing Map algorithm belongs to the field of Artificial Neural Networks and Neural Computation. More broadly it belongs to the field of Computational Intelligence. The Self-Organizing Map is an unsupervised neural network that uses a competitive (winner-take-all) learning strategy. It is related to other unsupervised neural networks such as the Adaptive Resonance Theory (ART) method. It is related to other competitive learning neural networks such as the the Neural Gas Algorithm, and the Learning Vector Quantization algorithm, which is a similar algorithm for classification without connections between the neurons. Additionally, SOM is a baseline technique that has inspired many variations and extensions, not limited to the Adaptive-Subspace Self-Organizing Map (ASSOM).

**Taxonomy**

The Genetic Algorithm is an Adaptive Strategy and a Global Optimization technique. It is an Evolutionary Algorithm and belongs to the broader study of Evolutionary Computation. The Genetic Algorithm is a sibling of other Evolutionary Algorithms such as Genetic Programming, Evolution Strategies, Evolutionary Programming, and Learning Classifier Systems. The Genetic Algorithm is a parent of a large number of variant techniques and sub-fields too numerous to list.

**Taxonomy**

Iterated Local Search is a Metaheuristic and a Global Optimization technique. It is an extension of Multi Start Search and may be considered a parent of many two-phase search approaches such as the Greedy Randomized Adaptive Search Procedure and Variable Neighborhood Search.

**Taxonomy**

Random search belongs to the fields of Stochastic Optimization and Global Optimization. Random search is a direct search method as it does not require derivatives to search a continuous domain. This base approach is related to techniques that provide small improvements such as Directed Random Search, and Adaptive Random Search.

**Taxonomy**

The Adaptive Random Search algorithm belongs to the general set of approaches known as Stochastic Optimization and Global Optimization. It is a direct search method in that it does not require derivatives to navigate the search space. Adaptive Random Search is an extension of the Random Search and Localized Random Search algorithms.

**Taxonomy**

The Stochastic Hill Climbing algorithm is a Stochastic Optimization algorithm and is a Local Optimization algorithm (contrasted to Global Optimization). It is a direct search technique, as it does not require derivatives of the search space. Stochastic Hill Climbing is an extension of deterministic hill climbing algorithms such as Simple Hill Climbing (first-best neighbor), Steepest-Ascent Hill Climbing (best neighbor), and a parent of approaches such as Parallel Hill Climbing and Random-Restart Hill Climbing.

The following program generates N random integers between 0 and 999, creates a linked list inserting a number in each node and then rearranges the nodes of the list so that the numbers appear sorted when we go through the list. For the sorting, it maintains two lists: one input list (not sorted) and one output list (sorted). In each iteration of the loop, it removes a node from the input list and enters it in the appropriate position in the output list. The code is simplified by using head nodes for each list, which contains links to the first node lists. Also, both lists (input and output) are printed.

This program demonstrates the use of an array and is representative of the usual situation in which we store data in one array to process them later. It counts the number of pairs of N randomly generated points of the unit square, which can be connected to a line segment of length less than ‘d’, using the point data type. Because the execution time of this program is O(n^{2}), it can’t be used for large N.

The function ‘reverse’ in the following example reverses the links in a list, returning a pointer to the end node, which then shows the next of the last node, and so forth, while the link to the first node of the initial list is assigned the value 0 corresponding to null pointer (in C++). To accomplish this task, we must maintain links to three consecutive nodes in the list.

For the representation of individuals arranged in a circle, we create a circular linked list with a combination of each person to the person on his left in the circle. The integer i represents the i-th person in the circle. After you create a circular list of one node for 1, we insert its unique node to nodes 2 to N. We end up with a cycle from 1 to N, with x indicating the node N. Then, starting from 1 we omit M-1 nodes, we define the pointer of the (M-1)-th node to omit the M-th, and continue that way until only one node remains in the list.

The aim of this program is to assign to a[i] the value 1 if i is a prime number and the value 0 if not. Initially, all elements of the array take the value 1 to indicate that there are no numbers which are known not to be prime. Then all elements of the array corresponding to indexes that are known not to be primes (multiples of known primes) take the value 0. If a[i] has the value 1 even after all multiples of smaller primes have taken the value 0, we know that i is a prime number.

The program generally simulates a Bernoulli trials sequence, a familiar and abstract notion of probability theory. So, if you flip a coin N times, we expect “head” to occur N/2 times – but it could occur anything between 0 and N times. The program performs the experiment M times, reading the N and M from the command line. It uses an array ‘f’ to count the frequency with which the result “i heads” appears for 0 <= i <= N, and then displays a histogram of the results of experiments with an asterisk for every 10 appearances. Also, the operation behind the program – of indexing an array with a calculated value – is critical to the effectiveness of many computational procedures.

**Sequential Search.**

This algorithm checks whether the number ‘v’ is contained in a set of numbers already stored in the data a[0], a[1], …, a[r-1] of the array ‘a’ (where ‘r’ the number of elements in it), comparing it sequentially with all numbers, starting from the beginning. If the check reaches the end without finding the number, the value -1 is returned. Otherwise, we are returned the index of the position of the one-dimensional array containing the number.

If we replace the loops ‘for’ of the simple version of weighted quick-union (you’ll find it in a previous article) with the following code, we reduce the length of each route passing to the half. The end result of this change is that after a long sequence of operations the trees end up almost level.

This program reads from the standard input a sequence of pairs of non-negative integers which are less than N (interpreting the pair [p q] as a “link of the object p to object q”) and displays the pairs that represent those objects which are not yet connected. The program complies with the array ‘id’ to include an entry for each object and applies that id[q] and id[p] are equal if and only if p and q are connected.

If we replace the body of the while loop of the quick-find algorithm (you can find it in a previous article) with the following code we have a program that meets the same specifications as the quick-find algorithm but performs fewer calculations for the act of union, to the expense of more calculations for act of finding. The ‘for’ loop and the ‘if’ operation that follows in this code determine the necessary and sufficient conditions in the array ‘id’ that p and q be linked. The act of union is implemented by the assignment id[i] = j.

This program is a modification of the simple quick-union algorithm (you’ll find it in a previous article). It uses an extra array ‘sz’ to store the number of nodes for each object with id[i] == i in the corresponding “tree”, so the act of union to be able to connect the smaller of the two specified “trees” with the largest, and thus avoid the formation of large paths in “trees”.

The presence of errors in software development (and not only) is inevitable. However, over time the programs improve and tend to perfection through various techniques and methods we have developed.

The deterministic problems are easy to spot because they always lead to the same error. There are tools that run through the source code of an application to find possible deterministic errors (these tools are especially useful in applications written with scripting languages such as Python, Bash Scripting, etc).

Within the framework of the course “Numerical Methods in Programming Environments – Theory” (Department of Informatics and Communications, T.E.I. of Central Macedonia) we were asked to develop an optional program that implements Müller’s numerical method for finding the root of equations of the form f(x) = 0.