MPI-IO only writes data from one process - c

For some reason, MPI-IO is only writing the data from one of my processes out to a file. I used MPI_File_open to open the file, MPI_File_set_view to set the view for each process, and MPI_File_write_all to write the data out. When I run the code, everything seems to execute fine and without any error, but for some reason, the file output consists of garbled junk at the first line of the CSV file (it just says NULL NULL NULL a bunch and keeps repeating on the first line when I open it to read in VS Code), and the remainder of the file is the output for the second process block (since I'm using block decomposition on two processes). I can't seem to figure out why my program isn't outputting values correctly (or at least the first process) and I figured I'd ask on here.
I've attached the code here and omitted the parts that didn't apply to the problem at hand:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <mpi.h>
int main (int argc, char** argv) {
int iproc, nproc;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &iproc);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
//Inputs:
int depth = 3;
float p_x_error = 0.05;
float p_z_error = 0.05;
int max_char[] = {128, 640, 328};
int i_max_char = max_char[(depth%3)];
int num_data_qubits = depth * depth;
int data_qubit_x_error[ depth + 2][ depth + 2 ];
int data_qubit_z_error[ depth + 2 ][ depth + 2 ];
int ancilla_qubit_value[ depth + 1 ][ depth + 1 ];
// Parallel block decomposition variables
int total_num_iter = pow(4, num_data_qubits); // Total number of outer loop iterations
int block_size = floor(total_num_iter/nproc); // Number of iterations per process (block)
if (total_num_iter%nproc > 0) { block_size += 1; } // Add 1 if blocks don't divide evenly
int iter_first = iproc * block_size;
int iter_last = iter_first + block_size;
MPI_Status status;
MPI_File fh;
char buf[i_max_char];
//Output:
MPI_File_open(MPI_COMM_SELF, "testfile.csv", MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
MPI_File_set_view(fh, iproc * block_size * strlen(buf) * sizeof(char), MPI_CHAR, MPI_CHAR, "native", MPI_INFO_NULL);
if(iproc == 0) {
printf("Block size: %d\n", block_size);
}
for ( int i = iter_first; i < iter_last; i++ ) {
// A bunch of stuff happens where values are written to the 2d arrays listed above
char label_list[i_max_char];
strcpy(label_list, "\n");
char anc_name[3];
// Output the ancilla qubit values in proper format
int ancilla_value;
for (int k=1; k < depth; k++) {
if (k%2 == 0) {
ancilla_value = (ancilla_qubit_value[depth][k] == 1) ? -1 : 1;
sprintf(anc_name, "%d,", ancilla_value);
strcat(label_list, anc_name);
}
for (int j=depth-1; j > 0; j--) {
if (k == 1 && j%2 == 0) {
ancilla_value = (ancilla_qubit_value[j][k-1] == 1) ? -1 : 1;
sprintf(anc_name, "%d,", ancilla_value);
strcat(label_list, anc_name);
} else if (k == (depth - 1) && j%2 == 1) {
ancilla_value = (ancilla_qubit_value[j][k+1] == 1) ? -1 : 1;
sprintf(anc_name, "%d,", ancilla_value);
strcat(label_list, anc_name);
}
ancilla_value = (ancilla_qubit_value[j][k] == 1) ? -1 : 1;
sprintf(anc_name, "%d,", ancilla_value);
strcat(label_list, anc_name);
}
if (k%2 == 1) {
ancilla_value = (ancilla_qubit_value[0][k] == 1) ? -1 : 1;
sprintf(anc_name, "%d,", ancilla_value);
strcat(label_list, anc_name);
}
}
// For printing label list:
strcat(label_list, "\"[");
char qubit_name[6];
int first = 1;
for (int k = 1; k < depth + 1; k++) {
for (int j = depth; j > 0; j--) {
if (data_qubit_x_error[j][k] == 1) {
if (first == 1) {
first = 0;
} else {
strcat(label_list, ", ");
}
sprintf(qubit_name, "'X%d%d'", (k-1), (depth-j));
strcat(label_list, qubit_name);
}
if (data_qubit_z_error[j][k] == 1) {
if (first == 1) {
first = 0;
} else {
strcat(label_list, ", ");
}
sprintf(qubit_name, "'Z%d%d'", (k-1), (depth-j));
strcat(label_list, qubit_name);
}
}
}
strcat(label_list, "]\"");
MPI_File_write_all(fh, label_list, strlen(label_list) * sizeof(char), MPI_CHAR, MPI_STATUS_IGNORE);
}
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}

After lots of digging, I finally found the answer. The value I used as the offset for MPI_File_set_view() was measuring the size of buf as 1 with strlen(buf) since the variable was initialized, but not populated. I remedied this by changing the offset value to (MPI_Offset) (iproc * block_size * i_max_char) so that the offset would be the correct length, which seems to have resolved the issue!

Related

How is my ring buffer adding an additional element?

I have a ring buffer example code that I'm practicing and for some odd reason, it adds an extra element with no apparent reason.
The behavior I am coding is that it drops incoming data if buffer is full.
Here is the code:
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct {
void *buf;
ssize_t ri; //read index
ssize_t wi; //write index
ssize_t capacity; // total size of buffer in bytes
size_t max_count;
size_t count;
ssize_t sz; // size of individual elements in bytes
bool full;
} r_buffer_t;
r_buffer_t* ring_buffer_init(unsigned int count, ssize_t dsize) {
r_buffer_t *buffer = malloc(sizeof(r_buffer_t));
if(buffer != NULL){
buffer->buf = malloc(count * sizeof(dsize));
if(buffer->buf != NULL) {
buffer->max_count = count;
buffer->sz = dsize;
buffer->count = 0;
buffer->ri = 0;
buffer->wi = 0;
buffer->capacity = count * dsize;
buffer->full = false;
return buffer;
}
free(buffer);
}
return NULL;
}
int put_item(r_buffer_t *buffer, void *data) {
assert(buffer && data); // exception catch on stderr;
if(!buffer->full) {
printf("\nw-memcpy");
memcpy((buffer->buf + (buffer->wi * buffer->sz)), data, sizeof(buffer->sz));
printf("\n\t\tret\tdata\tcount\tfull\twi");
//printf("\n-------------------------------------------------\n");
printf("\nAdding data :\t%d\t%d\t%ld\t%d\t%ld", 0, *((int*)data), buffer->count, buffer->full, buffer->wi);
buffer->count++;
buffer->wi++;
buffer->wi %= buffer->max_count;
//if((buffer->wi == buffer->ri) && (buffer->count >= (buffer->max_count))) {
if(buffer->count >= buffer->max_count) {
printf("\n>>>Full for count = %ld, buffer-full = %d, index ri = %ld, wi=%ld",
buffer->count, buffer->full, buffer->ri, buffer->wi);
buffer->full = true;
}
return 0;
}
printf("\n>>>Dropping data. Buffer Full for count = %ld, buffer-full = %d, index ri = %ld, wi=%ld",
buffer->count, buffer->full, buffer->ri, buffer->wi);
//printf("\n%d\t%d\t%ld\t%d", -1, *((int *)data), buffer->count, buffer->full);
return -1;
}
int get_item(r_buffer_t *buffer, void *data) {
assert(buffer && data);
if(buffer->count > 0) {
printf("r-memcpy");
memcpy(data, (buffer->buf + (buffer->ri * buffer->sz)), buffer->sz);
memset((buffer->buf + (buffer->ri * buffer->sz)), 0, buffer->sz);
//printf("\n%d\t%d\t%ld\t%d\t%ld", 0, *((int*)data), buffer->count, buffer->full, buffer->ri);
buffer->count--;
buffer->ri++;
buffer->ri %= buffer->max_count;
buffer->full = (buffer->count >= buffer->max_count);
return 0;
}
//printf("\n%d\t%d\t%ld\t%d\t%ld", -1, *((int*)data), buffer->count, buffer->full, buffer->ri);
return -1;
}
void print_buffer(r_buffer_t *buffer) {
int i = 0;
printf("\n*************Buffer***********\n");
printf("\ncount = %ld, full = %d, ri = %ld, wi = %ld",
buffer->count, buffer->full, buffer->ri, buffer->wi);
printf("\n\t");
for(i =0; i < buffer->max_count; i++){
if(buffer->ri == i)
printf("R ");
else
printf(" ");
}
printf("\n\t");
for(i =0; i < buffer->max_count; i++)
printf("%d |", *(int *)(buffer->buf + i * buffer->sz));
printf("\n\t");
for(i =0; i < buffer->max_count; i++){
if(buffer->wi == i)
printf("W ");
else
printf(" ");
}
printf("\n*********************************\n");
}
int main() {
int i = 0;
int d1[] = {1,2,3,4,5,6,7,8,9,10};
int rd = 0;
int ret = 0;
r_buffer_t *buf = ring_buffer_init(5, sizeof(unsigned int));
print_buffer(buf);
printf("\nAdding 4 items to buffer");
for(i = 0; i < 4; i++) {
printf("\nCalling put for %d", d1[i]);
ret = put_item(buf, (void *)&d1[i]);
}
print_buffer(buf);
printf("\nRemoving and printing 2");
for(i = 0; i < 2; i++){
get_item(buf, &rd);
}
print_buffer(buf);
printf("\nAdding 4 more items to buffer");
for(i = 4; i < 9; i++) {
ret = put_item(buf, &d1[i]);
}
print_buffer(buf);
return 0;
}
The output makes no sense:
*************Buffer***********
count = 0, full = 0, ri = 0, wi = 0
R
0 |0 |0 |0 |0 |
W
*********************************
Adding 4 items to buffer
Calling put for 1
w-memcpy
ret data count full wi
Adding data : 0 1 0 0 0
Calling put for 2
w-memcpy
ret data count full wi
Adding data : 0 2 1 0 1
Calling put for 3
w-memcpy
ret data count full wi
Adding data : 0 3 2 0 2
Calling put for 4
w-memcpy
ret data count full wi
Adding data : 0 4 3 0 3
*************Buffer***********
count = 4, full = 0, ri = 0, wi = 4
R
1 |2 |3 |4 |5 |
W
*********************************
How is there an extra '5' in the buffer ?
memcpy((buffer->buf + (buffer->wi * buffer->sz)), data, sizeof(buffer->sz));
The above line in put_item() would copy a number of sizeof(buffer->sz) bytes from data to (buffer->buf + (buffer->wi * buffer->sz)).
The sizeof(buffer->sz) equals to sizeof(ssize_t) for the type of buffer->sz is ssize_t in type r_buffer_t.
In many system, ssize_t would be signed long while size_t would be unsigned long, and they would be double the sizeof(int) bytes in general. It is possible that the above code line actually copy double the sizeof(int) bytes from the source to destination, then at the fourth call to put_item() the fifth element in array d1[] would always be copied into the ring buffer.
You might want to change it as the following line.
memcpy((buffer->buf + (buffer->wi * buffer->sz)), data, buffer->sz);

MPI_SEND and MPI_RECIEVE have no Reference by Compile

I am trying to compile an MPI program with mpicc. The compiler complains only that there is no reference to MPI_RECIVE and MPI_SEND, and ends the compile error. I have #include in the .c file.
Can someone tell me how I can fix this?
Here ist the Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <mpi.h>
#include "random.h"
#include "md5tool.h"
/* horizontal size of the configuration */
#define XSIZE 1024
/* "ADT" State and line of states (plus border) */
typedef char State;
typedef State Line[XSIZE + 2];
/* determine random integer between 0 and n-1 */
#define randInt(n) ((int)(nextRandomLEcuyer() * n))
/* random starting configuration */
static void initConfig(Line *buf, int lines){
int x, y;
initRandomLEcuyer(424243);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
buf[y][x] = randInt(100) >= 50;
}
}
}
/* annealing rule from ChoDro96 page 34
* the table is used to map the number of nonzero
* states in the neighborhood to the new state
*/
static State anneal[10] = {0, 0, 0, 0, 1, 0, 1, 1, 1, 1};
/* a: pointer to array; x,y: coordinates; result: n-th element of anneal,
where n is the number of neighbors */
#define transition(a, x, y) \
(anneal[(a)[(y)-1][(x)-1] + (a)[(y)][(x)-1] + (a)[(y)+1][(x)-1] +\
(a)[(y)-1][(x) ] + (a)[(y)][(x) ] + (a)[(y)+1][(x) ] +\
(a)[(y)-1][(x)+1] + (a)[(y)][(x)+1] + (a)[(y)+1][(x)+1]])
/* treat torus like boundary conditions */
static void boundary(Line *buf, int lines){
int x,y;
for (y = 0; y <= lines+1; y++) {
/* copy rightmost column to the buffer column 0 */
buf[y][0 ] = buf[y][XSIZE];
/* copy leftmost column to the buffer column XSIZE + 1 */
buf[y][1+1] = buf[y][1 ];
}
for (x = 0; x <= XSIZE+1; x++) {
/* copy bottommost row to buffer row 0 */
buf[0][x ] = buf[lines][x];
/* copy topmost row to buffer row lines + 1 */
buf[lines+1][x] = buf[1][x ];
}
}
/* make one simulation iteration with lines lines.
* old configuration is in from, new one is written to to.
*/
//umschreiben
/**
static void simulate(Line *from, Line *to, int lines){
boundary(from, lines);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
to[y][x ] = transition(from, x , y);
}
}
}
*/
/* --------------------- measurement ---------------------------------- */
int main(int argc, char** argv){
int lines, its;
int i;
Line *from, *to, *temp, *next;
char* hash;
assert(argc == 3);
lines = atoi(argv[1]);
its = atoi(argv[2]);
from = malloc((lines + 2) * sizeof(Line));
to = malloc((lines + 2) * sizeof(Line));
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
if(world_rank == 0){
int y;
next = malloc((lines + 2) * sizeof(Line));
initConfig(from, lines);
for (i = 0; i < its; i++) {
boundary(from, lines);
int z;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_SEND(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,0,MPI_COMM_WORLD);
}
}
MPI_Status status;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_RECIVE(next,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,1,&status);
if(status.MPI_ERROR){
//TODO
MPI_Abort(MPI_COMM_WORLD,1);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
stpcpy(to[y*z],next[y*z]);
}
}
}
temp = from;
from = to;
to = temp;
}
hash = getMD5DigestStr(from[1], sizeof(Line) * (lines));
printf("hash: %s\n", hash);
free(next);
}else{
int x,y;
MPI_Status status;
for(i = 0; i < its; i++){
MPI_RECIVE(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,0,&status);
if(status.MPI_ERROR){
MPI_Abort(MPI_COMM_WORLD,2);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
for (x = 1; x <= XSIZE; x++) {
to[y*world_rank][x ] = transition(from, x , y*world_rank);
}
}
MPI_SEND(to,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,1,MPI_COMM_WORLD);
}
}
MPI_Finalize();
free(from);
free(to);
free(hash);
return 0;
}
This is a C a Sequence implementation which I wrote for the university as a homework assignment.
Are you talking about MPI_Send and MPI_Recv ?
Don't know about any MPI_SEND or MPI_RECIV function...
I think you just mispelled them.
BTW: here is a great tutorial about how to use them http://mpitutorial.com/tutorials/mpi-send-and-receive/

