First threads in array of threads getting skipped in c (sometimes)? - c

I am trying to write a multithreaded program in C that sorts an array by breaking it up into partitions, and then each thread works on it's own partition. The problem seems to be that sometimes Thread 1, and sometimes Thread 2, get skipped in execution. I haven't even gotten to the sorting, just the comparison. For now i just want to know my threads are running correctly, but it seems the first ones can just not get scheduled or something. I am not very strong with C, and am really racking my brain for what can be going wrong.
I know each thread can be paused by the scheduler, but they all should eventually get completed right? So why does my first couple threads sometimes not run?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 11
#define HM_SORTERS 4
void * sort(void * param);
void printArr(int * arr);
struct PartitionBounds {
int tid;
size_t start;
size_t end;
};
int array[SIZE] = {18, 12, 68, 59, 75, 73, 68, 4, 16, 94, 15};
int main() {
// srand(time(NULL));
// for (size_t i = 0; i < SIZE; i++) {
// array[i] = rand() % 100;
// }
printArr(array);
pthread_t sorters[HM_SORTERS];
for(int i=0;i<HM_SORTERS;i++) {
struct PartitionBounds bounds;
size_t coverage = SIZE / HM_SORTERS;
bounds.tid = i;
bounds.start = i * coverage;
bounds.end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds.start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
if(status == 0) {
printf("\n--- Thread %d created successfully ---\n", i + 1);
printf("start: %zu, end: %zu\n", bounds.start, bounds.end);
} else {
printf("!!! Failed to create thread !!!\n");
return 0;
}
}
for(int i=0;i<HM_SORTERS;i++) {
pthread_join(sorters[i], NULL);
}
printf("\n\n----- Sorting completed -----\n\n");
return 0;
}
void * sort(void * param) {
struct PartitionBounds *bounds = param;
printf("\n\tin thread %d\n\n", bounds->tid + 1);
for(size_t i=bounds->start;i<=bounds->end;i++) {
for(size_t j=i+1;j<=bounds->end;j++) {
if(array[j] < array[i]) {
printf("Thread %d: %d is smaller than %d\n", bounds->tid + 1, array[j], array[i]);
}
}
}
pthread_exit(NULL);
}
void printArr(int * arr) {
int coverage = SIZE / HM_SORTERS;
for(int i=0;i<HM_SORTERS;i++) {
size_t partitionEnd = i + 1 == HM_SORTERS ? coverage + SIZE % HM_SORTERS : coverage;
for(int j=0;j<partitionEnd;j++) {
printf("%d", array[j + coverage * i]);
if(j+1 < partitionEnd) {
printf(", ");
}
}
if(i+1 < HM_SORTERS) {
printf(" | ");
}
}
printf("\n");
}
output: (typical, when threads get skipped)
18, 12 | 68, 59 | 75, 73 | 68, 4, 16, 94, 15
--- Thread 1 created successfully ---
start: 0, end: 1
--- Thread 2 created successfully ---
start: 2, end: 3
in thread 1
--- Thread 3 created successfully ---
Thread 3: 73 is smaller than 75
in thread 3
Thread 3: 73 is smaller than 75
in thread 2
start: 4, end: 5
Thread 3: 73 is smaller than 75
Thread 4: 68 is smaller than 75
Thread 4: 4 is smaller than 75
Thread 4: 16 is smaller than 75
Thread 4: 15 is smaller than 75
--- Thread 4 created successfully ---
start: 6, end: 10
Thread 4: 68 is smaller than 73
Thread 4: 4 is smaller than 73
Thread 4: 16 is smaller than 73
Thread 4: 15 is smaller than 73
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
in thread 4
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
----- Sorting completed -----

One problem I do see here is, referring the address of local variable.
struct PartitionBounds bounds;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
bounds is local variable and it will be vanished and new instance will be created on each iteration. Thus referring to it in sort function will have undefined behavior.
What you can do is, dynamically allocate the memory.
struct PartionBounds *bounds = malloc(sizeof(*bounds));
int status = pthread_create(&sorters[i], NULL, sort, bounds);
Make sure you free the memory once done.

An alternative solution without using malloc/free .
struct PartitionBounds bounds[HM_SORTERS];
...
size_t coverage = SIZE / HM_SORTERS;
bounds[i].tid = i;
bounds[i].start = i * coverage;
bounds[i].end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds[i].start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds[i]);
...

Related

Rearrange Matrix using threads