Brute force algorithm causes undefined behaviour

I have to create a program for an assignment that solves a sudoku puzzle. User needs to enter the name of a binary file (NOT a true binary file, it just has a .bin extension, it can be opened with notepad, notepad++ etc. as well) that contains numbers. Those numbers represent coordinates on the puzzle as well as the number contained in those coordinates e.g 432 means 4th row 3rd column contains number 2. After filling out the puzzle i need to solve it and print it on screen. After executing the program it crashed, so I decided to use MSVC 2017 debugger which is among the best according to some developers to find and fix the bug. Here is my code:
Sudoku.c
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h"
#include "sudokulib.h"
#define MALLOC_ERROR 0xFF
#define FILE_NOT_FOUND 0xFFF
#define ROWS 9
#define COLUMNS 9
int main(int argc, char ** argv)
{
char **matrix;
int i, args;
int row, column, num;
FILE * fp;
char * filename;
char * importedData;
matrix = (char **)malloc(ROWS * sizeof(char *));
if (!matrix)
exit(MALLOC_ERROR);
for (i = 0; i<ROWS; ++i)
{
matrix[i] = (char *)malloc(COLUMNS * sizeof(char));
if (!matrix[i])
exit(MALLOC_ERROR);
}
initSudoku(matrix);
printf ("Give me the name of data file: ");
filename = (char *)malloc(100 * sizeof(char));
if (!filename)
exit(MALLOC_ERROR);
scanf("%99s", filename);
fp = fopen(filename, "rb");
if (!fp)
{
printf ("File not found\n");
exit(FILE_NOT_FOUND);
}
importedData = (char *)malloc(sizeof(char)*ROWS*COLUMNS * 3);
if (!importedData)
exit (MALLOC_ERROR);
args = fread(importedData, 1, 243, fp);
i = 0;
while (importedData[i] != ' ' && importedData[i + 1] != ' ' && importedData[i + 2] != ' ' && importedData[i] >= '1' && importedData[i + 1] >= '1' && importedData[i + 2] >= '1' && importedData[i] <= '9' && importedData[i + 1] <= '9' && importedData[i + 2] <= '9' && i < 243)
{
row = importedData[i] - '0' - 1; /* Convert from ascii code to number */
column = importedData[i + 1] - '0' - 1;
num = importedData[i + 2] - '0';
matrix[row][column] = num;
i = i + 3;
}
printf("Sudoku after importing data:\n\n");
printSudoku(matrix);
system("pause");
if (solvePuzzle(matrix))
{
printSudoku(matrix);
}
else
printf ("Puzzle has no solution\n");
fclose(fp);
free(filename);
for (i = 0; i<9; ++i)
{
free(matrix[i]);
}
free(matrix);
return 0;
}
Sudokulib.h
#pragma once
#include <stdlib.h>
#include <stdio.h>
/* Function Prototypes Begin Here */
void printSudoku(char **);
void initSudoku(char **);
int checkRow(char **, int, int);
int checkCol(char **, int, int);
int check3x3(char **, int, int, int);
int checkIfEmpty(char **, int*, int*);
int solvePuzzle (char **);
/* Function Prototypes End Here */
void printSudoku(char ** Mat)
{
int i, j;
for (i = 0; i<9; ++i)
{
printf ("-------------------\n");
printf("|");
for (j = 0; j<9; ++j)
{
printf("%d|", Mat[i][j]);
}
printf("\n");
}
printf ("-------------------\n");
}
void initSudoku(char ** Mat)
{
int i, j;
for (i = 0; i<9; ++i)
for (j = 0; j<9; ++j)
Mat[i][j] = 0;
}
int checkRow (char ** Mat, int row, int num) // if row is free returns 1 else returns 0
{
int col;
for (col = 0; col < 9; col++)
{
if (Mat[row][col] == num)
{
return 0;
}
}
return 1;
}
int checkCol (char ** Mat, int col, int num) // if column is free returns 1 else returns 0
{
int row;
for (row = 0; row < 9; row++)
{
if (Mat[row][col] == num)
{
return 0;
}
}
return 1;
}
int check3x3 (char ** Mat, int row, int col, int num) // if number doesnt exist in the 3x3 grid returns 1 else returns 0
{
row = (row / 3) * 3; // set to first row in the grid
col = (col / 3) * 3; // set to first col in the grid
int i;
int j;
for (i = 0; i < 3; i++) // grid is 3x3
{
for (j = 0; j < 3; j++)
{
if (Mat[row + i][col + j] == num)
{
return 0;
}
}
}
return 1;
}
int isValid (char ** Mat, int row, int col, int num)
{
return (checkRow(Mat, row, num) && checkCol(Mat, col, num) && check3x3(Mat, row, col, num));
}
int checkIfPuzzleSolved (char ** Mat, int *row, int *col) // if function finds a box empty (puzzle not solved) returns 0 else returns 1
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
printf("ROW: %d COL: %d\n",*row,*col);
if (Mat[*row][*col] == 0)
{
return 0;
}
}
}
return 1;
}
int solvePuzzle (char ** Mat)
{
int row;
int col;
if (checkIfPuzzleSolved(Mat, &row, &col))
{
return 1;
}
int num;
for (num = 1; num <= 9; num++)
{
//if (checkRow (Mat,row,num) && checkCol (Mat,col,num) && check3x3 (Mat,row,col,num))
if (isValid(Mat, row, col, num))
{
Mat[row][col] = num;
if (solvePuzzle(Mat))
return 1;
Mat[row][col] = 0;
}
}
return 0;
}
The debugger found a bug at this function:
int checkIfPuzzleSolved (char ** Mat, int *row, int *col) // if function finds a box empty (puzzle not solved) returns 0 else returns 1
{
for (*row = 0; *row < 9; *row++)
{
for (*col = 0; *col < 9; *col++)
{
printf("ROW: %d COL: %d\n",*row,*col);
if (Mat[*row][*col] == 0) /* DEBUGGER ERROR CODE 0xC0000005: Access violation reading location 0xCDCA247C
{
return 0;
}
}
}
return 1;
}
Two things that confused me:
1) I don't understand the reason solvePuzzle gets stuck brute forcing the first box in the puzzle (1st row 1st column). It seems that checkIfPuzzleSolved thinks that the first box is empty (containing 0), even though using printSudoku I can see the algorithm modifying that box toggles its value between 3 and 4 and obviously 0 != 3 and 0 != 4.
2) In checkIfPuzzleSolved, printf prints on screen row and column number and it constantly produces the following result:
ROW: 0 COL: 0
ROW: 0 COL: 0
ROW: 0 COL: -858993460
Also double checked this with the debugger and the values are indeed those mentioned.
My train of thought was the following:
1) Use checkIfEmpty to determine if a box of the puzzle contained 0, that would mean that the puzzle would not be solved yet. Row and col variables are sent into the function by reference, so when function finds an empty box and returns, row and col would save the coordinates of the empty box.
2) In the loop, call checkRow, checkCol and check3x3 to check if a number can be put into the desired box without breaking the sudoku rules. isValid is there for readability purposes.
3) Call solvePuzzle recursively until the puzzle is solved, meanwhile if a number is wrong, reset it to 0.
I have tried everything i could think of to solve this problem, wasting hours reading again and again my code to find a logical error, but everything seems okay. Any ideas?
EDIT: On request of Michael Beer, here is a sample binary file:
data.bin
142156177191216228257289311329364375418422441484534546562579625663682698739743787794824855883896917933951968
*row++; parses as *(row++);, which is equivalent to just row++. You're incrementing the pointer, not the counter.
– melpomene
I see. So am I incrementing the pointer by sizeof(int) and not increasing the value that it refers to by 1? If so what is the correct way of writing "increment the value of the address you are pointing to by 1" regarding the syntax?
(*row)++ or ++(*row) or ++*row or *row += 1.
– melpomene

Dynamic Program in C

Hi Guys i have edited the questions.Here is my entire code.I have given basic amount of readability to my program.I hope u guys can understand the program.
#include<stdio.h>
#include<stdlib.h>
int Max_Min(int,int,int,int *, int *);
int *Max,Number;
int main()
{
int n1, n2,Maximum_Element=0,*Max;
int i = 0, j = 0;
scanf("%d",&Number);
Max =(int *) malloc(sizeof(int)*Number);//Array Max is created
for (int k = 0;k <(Number/2);k++)
{
scanf("%d", &n1);
scanf("%d", &n2);
Max[k] = Max_Min(0,1,0,&n1,&n2);//Passing integer elements n1,n2 with flag 0
}
Maximum_Element=Max_Min(1,1,((sizeof(Max)*Number)/8),Max,Min);//Passing array elements Max,Min with flag 1 to function Max_Min
printf("Maximum_Element=%d", Maximum_Element);
return 0;
}
int Max_Min(int flag,int Max_Min_flag,int length,int *n1,int *n2)//n1 and n2 should be able to handle array and integers
{
int i=0,j = 0,k1,k2,Min1 = 0, Min2 = 0,count=0, Not_Zero = 0,x=0,y=0, *New_Max = 0,*New_Min;
/*Recursive Loop for splitting the array elements and calling the array */
if (flag == 1)
{
New_Max = (int *)(malloc(sizeof(int)*length));
for (;i <= ((length) / 2);i = i + 2)//
{
k1 = n1[i];
j = i + 1;
if (j <= ((length + 1) / 2))
{
k2 = n1[j];
New_Max[count] = Max_Min(0, 1, 0, &k1, &k2);//It is passing integer elements with flag 0 to function Max_Min
count++;
}
}
New_Max[count] = n1[j + 1];
for (int i = 0;i < count + 1;i++)
{
**/* Problem is assigning Max[i]=New_Max[i] is not getting assigned*/**
Max[i] = New_Max[i];//Copying from New_Max to Max because New_Max will be overwritten,so possible chaunce of dataloss
Not_Zero++;
}
while ((sizeof(Max) / 4 - (Not_Zero))>0)
{
Max[Not_Zero] = 0;
Not_Zero++;
}
/*Logic for calling recursive functions based on the count*/
if (count > 1)
{
count--;
Max_Min(1, 1, count, Max, Min);//Calling Recursive function by Passing Entire Arrays with flag 1.
}
else if (count == 1 && Max[1] == 0)
{
*n1 = Max[0];
*n2 = Min[0];
}
else if (count == 1 && Max[2] == 0)
{
Max_Min(1, 1, count + 1, Max, Min);
count--;
}
}
/*Logic for Finding Maximum & Minimum element is present down*/
if (flag == 0)
{
printf("flag");
if (Max_Min_flag == 1)
{
if (*n1 > *n2)
{
}
else if ((*n1 < *n2) && Max_Min_flag == 1)
{
int temp = 0;
temp = *n1;//5
*n1 = *n2;//7
*n2 = temp;//5
}
}
else if (Max_Min_flag == 2)
{
if (*n1 > *n2)//7>2
{
int temp = 0;
temp = *n1;//2
*n1 = *n2;//2
*n2 = temp;//2,7
}
else if (*n1 < *n2)
{
}
}
}
return *n1;//7
}
Problem is assigning Max[i]=New_Max[i] in function Max_Min().It shows Run time error as "Access violation writing location 0x00000000."
First you need to #include <stdlib.h> to use malloc
You must declare your function before using it.
func must return int*.
Also in func "n", first "Max", and second "Max" needs to be the same variable. Rename "n" to "Max"
This is the code corrected with an extra printf;
#include <stdio.h>
#include <stdlib.h>
int *Max,Number=5;
int* func(int *Max)
{
for(int j=0;j<5;j++)
Max[j]=j;//Its not working in this line
return Max;
}
int main()
{
Max=(int *) malloc(sizeof(int)*Number);
for(int i=0;i<5;i++)
Max[i]=i;
int* x = func(Max);
for(int i=0;i<5;i++)
printf("%d", x[i]);
}
The following contains only minor adaptations of your code and it runs fine:
int *func(int *n);
int *Max,Number=5;
int main()
{
int *x,i;
Max=(int *) malloc(sizeof(int)*Number);
for(i=0;i<Number;i++)
Max[i]=i;
x=func(Max);
free(Max);
return(0);
}
int *func(int *n)
{
int j;
for (j=0;j<Number;j++)
n[j]=Number-j; // reverse the number, just to check
return Max;
}

karger Minimum Cut algo crashes for big input

I try to implement the karger Minimum Cut algorithm (Karger wiki page)
So far, I have tried my algorithm on small examples (input of size 10) and it seems to work. But when I try to have a bigger input, let's say 200. It just crashes.
To store the minimum cut data, I create a 2D array: GraphCut[SIZE_ARRAY][SIZE_ARRAY_2]
SIZE_ARRAY = 200 in this case, but I can't find a good length for SIZE_ARRAY_2.
Issue is, SIZE_ARRAY_2 has to be big as I modify the initial array to merge the different vertices.
If I declare SIZE_ARRAY_2 = 200, the size won't be enough, but if i put SIZE_ARRAY_2 = 1000, the program just crashes.
The thing is, I have to execute the algorithm 100000 times.
Here is parts of the code:
#define ARRAY_SIZE 200
#define ARRAY_SIZE_2 200
int main()
{
int minCut,minMinCut;
for (int k = 0; k < ARRAY_SIZE * ARRAY_SIZE * 4;k++) {
minCut = kargerMinCut(k);
if (k == 0)
minMinCut = minCut;
else if (minMinCut > minCut)
minMinCut = minCut;
}
printf("\n minMinCut = %d\n", minMinCut);
return 0;
}
int kargerMinCut(int k) {
// 1st dimension: each different node
// 2nd dimension: vertices
long graphCut[ARRAY_SIZE + 1][ARRAY_SIZE_2] = {0};
populateIntegerArray(graphCut); // import data from a file
int nodeToMain[ARRAY_SIZE + 1];
int sizeOfMainNode, indexToMerge,initialRand,i,j,m,nodeToMerge,nodeRemaining = ARRAY_SIZE;
for (m = 0;m<ARRAY_SIZE + 1;m++) // initialization of nodeToMain
nodeToMain[m] = m;
while (nodeRemaining > 2) {
i = 0;
j = 0;
srand(time(NULL) + nodeRemaining);// initialise rand
initialRand = nodeToMain[rand()%(ARRAY_SIZE) + 1]; // pick a random initial node, but not a merged one
sizeOfMainNode = sizeOfArray(graphCut[initialRand]); // size of the initial node
srand(time(NULL) + k); // initialise rand
indexToMerge = rand()%sizeOfMainNode;// pick another random node in the linked nodes (its index to be precise)
nodeToMerge = nodeToMain[graphCut[initialRand][indexToMerge]];
for (m = 0;m<ARRAY_SIZE + 1;m++) // update the nodeToMain array, initialRand is now the main node for nodeToMerge
if (nodeToMain[m] == nodeToMerge)
nodeToMain[m] = initialRand;
// remove the nodeToMerge numbers from the graphCut[initialRand] (as they are going to be merged)
while(graphCut[initialRand][j] > 0 && j < sizeOfMainNode) {
if (initialRand == nodeToMain[graphCut[initialRand][j]]) {
// if this is the last element, do nothing
while(nodeToMain[graphCut[initialRand][sizeOfMainNode - 1]] == initialRand && j < sizeOfMainNode - 1) {
graphCut[initialRand][sizeOfMainNode - 1] = 0;
sizeOfMainNode--;
}
graphCut[initialRand][j] = nodeToMain[graphCut[initialRand][sizeOfMainNode - 1]];
graphCut[initialRand][sizeOfMainNode - 1] = 0;
sizeOfMainNode--;
}
j++;
}
i = 0;
while (graphCut[nodeToMerge][i] > 0 && sizeOfMainNode < ARRAY_SIZE_2 && i < ARRAY_SIZE_2) { // add each vextex of the nodeTomerge to the merged nodes
if (nodeToMain[graphCut[nodeToMerge][i]] != initialRand) {
graphCut[initialRand][sizeOfMainNode] = nodeToMain[graphCut[nodeToMerge][i]];
sizeOfMainNode++;
}
i++;
}
nodeRemaining--;
}
return sizeOfArray(graphCut[nodeToMain[1]]);
}
I'm sure that the code is not really clean, maybe even really bad (beginner in C). So i Welcome any other advice.
The errors I get with the debugger seems really random.
Error is:
Impossible to divide by 0
it stops in time64.c at line 62
tim = (__time64_t)((nt_time.ft_scalar - EPOCH_BIAS) / 10000000i64);
The change in array size is probably causing a stack overflow. A common default size for the stack is 1MB (1048576 bytes). If you have:
long graphCut[200][1000];
and 4 == sizeof(long) the graphCut array is taking up 200 * 1000 * 4 = 800000 bytes, which leaves 248576 bytes which may not be enough for the stack variables in populateIntegerArray() function (I don't see that function). If 8 == sizeof(long) then the array would require 1600000 bytes, which is greater than 1MB.
If an array of that size is required then allocate (all or part) on the heap instead of the stack. For example:
long* graphCut[ARRAY_SIZE_1];
int i;
for (i = 0; i < sizeof(graphCut)/sizeof(graphCut[0]); i++)
{
graphCut[i] = malloc(ARRAY_SIZE_2 * sizeof(graphCut[0][0]));
memset(graphCut[i], 0, ARRAY_SIZE_2 * sizeof(graphCut[0][0]));
}
for (i = 0; i < sizeof(graphCut)/sizeof(graphCut[0]); i++)
{
free(graphCut[i]);
}
Some possible problems are integer or stack overflow (so you're on the right site) and memory initialization.
This implementation should allocate graphCut on the heap, and zero it every time kargerMin gets called, thus addressing those problems.
int minCut, minMinCut;
// There is a small possibility that ARRAY_SIZE*ARRAY_SIZE*4 exceeds int boundary if 16-bit
long k;
long **buffer;
// Allocate graphCut on the heap
buffer = malloc((ARRAY_SIZE + 1)*sizeof(long *));
for (k = 0; k < ARRAY_SIZE + 1; k++)
buffer[k] = malloc(ARRAY_SIZE_2*sizeof(long));
for (k = 0; k < ARRAY_SIZE * ARRAY_SIZE * 4;k++) {
minCut = kargerMinCut(k, buffer);
if (k == 0)
minMinCut = minCut;
else if (minMinCut > minCut)
minMinCut = minCut;
}
printf("\n minMinCut = %d\n", minMinCut);
// Here we free the buffer. We could do it in any order, but
// as it costs nothing here to do so, we free it in reverse-
// allocation-order to avoid any possible memory fragmentation
// - which is moot anyway, if this is a main() and we're exiting
// the program. In other instances it could be relevant.
for (k = 0; k < ARRAY_SIZE + 1; k++)
{
free(buffer[ARRAY_SIZE-k]); buffer[ARRAY_SIZE-k] = NULL;
}
free(buffer); buffer = NULL;
// The NULLing of the just-freed variables has no purpose except
// to GUARANTEE that any illegal use of them, dangling pointers,
// leftover copies etc. will immediately trigger a core dump and
// be discovered, instead of lurking undetected.
return 0;
}
int kargerMinCut(long k, long **graphCut) {
// 1st dimension: each different node
// 2nd dimension: vertices
// Zero graphCut. If populateIntegerArray rewrites
// the whole of graphCut, these four lines are redundant.
int i, j;
for (i = 0; i < ARRAY_SIZE + 1; i++)
for (j = 0; j < ARRAY_SIZE_2; j++)
graphCut[i][j] = 0;
// otherwise, they make sure that no old value of graphCut
// or uninitialised value is going to linger and potentially
// corrupt calculations later on.
populateIntegerArray(graphCut); // import data from a file
I have implemented the Karger algorithm in C++. My code below works on large files but I have not optimized enough...it still runs fast though..but could be faster..Try this solution.
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <list>
#include <fstream>
#include <sstream>
#include <set>
#include <stdlib.h>
#include <time.h>
int pick_edge(std::map <int, std::list<int>> g2, set<int> myset, int &u, int &v)
{
std::map <int, std::list<int>>::iterator it;
std::list<int> eachRow;
int rand_vertex;
int rand_edge;
srand (time(NULL));
rand_vertex = (rand() + 1) % myset.size() ;
if (rand_vertex == 0)
rand_vertex = 1;
u = get_value_at_i(myset, rand_vertex);
for (it = g2.begin(); it != g2.end(); ++it) {
if (it->first == u) {
eachRow = it->second;
rand_edge = (rand() + 1) % eachRow.size();
if (rand_edge == 0)
rand_edge = 1;
v = get_edge_at_j(eachRow, rand_edge);
break;
}
}
return 0;
}
map <int, std::list<int>> merge_uv(map <int, std::list<int>> g2, int u, int v)
{
std::map <int, std::list<int>>::iterator it_g;
std::map <int, std::list<int>>::iterator it_u;
std::map <int, std::list<int>>::iterator it_v;
std::list<int>::iterator iter_l;
std::list<int> eachRow, uRow, vRow;
std::list<int> newRow;
int vertex;
int j = 0;
map <int, std::list<int>> new_Graph_G;
vRow.clear();
uRow.clear();
eachRow.clear();
newRow.clear();
for (it_g = g2.begin(); it_g != g2.end(); ++it_g) {
vertex = it_g->first;
eachRow = it_g->second;
if (vertex == u) {
uRow = it_g->second;
it_u = it_g;
j++;
continue;
}
if (vertex == v) {
vRow = it_g->second;
it_v = it_g;
j++;
continue;
}
}
if (j == 2) {
uRow.sort();
vRow.sort();
// uRow.merge(vRow);
for (std::list<int>::iterator ite = vRow.begin(); ite != vRow.end(); ++ite) {
if (*ite != u) {
uRow.push_back(*ite);
}
}
g2.erase(v);
g2[u] = uRow;
}
for (it_g = g2.begin(); it_g != g2.end(); ++it_g) {
eachRow = it_g->second;
for (std::list<int>::iterator ite = eachRow.begin(); ite != eachRow.end(); ++ite) {
if (*ite == v && *ite != it_g->first) {
newRow.push_back(u);
} else if (*ite == it_g->first) {
continue;
} else {
newRow.push_back(*ite);
}
}
new_Graph_G[it_g->first] = newRow;
newRow.clear();
}
for (it_g = g2.begin(); it_g != g2.end(); ++it_g) {
eachRow = it_g->second;
if (it_g->first == u) {
for (std::list<int>::iterator ite = eachRow.begin(); ite != eachRow.end(); ++ite) {
if (*ite != u && *ite != v) {
newRow.push_back(*ite);
}
}
new_Graph_G[it_g->first] = newRow;
break;
}
}
return new_Graph_G;
}
int get_min_cut(std::map <int, std::list<int>> g1)
{
int v;
std::list<int> eachRow;
std::map <int, std::list<int>>::iterator it_g;
int min_cut = 0;
for (it_g = g1.begin(); it_g != g1.end(); ++it_g) {
eachRow = it_g->second;
v = it_g->first;
for (std::list<int>::iterator ite = eachRow.begin(); ite != eachRow.end(); ++ite) {
if (*ite != v) {
min_cut++;
}
}
break;
}
return min_cut;
}
int EdgeContractionAlgorithm()
{
std::map <int, std::list<int>>::iterator it;
int min_cut = 0;
int vertex = 1;
std::list<int> eachRow;
std::set<int> myset;
std::set<int>::iterator itSet;
std::map <int, std::list<int>> g2;
int edge;
int n_vertices;
int cnt = 0;
int u, v;
n_vertices = Cal_nVertices(myset, Graph_G);
g2 = Graph_G;
// Contraction algorithm.
while (n_vertices > 2) {
edge = pick_edge(g2, myset, u, v);
g2 = merge_uv(Graph_G, u, v);
n_vertices = g2.size();
myset.erase (myset.find(v));
Graph_G = g2;
}
print_graph(g2);
min_cut = get_min_cut(g2);
return (min_cut);
}

Resources