I`m trying to do this program, that taking matrix 4X4, and then creating 4 threads, and in parallel inserting the 4X4 matrix into array of 16 integer, sorting like this. odd number will go to odd index, and even number to even index in the array.
2 1 10 9 4 ec`
for example
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
will looks something like this:
The arranged array:
2 1 10 9 4 3 12 11 6 5 14 13 8 7 16 15
Num 2 was found by thread 0
Num 1 was found by thread 2
Num 10 was found by thread 1
Num 9 was found by thread 3
Num 4 was found by thread 0
Num 3 was found by thread 2
Num 12 was found by thread 1
Num 11 was found by thread 3
Num 6 was found by thread 0
Num 5 was found by thread 2
Num 14 was found by thread 1
Num 13 was found by thread 3
Num 8 was found by thread 0
Num 7 was found by thread 2
Num 16 was found by thread 1
Num 15 was found by thread 3
Now I came up with this code, but for some reason I'm not using all the threads like in the sample. I mean in the sample there is thread 0 then 2 then 1 then 3 etc. very mixed. I'm from other hand getting thread 0, thread 0, thread 0, 3, 3 ,0,0 etc.
How can I fix this?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX 4
#define MAX_THREAD 4
int i = 0;
int newmatrix[16];
int oldmatrix[MAX][MAX] =
{1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16};
int isUsed(int num)
{
for (int p = 0; p < 16; p++)
if (newmatrix[p] == num)
return 0;
return 1;
}
void *printHello(void *threadid)
{
int j, k;
long tid;
tid = (long)threadid;
while (i < 16)
{
sleep(0.01);
for (j = 0; j < 4; j++)
{
for (k = 0; k < 4; k++)
{
if (oldmatrix[j][k] % 2 == 0 && isUsed(oldmatrix[j][k]))
{
newmatrix[i] = oldmatrix[j][k];
printf("Num %d was found by thread %ld\n", oldmatrix[j][k], tid);
i++;
}
else if (isUsed(oldmatrix[j][k]))
{
newmatrix[i] = oldmatrix[j][k];
printf("Num %d was found by thread %ld\n", oldmatrix[j][k], tid);
i++;
}
}
}
}
if (tid == 1)
{
sleep(2);
printf("Hello There! thread %ld \n\n", tid);
for (int p = 0; p < 16; p++)
printf("%d ", newmatrix[p]);
}
pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{
pthread_t threads[MAX_THREAD];
int rc;
long t;
for (t = 0; t < MAX_THREAD; t++)
{
rc = pthread_create(&threads[t], NULL, printHello, (void *)t);
if (rc)
{
printf("ERORR; return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
}
pthread_exit(NULL);
}

reading and printing matrix from stdin

Well I posted this before but it's kinda improved now, and I only have one problem (I guess).
The assignment was to write a function which reads an integer matrix given in a ‘.txt file’ using
I/O redirection, then write another function to print it.
I read txt into a 1D array (arr) then create 2D matrix (mat) out of it, before those, I allocated memory dynamically bc our professor asked to do it that way. The problem is that arr seems to be changing when I put it on for loop and try to address it for the matrix. I would appreciate any ideas... Also, it would be helpful if you guys can comment on my way of allocating memory. (Don't forget we have 3 different input.txts some of them has -5.58234 like values or they are not seperated by "," in this example, so I want to make my code usable in any cases)
example txt file:
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int readMatrix(int *arr, int **mat);
void printMatrix(int **mat, int size);
int main(){
// declare 1D array and allocate memory
int *arr;
arr = malloc(sizeof(stdin)*sizeof(int));
// declare 2D Matrix and allocate memory
int **mat;
mat = (int **)malloc(sizeof(stdin)*sizeof(int));
// function implementations
int size;
size = readMatrix(arr, mat);
printMatrix(mat,size);
return 0;
}
int readMatrix(int *arr, int **mat){
// reading
int i=0, size=0; // loop var i and size to count the elements of array
while(scanf("%d,", &arr[i]) != EOF)
{
i++;
size++;
}
printf("arr[63] = %d \n\n",arr[63]); // VALUE IS CORRECT HERE
// finding row and column numbers
int rows = sqrt(size), cols = rows;
// appending 1d array into matrix
int m = 0;
// test printf("rows = %d, cols = %d\n", rows, cols);
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
printf("arr[%d] = %d\n",m, arr[m]); // VALUES OF arr[] BECAME WEIRD AFTER arr[12]
//mat[i][j] = arr[m]; // segmentation fault
//*(*(mat+i)+j) = arr[m]; // segmentation fault
//*(*(mat+i)+j) = &arr[m]; // segmentation fault
*(mat + i*cols + j) = &arr[m]; // I don't know if this is the proper way but it works
m++;
}
}
printf("\narr[63] = %d\n",arr[63]); // HOWWWWW
// return size for further implementations
//
return size;
}
void printMatrix(int **mat, int size){
int rows = sqrt(size), cols = rows;
printf("\nMATRIX A:\n");
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++)
{
printf("%d ", mat[i][j]);
//if(mat[i][j]>=10 && mat[i][j]<100 ){printf("%d ", mat[i][j]);}
//else if(mat[i][j]>=100 ){printf("%d ", mat[i][j]);}
//else{printf("%d ", mat[i][j]);}
}
printf("\n");
}
}
output:
$ ./secondtry < input1.txt
arr[63] = 99
arr[0] = 16
arr[1] = 11
arr[2] = 10
arr[3] = 16
arr[4] = 24
arr[5] = 40
arr[6] = 51
arr[7] = 61
arr[8] = 12
arr[9] = 12
arr[10] = 14
arr[11] = 19
arr[12] = 976
arr[13] = 8
arr[14] = 980
arr[15] = 8
arr[16] = 984
arr[17] = 8
arr[18] = 988
arr[19] = 8
arr[20] = 992
arr[21] = 8
arr[22] = 996
arr[23] = 8
arr[24] = 1000
arr[25] = 8
arr[26] = 1004
arr[27] = 8
arr[28] = 1008
arr[29] = 8
arr[30] = 1012
arr[31] = 8
arr[32] = 1016
arr[33] = 8
arr[34] = 1020
arr[35] = 8
arr[36] = 1024
arr[37] = 8
arr[38] = 1028
arr[39] = 8
arr[40] = 1032
arr[41] = 8
arr[42] = 1036
arr[43] = 8
arr[44] = 1040
arr[45] = 8
arr[46] = 1044
arr[47] = 8
arr[48] = 1048
arr[49] = 8
arr[50] = 1052
arr[51] = 8
arr[52] = 1056
arr[53] = 8
arr[54] = 1060
arr[55] = 8
arr[56] = 1064
arr[57] = 8
arr[58] = 1068
arr[59] = 8
arr[60] = 1072
arr[61] = 8
arr[62] = 1076
arr[63] = 8
arr[63] = 8
MATRIX A:
16 11 10 16 24 40 51 61
11 10 16 24 40 51 61 12
10 16 24 40 51 61 12 12
16 24 40 51 61 12 12 14
24 40 51 61 12 12 14 19
40 51 61 12 12 14 19 976
51 61 12 12 14 19 976 8
61 12 12 14 19 976 8 980
Because we're reading from stdin, we can not do simple things like:
read/parse the first to determine number of columns
rewind file
read/parse all lines and store in matrix (allocating space as we go)
Note that using sqrt on the count to get number of rows/columns is a bit "unique". This is the first time I've seen that done.
When handling a 2D matrix that has dynamic dimensions, it helps to define a control struct to be able to store the dimensions. Then, all relevant info for the matrix is available to everyone.
In general, I really prefer fgets/strtok/strtol over scanf.
In this use case, I'm not sure if scanf("%d,",&val) can parse both (e.g.) 103, and 99. That is, the last number of the input file has no comma after it.
So, I had to refactor the code quite a bit. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DEBUG
#define dbgprt(_fmt...) \
printf(_fmt)
#else
#define dbgprt(_fmt...) \
do { } while (0)
#endif
// matrix control
typedef struct {
int mtx_cols; // number of columns
int mtx_rows; // number of rows (input lines)
int *mtx_base; // pointer to matrix data
} mtx_t;
// helper macro to access a given matrix coordinate
#define MTX(_mtx,_irow,_icol) \
_mtx->mtx_base[((_irow) * _mtx->mtx_cols) + _icol]
// newMatrix -- get new matrix control
mtx_t *
newMatrix(void)
{
mtx_t *mtx;
mtx = calloc(1,sizeof(*mtx));
return mtx;
}
// readMatrix -- read in matrix from stream
void
readMatrix(mtx_t *mtx,FILE *xfin)
{
char *bp;
char *cp;
char buf[1000];
// get first line as a special case to calculate the number of columns
fgets(buf,sizeof(buf),xfin);
// we need to preserve the original data for the second loop below
char tmp[1000];
strcpy(tmp,buf);
// calculate number of columns
bp = tmp;
while (1) {
char *cp = strtok(bp," ,\n");
bp = NULL;
if (cp == NULL)
break;
mtx->mtx_cols += 1;
}
// read in row by row
while (1) {
// get current row index and advance the row count
int irow = mtx->mtx_rows++;
dbgprt("BUF/%d: %s",irow,buf);
// add space for this row
mtx->mtx_base = realloc(mtx->mtx_base,
sizeof(*mtx->mtx_base) * mtx->mtx_rows * mtx->mtx_cols);
if (mtx->mtx_base == NULL) {
perror("realloc");
exit(2);
}
// parse this row
bp = buf;
for (int icol = 0; icol < mtx->mtx_cols; ++icol) {
char *cp = strtok(bp," ,\n");
bp = NULL;
if (cp == NULL)
break;
MTX(mtx,irow,icol) = strtol(cp,&cp,10);
dbgprt(" %d\n",MTX(mtx,irow,icol));
}
// get data for next row
if (fgets(buf,sizeof(buf),xfin) == NULL)
break;
}
}
void
printMatrix(const mtx_t *mtx)
{
printf("\nMATRIX A:\n");
for (int irow = 0; irow < mtx->mtx_rows; ++irow) {
for (int icol = 0; icol < mtx->mtx_cols; ++icol)
printf(" %d",MTX(mtx,irow,icol));
printf("\n");
}
}
int
main(int argc,char **argv)
{
--argc;
++argv;
FILE *xfin;
if (argc > 0)
xfin = fopen(*argv,"r");
else
xfin = stdin;
if (xfin == NULL)
exit(1);
// declare 1D array and allocate memory
mtx_t *mtx = newMatrix();
readMatrix(mtx,xfin);
printMatrix(mtx);
return 0;
}

Prime numbers in c language

I want to find prime numbers with multithreading and using Sieve of E. function.I write some piece of codes. If the program will run, the user enter a max number and thread number. The program should create threads that given thread number. The program find all prime numbers until the max number. Each thread must check one prime number.
My program doesn't find prime numbers. I write checkPrime function and crossout functions for finding prime numbers efficiently. But it doesn't work. So, I can't check my threads work correctly or not. How can I implement checkPrime function?
There are 3 functions. crossout is for Sieve E. method. checkPrime is for checking is a number prime or not. worker is for thread's function. Each thread must check one prime number.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#define MAX_N 100000000
#define MAX_THREADS 25
// global values
int threadNumber;
int largestNumber;
int isPrime;
int nthreads, // number of threads (not counting main())
prime[MAX_N + 1],
n, // in the end, prime[i] = 1 if i prime, else 0
nextbase; // next sieve multiplier to be used
// lock for the shared variable nextbase
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;
void crossout(int a) {
int i, j, check;
for (i = 2; i < largestNumber; i++)
prime[i] = 1;
for (i = a; i < largestNumber;)
if (prime[i])
for (j = i; i * j < largestNumber; j++)
prime[i * j] = 0;
}
int checkPrime(int a) {
int i;
for (i = 2; i <= a; ++i) {
if (a % i == 0) {
isPrime = 1;
return isPrime;
break;
} else
isPrime = 2;
crossout(a);
return isPrime;
}
}
void* workerThread(void* t) {
int lim, base;
long i, j;
long tid;
tid = (long)t;
printf("Thread %ld starting...\n", tid);
while (1) {
pthread_mutex_lock(&nextbaselock);
base = nextbase;
nextbase++;
// unlock the lock
pthread_mutex_unlock(&nextbaselock);
if (base <= lim) {
if (prime[base]) {
checkPrime(base);
// log work done by this thread
}
}
if (checkPrime(base) == 2)
printf("Thread %ld done. Prime = %d\n", tid, base);
pthread_exit((void*) t);
}
return NULL;
}
//main function with two parameters :argc and argv
int main(int argc, char** argv) {
threadNumber = argv[3];
largestNumber = argv[1];
int i;
pthread_t thread[threadNumber];
int rc;
long t;
void* status;
for (t = 0; t < threadNumber; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], NULL, workerThread, (void*)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < threadNumber; t++) {
rc = pthread_join(thread[t], (void*)&t);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld \n", t);
}
}
You are trying to mix two different methods for finding prime numbers. You don't need to use both the iterative division method and the sieve of Eratosthenes. This shows a way of implementing the sieve. Even numbers are ignored in the sieve but treated as special cases in isprime(). But it won't help you find a multi threaded solution, because you can't just hand over different numbers to different threads - each prime builds on the work of the previous prime, starting with the assumption that 3 is prime.
// Sieve of Eratosthenes
#include <stdio.h>
#include <stdlib.h>
#define LIMIT 200
char sieve[LIMIT] = { 1, 1, }; // 1 for not-prime
int isprime(unsigned n)
{
if(n <= 2) // special cases
return sieve[n] == 0;
if(n % 2 == 0) // even numbers are not prime
return 0;
if(n >= LIMIT) // test range
exit(1);
return sieve[n] == 0;
}
int main(void)
{
unsigned n, p;
for(n=3; n<LIMIT; n+=2) { // odd numbers only
if (sieve[n] == 0) { // if n is prime
for(p=n*n; p<LIMIT; p+=n*2) { // ignore even numbers
sieve[p] = 1; // not primne
}
}
}
printf("Prime numbers are:\n");
for(n=0; n<LIMIT; n++) { // check all numbers
if (isprime(n)) { // if n is prime
printf("%-4d", n);
}
}
printf("\n");
return 0;
}
Program output:
Prime numbers are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199
I'll now show an iterative division method. Once again, even numbers are treated as special cases. I don't often write multi threaded C code, so I can't help you with that. But I hope you can build on this second example to make a multi threaded solution.
// iterative division
#include <stdio.h>
#include <math.h>
#define LIMIT 200
int isprime(unsigned n)
{
unsigned s, i;
if(n <= 1)
return 0;
if(n == 2)
return 1;
if(n % 2 == 0) // no even numbers
return 0;
s = (unsigned)sqrt(n); // limit the loop
for(i=3; i<=s; i+=2) // odd numbers only
if (n % i == 0)
return 0;
return 1;
}
int main(void)
{
unsigned n;
printf("Prime numbers are:\n");
for(n=0; n<LIMIT; n++) { // check all numbers
if (isprime(n)) { // if n is prime
printf("%-4d", n);
}
}
printf("\n");
return 0;
}
Program output:
Prime numbers are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199
There are some pitfalls in both of the above examples when working with larger numbers, but I'll leave them for you to discover.
This is modified version of Sieve of Eratosthenes which is the very simple, interesting and fast. Understand its working as I have tried to explain it using comments. Actually try to understand the run-time allocation of array size to avoid defining a large MAX value and try to code simple by analyzing your algorithm and applying good mathematics along with smart coding knowledge.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
int *arr;
int count=0,i=3,j,n;
arr=(int*)malloc(count+1*sizeof(int)); //set array size to 1
arr[count++]=2; //stored 2 as array first element
printf("Find all prime numbers upto :: ");
scanf("%d",&n); //n is the number up to which prime numbers are required
here:
{
while(i<=n) //start with i=3
{
j=0;
while(arr[j]<=sqrt(i)) //till array element value is less than or equal to root of number under checking
{
if(i%arr[j]!=0) //if remainder is not zero check divisibility with next array element
j++;
else
{
i++; //if remainder is zero then start checking for another number
goto here;
}
}
printf("%d, ",arr[count-1]); //printing the number which was proved as prime last time
arr=(int *)realloc(arr,(count+1)*sizeof(int)); //increasing array size by 1
arr[count++]=i; //newly proved prime is stored as next array element
i++;
}
printf("%d, ",arr[count-1]); //print last number proved as prime
}

Multithreaded Sorting Application

I am new to multithreaded programming and so I thought I would work on a project to help me learn it. Here are the details of the project:
Write a multithreaded sorting program in c that works as follows: A list of integers is divided into two smaller lists of equal size. Two separate threads (which we will term sorting threads) sort each sublist using a sorting algorithm of your choice. The two sublists are then merged by a third thread - a merging thread - which merges the two sublists into a single sorted list.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
#define NUMBER_OF_THREADS 3
void *sorter(void *params); /* thread that performs basic sorting algorithm */
void *merger(void *params); /* thread that performs merging of results */
int list[SIZE] = {7,12,19,3,18,4,2,6,15,8};
int result[SIZE];
typedef struct
{
int from_index;
int to_index;
} parameters;
int main (int argc, const char * argv[])
{
int i;
pthread_t workers[NUMBER_OF_THREADS];
/* establish the first sorting thread */
parameters *data = (parameters *) malloc (sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2) - 1;
pthread_create(&workers[0], 0, sorter, data);
/* establish the second sorting thread */
data = (parameters *) malloc (sizeof(parameters));
data->from_index = (SIZE/2);
data->to_index = SIZE - 1;
pthread_create(&workers[1], 0, sorter, data);
/* now wait for the 2 sorting threads to finish */
for (i = 0; i < NUMBER_OF_THREADS - 1; i++)
pthread_join(workers[i], NULL);
/* establish the merge thread */
data = (parameters *) malloc(sizeof(parameters));
data->from_index = 0;
data->to_index = (SIZE/2);
pthread_create(&workers[2], 0, merger, data);
/* wait for the merge thread to finish */
pthread_join(workers[2], NULL);
/* output the sorted array */
return 0;
}
void *sorter(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->from_index;
int end = p->to_index+1;
int z;
for(z = begin; z < end; z++){
printf("The array recieved is: %d\n", list[z]);
}
printf("\n");
int i,j,t,k;
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i-1; j++)
{
if(list[j] > list[j+1])
{
t = list[j];
list[j] = list[j+1];
list[j+1] = t;
}
}
}
for(k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
printf("\n");
pthread_exit(0);
}
void *merger(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->from_index;
int end = p->to_index+1;
int i,j,t;
printf("list[1]: %d",list[1]);
printf("result[1]: %d",result[1]);
for(i=begin; i< end; i++)
{
for(j=begin; j< end-i; j++)
{
if(result[j] > result[j+1])
{
t = result[j];
result[j] = result[j+1];
result[j+1] = t;
}
}
}
int d;
for(d=0; d<SIZE; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(0);
}
I'm not sure what I'm doing wrong in my algorithms that its not working. It doesn't seem to catch the new sorted array. Any help on this problem would be appreciated VERY much! Thanks again in advance for all your help!
Your approach is incorrect. You should be splitting your partitions, then recursing or threading into them, joining the results, then merging. Its easy to screw this algorithm up, believe me.
Before anything else, make sure your merge algorithm is solid. If your merge has issues in a single-threaded arena, adding threads is only going to make it worse. In your case, you're making it worse because your merge thread appears to be running concurrently with your sorter threads.
That said, step back and consider this. Mergesort is about divide and conquer. To thread up a merge sort you should be doing the following:
Establish a maximum number of threads. Believe me, the last thing you want happening is spinning a thread for each partition. a sequence of 1024 values has 1023 partitions if you crunch the math hard enough. that many threads is not a solution. Establish some boundaries.
Establish a minimum partition size that you're willing to spin a thread for. This is as important as the first item above. Just like you don't want to be spinning 1023 threads to sort a 1024-slot sequence, you also don't want to be spinning a thread just to sort a sequence that has two items. There is zero benefit and much cost.
Have a solid merge algorithm. There are many efficient ways to do it, but do something simple and enhance it later. Right now we're just interested in getting the general threading down right. There is always time to enhance this with a fancy merge algorithm (like in-place, which believe me is harder than it sounds).
Having the above the idea is this:
The merge sort algorithm will have three parameters: a starting pointer, a length, and a thread-depth. For our purposes the thread depth will be N in a situation where we are using at-most 2N-1 threads. (more on that later, but trust me, it makes it easier to do the math this way).
If the thread depth has reached zero OR the sequence length is below a minimum threshold *we set), do not setup and run a new thread. Just recurse into our function again.
Otherwise, split the partition. Setup a structure that holds a partition definition (which for us will be a starting point and a length as well as the thread depth which will be N/2), launch a thread with that parameter block, then do NOT launch another thread. instead use the current thread to recurse into merge_sort_mt() for the "other" half.
Once the current thread returns from its recursion is must wait on the other thread via a join. once that is done both partitions will be done and they can be merged using your trivial merge algorithm.
Whew. Ok. so how does it look in practice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
struct Params
{
int *start;
size_t len;
int depth;
};
// only used for synchronizing stdout from overlap.
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
// forward declare our thread proc
void *merge_sort_thread(void *pv);
// a simple merge algorithm. there are *several* more efficient ways
// of doing this, but the purpose of this exercise is to establish
// merge-threading, so we stick with simple for now.
void merge(int *start, int *mid, int *end)
{
int *res = malloc((end - start)*sizeof(*res));
int *lhs = start, *rhs = mid, *dst = res;
while (lhs != mid && rhs != end)
*dst++ = (*lhs < *rhs) ? *lhs++ : *rhs++;
while (lhs != mid)
*dst++ = *lhs++;
// copy results
memcpy(start, res, (rhs - start) * sizeof *res);
free(res);
}
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
if (depth <= 0 || len < 4)
{
merge_sort_mt(start, len/2, 0);
merge_sort_mt(start+len/2, len-len/2, 0);
}
else
{
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, &params);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
}
// merge the partitions.
merge(start, start+len/2, start+len);
}
// our thread-proc that invokes merge_sort. this just passes the
// given parameters off to our merge_sort algorithm
void *merge_sort_thread(void *pv)
{
struct Params *params = pv;
merge_sort_mt(params->start, params->len, params->depth);
return pv;
}
// public-facing api
void merge_sort(int *start, size_t len)
{
merge_sort_mt(start, len, 4); // 4 is a nice number, will use 7 threads.
}
int main()
{
static const unsigned int N = 2048;
int *data = malloc(N * sizeof(*data));
unsigned int i;
srand((unsigned)time(0));
for (i=0; i<N; ++i)
{
data[i] = rand() % 1024;
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
// invoke our multi-threaded merge-sort
merge_sort(data, N);
for (i=0; i<N; ++i)
{
printf("%4d ", data[i]);
if ((i+1)%8 == 0)
printf("\n");
}
printf("\n");
free(data);
return 0;
}
The output for this looks something like this:
825 405 691 290 900 715 125 969
534 809 783 820 933 895 310 687
152 19 659 856 46 765 497 371
339 660 297 509 152 796 230 465
502 948 278 317 144 941 195 208
617 428 118 505 719 161 53 292
....
994 154 745 666 590 356 894 741
881 129 439 237 83 181 33 310
549 484 12 524 753 820 443 275
17 731 825 709 725 663 647 257
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 2 3 3
5 5 5 5 6 6 7 7
7 7 7 8 8 10 10 11
11 11 12 12 12 13 14 14
15 15 15 15 16 17 17 17
17 18 18 19 19 19 20 21
21 21 22 22 23 24 24 24
25 25 25 26 26 28 28 29
29 29 30 30 30 30 30 31
....
994 995 996 998 1000 1001 1001 1003
1003 1003 1003 1004 1004 1005 1007 1007
1010 1010 1010 1010 1011 1012 1012 1012
1012 1013 1013 1013 1015 1015 1016 1016
1016 1017 1018 1019 1019 1019 1020 1020
1020 1021 1021 1021 1021 1022 1023 1023
The most important part of this is the limiters that keep us from going thread-wild (which is easy to accidentally do with recursive threaded algorithms), and the join of the threads before merging their content with the other half of the partition (which we sorted on our thread, and may also have done the same thing).
It's a fun exercise, and I hope you got something out of it. Best of luck.
Update: Integrating qsort()
An interesting task would be performing this functionality using qsort() for sorting the smaller partitions or once the thread pool reaches exhaustion. qsort() is a pretty big hammer to bring to this party, and as such you're going to want to raise the minimum partition size to something respectful (in the example below, we use 256 elements).
So what would it take to integrate qsort() the the sub partitions rather than a hand-rolled merge-sort? Surprisingly, not much. Start with a qsort() compatible comparator:
// comparator for qsort
int cmp_proc(const void *arg1, const void* arg2)
{
const int *lhs = arg1;
const int *rhs = arg2;
return (*lhs < *rhs) ? -1 : (*rhs < *lhs ? 1 : 0);
}
Pretty brain-dead. Now, modify the mt-wrapper to look something like this:
// our multi-threaded entry point.
void merge_sort_mt(int *start, size_t len, int depth)
{
if (len < 2)
return;
// invoke qsort on the partition. no need for merge
if (depth <= 0 || len <= 256)
{
qsort(start, len, sizeof(*start), cmp_proc);
return;
}
struct Params params = { start, len/2, depth/2 };
pthread_t thrd;
pthread_mutex_lock(&mtx);
printf("Starting subthread...\n");
pthread_mutex_unlock(&mtx);
// create our thread
pthread_create(&thrd, NULL, merge_sort_thread, &params);
// recurse into our top-end parition
merge_sort_mt(start+len/2, len-len/2, depth/2);
// join on the launched thread
pthread_join(thrd, NULL);
pthread_mutex_lock(&mtx);
printf("Finished subthread.\n");
pthread_mutex_unlock(&mtx);
// merge the paritions.
merge(start, start+len/2, start+len);
}
That's it. Seriously. That is all it takes. Proving this works is a simple test run with the original program, shown below:
986 774 60 596 832 171 659 753
638 680 973 352 340 221 836 390
930 38 564 277 544 785 795 451
94 602 724 154 752 381 433 990
539 587 194 963 558 797 800 355
420 376 501 429 203 470 670 683
....
216 748 534 482 217 178 541 242
118 421 457 810 14 544 100 388
291 29 562 718 534 243 322 187
502 203 912 717 1018 749 742 430
172 831 341 331 914 866 931 368
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Starting subthread...
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
Finished subthread.
0 0 1 1 1 1 3 3
3 4 5 5 6 6 6 6
7 7 8 9 10 10 10 10
11 12 12 12 13 13 14 14
14 15 15 15 16 17 17 19
19 20 20 21 21 21 22 22
23 23 23 24 24 24 25 26
26 26 26 27 28 28 28 28
....
1000 1000 1000 1001 1001 1002 1003 1003
1004 1004 1004 1005 1005 1005 1006 1007
1008 1010 1010 1010 1010 1010 1011 1011
1011 1012 1012 1012 1012 1013 1013 1013
1015 1015 1015 1016 1016 1017 1017 1017
1018 1018 1018 1019 1019 1021 1021 1022
As you can see, the results are similar.
A couple of issues:
1 - What do you think this code is doing:
int x;
for(x=begin; x<end; x++)
{
list[x] = result[x];
}
2 - Your merger currently looks exactly like your sorter. It should instead be merging the sorted values from the first half of the list and the second half of the list into the result.
Your code is correct i have modified your code and tried to figure out the error,
the loop indexes are not correctly mapped and you are assigning the null result list into actual data in one loop, so the list is taking zeroes.
Find below the modified code and output.
//Sort a list of numbers using two separate threads
//by sorting half of each list separately then
//recombining the lists
void *sort(void *params)
{
parameters* p = (parameters *)params;
//SORT
int begin = p->fromVal;
int end = p->toVal+1;
for(int i = begin; i < end; i++){
printf("The array recieved is: %d\n", list[i]);
}
printf("\n");
int temp=0;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(list[j] > list[j+1])
{
temp = list[j];
list[j] = list[j+1];
list[j+1] = temp;
}
}
}
for(int k = begin; k< end; k++){
printf("The sorted array: %d\n", list[k]);
}
for(int i=begin; i<end; i++)
{
result[i] = list[i];
}
printf("\n");
pthread_exit(NULL);
}
void *merging(void *params)
{
parameters* p = (parameters *)params;
//MERGE
int begin = p->fromVal;
int end = p->toVal+1;
int temp;
for(int i=begin; i< end; i++)
{
for(int j=begin; j< end-1; j++)
{
if(result[j] > result[j+1])
{
temp= result[j];
result[j] = result[j+1];
result[j+1] = temp;
}
}
}
printf("\n\nFINAL RESULT IS:\n");
for(int d=begin+1; d<end; d++)
{
printf("The final resulting array is: %d\n", result[d]);
}
pthread_exit(NULL);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
/*globle variables*/
/* structure for passing data to threads */
typedef struct
{
int *start;
int end;
int size;
} parameters;
int t = 1;
int *arr1, *arr2;
//for using quicksort
int comparator (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
void *merge(void *params){
//get data
int *len = params;
//SORT
int start = 0;
int end = *len/2;
int counter = end;
int size = *len;
int index = 0;
while (start < end && counter < size)
{
if (arr1[start] < arr1[counter])
{
arr2[index] = arr1[start];
start ++;
}
else
{
arr2[index] = arr1[counter];
counter ++;
}
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( start < end)
{
arr2[index] = arr1[start];
start ++;
index ++;
}
/* Copy the remaining elements , if there
are any */
while ( counter < size)
{
arr2[index] = arr1[counter];
counter ++;
index ++;
}
}
void *sorting_thread(void *params){
printf("Thread %d ......\n", t);
t++;
//get data
parameters* data = (parameters *)params;
//SORT
int end = data->end;
int size = data->size;
//qsort
qsort(data->start, end, sizeof(*data->start), comparator);
printf("The array after sort : \n");
for(int i = size - end; i < size; i ++){
printf("arr1[%d]:%d, \n", i,arr1[i]);
}
printf("\n");
pthread_exit(0);
}
void *merge_sort_thread(void *params){
int *len = params;
//varaible allocation for two sorting threads.
parameters *data = (parameters *) malloc (sizeof(parameters));
parameters *data1 = (parameters *) malloc (sizeof(parameters));
if(data == NULL&& data1 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
//value for data passing
data->start= arr1;
data->end = *len/2;
data->size = *len/2;
data1->start = arr1 + *len/2;
data1->end = *len-*len/2;
data1->size = *len;
pthread_t left, right;/* the thread identifier */
printf("Entering merge_Sorting..\n");
/* create the sorting thread */
pthread_create(&left, NULL, sorting_thread, data);
pthread_create(&right, NULL, sorting_thread, data1);
/* wait for the thread to exit */
pthread_join(left, NULL);
//free memory
free(data);
pthread_join(right, NULL);
printf("Merging Thread %d ......\n", t);
merge(len);
printf("Process is done.\n");
printf("The final output: \n");
for(int i = 0; i < *len; i ++){
if(i%10==0){
printf("\n");
}
printf("%d, ", arr2[i]);
}
printf("\n");
//free memory
free(data1);
pthread_exit(0);
}
int main( int argc, char *argv[] ) {
long len;
int temp, c, j, k;
char *ptr;
//
//check if the right amount of argument
if( argc == 2 ) {
printf("The input array size is %s\n", argv[1]);
//covert the user input to integer
len = strtol(argv[1], &ptr, 10);
//check if the input is valid.
if(len == 0) {//if not, leave the program.
printf("Please enter a proper number. Leaving the program...\n");
}else{
//dynamically allocate memory
arr1 = (int*)malloc(len * sizeof(int));
arr2 = (int*)malloc(len * sizeof(int));
//check Memory
if(arr1 == NULL && arr2 == NULL){
printf("Memory not allocated. \n");
exit(0);
}
printf("Memory allocated. \n");
//decide the value of data.
//generate random number to 100
srand(time(0));
printf("The array before sorting is: \n");
for(int i = 0; i < len; i ++){
arr1[i] = rand() % 100;
if(i%10==0){
printf("\n");
}
printf("%d, ", arr1[i]);
}
printf(" \n");
//merge sort handle all the threads
pthread_t tid;/* the thread identifier */
/* create the parent sorting thread */
pthread_create(&tid, NULL, merge_sort_thread, &len);
//wait for children thread
pthread_join(tid, NULL);
//printout array after merging threading
printf("\nThe program is finished. \n");
//free memory space
free(arr2);
free(arr1);
}
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
return 0;
}

How to implement ordered crossover

So I have two parents
ABCDE
EDCBA
can I just select a subset from both:
From parent one: ACD
From parent two: EDC
Then I copy parent one into offspring one but copy the selected subset with parent twos order so:
Offspring one: DBCAE
Offspring two: CDEBA
To answer the title question:
http://www.eecs.tufts.edu/~jfinke02/jmona/xref/jmona/example/tsp/crossover/OrderedCrossoverFunction.html:
1 /**
2 * OrderedCrossoverFunction.java
3 *
4 * Copyright 2009, 2010 Jeffrey Finkelstein
5 *
6 * This file is part of jmona.
7 *
8 * jmona is free software: you can redistribute it and/or modify it under the
9 * terms of the GNU General Public License as published by the Free Software
10 * Foundation, either version 3 of the License, or (at your option) any later
11 * version.
12 *
13 * jmona is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * jmona. If not, see <http://www.gnu.org/licenses/>.
19 */
20 package jmona.example.tsp.crossover;
21
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Vector;
25
26 import jmona.CrossoverFunction;
27 import jmona.functional.Range;
28 import jmona.random.RandomUtils;
29
30 /**
31 * Ordered crossover (also known as OX) for a tour in the traveling salesman
32 * problem.
33 *
34 * #author Jeffrey Finkelstein
35 * #since 0.1
36 */
37 // TODO references for the original authors of TSP crossover functions
38 public class OrderedCrossoverFunction implements
39 CrossoverFunction<List<Integer>> {
40
41 /**
42 * Perform ordered crossover (also known as OX) on the specified tours.
43 *
44 * Ordered crossover works in two stages. First, a random slice is swapped
45 * between the two tours, as in a two-point crossover. Second, repeated cities
46 * not in the swapped area are removed, and the remaining integers are added
47 * from the other tour, in the order that they appear starting from the end
48 * index of the swapped section.
49 *
50 * #param tour1
51 * A tour.
52 * #param tour2
53 * Another tour.
54 * #see jmona.CrossoverFunction#crossover(Object, Object)
55 */
56 #Override
57 public void crossover(final List<Integer> tour1, final List<Integer> tour2) {
58
59 // get the size of the tours
60 final int size = tour1.size();
61
62 // choose two random numbers for the start and end indices of the slice
63 // (one can be at index "size")
64 final int number1 = RandomUtils.randomData().nextInt(0, size - 1);
65 final int number2 = RandomUtils.randomData().nextInt(0, size);
66
67 // make the smaller the start and the larger the end
68 final int start = Math.min(number1, number2);
69 final int end = Math.max(number1, number2);
70
71 // instantiate two child tours
72 final List<Integer> child1 = new Vector<Integer>();
73 final List<Integer> child2 = new Vector<Integer>();
74
75 // add the sublist in between the start and end points to the children
76 child1.addAll(tour1.subList(start, end));
77 child2.addAll(tour2.subList(start, end));
78
79 // iterate over each city in the parent tours
80 int currentCityIndex = 0;
81 int currentCityInTour1 = 0;
82 int currentCityInTour2 = 0;
83 for (final int i : new Range(size)) {
84
85 // get the index of the current city
86 currentCityIndex = (end + i) % size;
87
88 // get the city at the current index in each of the two parent tours
89 currentCityInTour1 = tour1.get(currentCityIndex);
90 currentCityInTour2 = tour2.get(currentCityIndex);
91
92 // if child 1 does not already contain the current city in tour 2, add it
93 if (!child1.contains(currentCityInTour2)) {
94 child1.add(currentCityInTour2);
95 }
96
97 // if child 2 does not already contain the current city in tour 1, add it
98 if (!child2.contains(currentCityInTour1)) {
99 child2.add(currentCityInTour1);
100 }
101 }
102
103 // rotate the lists so the original slice is in the same place as in the
104 // parent tours
105 Collections.rotate(child1, start);
106 Collections.rotate(child2, start);
107
108 // copy the tours from the children back into the parents, because crossover
109 // functions are in-place!
110 Collections.copy(tour1, child2);
111 Collections.copy(tour2, child1);
112 }
113
114 }
More theory: http://www.dmi.unict.it/mpavone/nc-cs/materiale/moscato89.pdf (mirror: http://www.scribd.com/doc/101866504/1989-On-Genetic-Crossover-Operators-for-Relative-Order-Preservation)
Related: http://www.scribd.com/doc/53306810/35/ORDERED-CROSSOVER:
Here is the code above implemented in C++ with my own random class. I'm not sure if the rotation is correct but the cross overing seems legit. At the end of the day, you won't get any repeats!
#include <array>
#include <random>
#include <iostream>
// I converted this found code into a functional class
// http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
class MyRandom
{
public:
MyRandom() : gen(rd()) {}
int nextInt(const int& max)
{
std::uniform_int_distribution<> dis(0, max);
return dis(gen);
}
private:
std::random_device rd;
std::mt19937_64 gen;
std::uniform_int_distribution<> setdis;
bool disSet = false;
};
void crossover(std::vector<int>& parent1, std::vector<int>& parent2)
{
int size = int(parent1.size());
MyRandom rand;
int number1 = rand.nextInt(7);
int number2 = rand.nextInt(7);
int start = fmin(number1, number2);
int end = fmax(number1, number2);
std::vector<int> child1;
std::vector<int> child2;
for(int i = start; i<end; i++)
{
child1.push_back(parent1[i]);
child2.push_back(parent2[i]);
}
int geneIndex = 0;
int geneInparent1 = 0;
int geneInparent2 = 0;
for (int i = 0; i<size; i++)
{
geneIndex = (end + i) % size;
geneInparent1 = parent1[geneIndex];
geneInparent2 = parent2[geneIndex];
bool is_there = false;
for(int i1 = 0; i1<child1.size(); i1++)
{
if(child1[i1] == geneInparent2)
{
is_there = true;
}
}
if(!is_there)
{
child1.push_back(geneInparent2);
}
bool is_there1 = false;
for(int i1 = 0; i1<child2.size(); i1++)
{
if(child2[i1] == geneInparent1)
{
is_there1 = true;
}
}
if(!is_there1)
{
child2.push_back(geneInparent1);
}
}
std::rotate(child1.begin(), child1.begin()+start, child1.end());
std::rotate(child2.begin(), child2.begin()+start, child2.end());
for(int i = 0; i<size; i++)
{
parent1[i] = child2[i];
parent2[i] = child1[i];
}
}
int main(int argc, const char * argv[]) {
std::vector<int> parent1 = {0, 1, 2, 3, 4, 5, 6, 7};
std::vector<int> parent2 = {7, 6, 5, 4, 3, 2, 1, 0};
for(int i = 0; i<8; i++)
{
std::cout << parent1[i] << " ";
}
std::cout << std::endl;
for(int i = 0; i<8; i++)
{
std::cout << parent2[i] << " ";
}
std::cout << std::endl;
crossover(parent1, parent2);
for(int i = 0; i<8; i++)
{
std::cout << parent1[i] << " ";
}
std::cout << std::endl;
for(int i = 0; i<8; i++)
{
std::cout << parent2[i] << " ";
}
std::cout << std::endl;
return 0;
}

Resources