0

I have an assignment to solve a Knapsack problem from a set of dataset i'm given and one of the ways i have to do solve it with is branch and bound depth first The program below works fine when given a dataset with a capacity of 100000 and number of items being 30 but when that increases to 341045 capacity and number of items being 50 the program gives me an error memory allocation failed not enough space I've tried dynamically allocating memory, program slows down to a crawl I've tried freeing up memory, i get errors I've tried to run the program with saving the selected items to only have a final value and free capacity, same issue not enough space for memory allocation so any help would be appreciated

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct {
    int weight;
    int value;
} Item;
typedef struct Node {
    int value;
    int weight;
    int estimate;
    int level;
    int* selected; //pointer toy selected
} Node;
typedef struct QueueNode {
    Node data;
    struct QueueNode* next;
} QueueNode;

typedef struct {
    QueueNode* front;
    QueueNode* rear;
} Queue;

// Function to create a new queue
Queue* createQueue() {
    Queue* queue = (Queue*)malloc(sizeof(Queue));
    if (queue == NULL) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }
    queue->front = queue->rear = NULL;
    return queue;
}

Node createNode(int value, int weight, int estimate, int level, int* selected, int length) {
    Node newNode;
    newNode.value = value;
    newNode.weight = weight;
    newNode.estimate = estimate;
    newNode.level = level;
    newNode.selected = (int*)malloc(length * sizeof(int)); // Allocate memory for the selected array
    if (newNode.selected == NULL) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < length; i++) {
        newNode.selected[i] = selected[i];
    }
    return newNode;
} 

//Function to check if the queue is empty
int isEmpty(Queue* queue) {
    return queue->front == NULL;
}

// Function to enqueue a node
void enqueue(Queue* queue, Node newNode) {
    QueueNode* newNodePtr = (QueueNode*)malloc(sizeof(QueueNode));
    if (newNodePtr == NULL) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }
    newNodePtr->data = newNode;
    newNodePtr->next = NULL;

    if (queue->rear == NULL) {
        queue->front = queue->rear = newNodePtr;
        return;
    }

    queue->rear->next = newNodePtr;
    queue->rear = newNodePtr;
}

// Function to dequeue a node
Node dequeue(Queue* queue) {
    if (isEmpty(queue)) {
        perror("Queue is empty");
        exit(EXIT_FAILURE);
    }

    QueueNode* temp = queue->front;
    Node data = temp->data;
    queue->front = queue->front->next;

    if (queue->front == NULL)
        queue->rear = NULL;

    free(temp);
    return data;
}

// Function to free the memory occupied by the queue
void freeQueue(Queue* queue) {
    while (!isEmpty(queue)) {
        dequeue(queue);
    }
    free(queue);
}
int main() {
    FILE *file;
    char filename[] = "pr2_50"; //ONOMA FILE
    int K, N;
    clock_t start, end;
    double cpu_time_used;

    start = clock();

    // Open file
    file = fopen(filename, "r");
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }
    fscanf(file, "%d %d", &K, &N); //K=Knapsack Capacity, N=Number of items
    
    // Allocate memory for items
    Item *items = (Item *)malloc(N * sizeof(Item));
    if (items == NULL) {
        perror("Memory allocation failed");
        fclose(file);
        return 1;
    }
    int optimistic_value=0;
    // Read items from file
    for (int i = 0; i < N; i++) {
        if (fscanf(file, "%d %d", &items[i].weight, &items[i].value) != 2) {
            perror("Error reading file");
            fclose(file);
            return 1;
        }
        optimistic_value=optimistic_value+items[i].value;
    }
    fclose(file);
    int level=0;
    int max = 0;
    int maxw=0;
    Queue* queue = createQueue();
    int current_value=0;
    int current_weight=0;
    int selection[N];
    int finalselection[N];
    for (int i=0;i<N;i++) {
        selection[i] = 0;
        finalselection[i] = 0;
    }
    Node newNode = createNode(current_value, current_weight, optimistic_value, level, selection, N);
    enqueue(queue, newNode);
    while(!isEmpty(queue))
    {
      Node currentNode = dequeue(queue);
      level = currentNode.level+1;
      if (level<=N){
        current_weight = currentNode.weight;
        current_value = currentNode.value;
        optimistic_value = currentNode.estimate;
        int *selection = (int *)malloc(N * sizeof(int));
        if (selection == NULL) {
            perror("Memory allocation failed");
            exit(EXIT_FAILURE);
        }
        for (int i = 0; i < level - 1; i++) {
            selection[i] = currentNode.selected[i];
        }
        if(current_weight+items[level-1].weight<=K && optimistic_value>max)
        {
            selection[level-1]=1;
            Node additem = createNode(current_value+items[level-1].value, current_weight+items[level-1].weight, optimistic_value, level,  selection, N);
            enqueue(queue, additem);
            if (max<additem.value){
                max=additem.value;
                maxw=additem.weight;
                for (int i=0;i<N;i++) {
                    finalselection[i]=selection[i];
                }

            }
        }
        if(optimistic_value>max)
        {
            selection[level-1]=0;
            Node noitem = createNode(current_value, current_weight, optimistic_value-items[level-1].value, level,  selection, N);
            enqueue(queue, noitem);
        }
        free(selection);
      }
      else{
        freeQueue(queue);
        K=K-maxw;
        printf("Selected items:\n");
        for (int i = 0; i < N; i++) {
            if (finalselection[i]==1) {
                printf("Item %d: Weight = %d, Value = %d\n", i+1, items[i].weight, items[i].value);
            }
        }
        free(items);
        break;
      }
      free(currentNode.selected);
    }
    printf("Total value in knapsack is %d \n ", max);
    printf("Backpack capacity: %d\n", K);
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC * 1000; // Convert to milliseconds
    printf("Program executed in %.2f milliseconds.\n", cpu_time_used);
    return 0;
}

Valgrind Report:

==4874== Memcheck, a memory error detector
==4874== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4874== Using Valgrind-3.18.1-42b08ed5bd-20211015 and LibVEX; rerun with -h for copyright info
==4874== Command: ./a.out
==4874== Parent PID: 3343
==4874== 
--4874-- 
--4874-- Valgrind options:
--4874--    --leak-check=full
--4874--    --show-leak-kinds=all
--4874--    --track-origins=yes
--4874--    --verbose
--4874--    --log-file=valgrind-out.txt
--4874-- Contents of /proc/version:
--4874--   Linux version 4.4.0-19041-Microsoft ([email protected]) (gcc version 5.4.0 (GCC) ) #3996-Microsoft Thu Jan 18 16:36:00 PST 2024
--4874-- 
--4874-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3-avx-avx2-bmi-f16c-rdrand-rdseed
--4874-- Page sizes: currently 4096, max supported 4096
--4874-- Valgrind library directory: /usr/libexec/valgrind
--4874-- Reading syms from /home/stratos/a.out
--4874-- Reading syms from /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
--4874--   Considering /usr/lib/debug/.build-id/15/921ea631d9f36502d20459c43e5c85b7d6ab76.debug ..
--4874--   .. build-id is valid
--4874-- Reading syms from /usr/libexec/valgrind/memcheck-amd64-linux
--4874--    object doesn't have a symbol table
--4874--    object doesn't have a dynamic symbol table
--4874-- Scheduler: using generic scheduler lock implementation.
--4874-- Reading suppressions file: /usr/libexec/valgrind/default.supp
==4874== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-4874-by-stratos-on-???
==4874== embedded gdbserver: writing to   /tmp/vgdb-pipe-to-vgdb-from-4874-by-stratos-on-???
==4874== embedded gdbserver: shared mem   /tmp/vgdb-pipe-shared-mem-vgdb-4874-by-stratos-on-???
==4874== 
==4874== TO CONTROL THIS PROCESS USING vgdb (which you probably
==4874== don't want to do, unless you know exactly what you're doing,
==4874== or are doing some strange experiment):
==4874==   /usr/bin/vgdb --pid=4874 ...command...
==4874== 
==4874== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==4874==   /path/to/gdb ./a.out
==4874== and then give GDB the following command
==4874==   target remote | /usr/bin/vgdb --pid=4874
==4874== --pid is optional if only one valgrind process is running
==4874== 
==4874== error calling PR_SET_PTRACER, vgdb might block
--4874-- REDIR: 0x402aa40 (ld-linux-x86-64.so.2:strlen) redirected to 0x580bcec2 (???)
--4874-- REDIR: 0x402a810 (ld-linux-x86-64.so.2:index) redirected to 0x580bcedc (???)
--4874-- Reading syms from /usr/libexec/valgrind/vgpreload_core-amd64-linux.so
--4874--    object doesn't have a symbol table
--4874-- Reading syms from /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so
--4874--    object doesn't have a symbol table
==4874== WARNING: new redirection conflicts with existing -- ignoring it
--4874--     old: 0x0402aa40 (strlen              ) R-> (0000.0) 0x580bcec2 ???
--4874--     new: 0x0402aa40 (strlen              ) R-> (2007.0) 0x0484ee30 strlen
--4874-- REDIR: 0x4027220 (ld-linux-x86-64.so.2:strcmp) redirected to 0x484fcd0 (strcmp)
--4874-- REDIR: 0x402afa0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4853840 (mempcpy)
--4874-- Reading syms from /usr/lib/x86_64-linux-gnu/libc.so.6
--4874--   Considering /usr/lib/debug/.build-id/c2/89da5071a3399de893d2af81d6a30c62646e1e.debug ..
--4874--   .. build-id is valid
==4874== WARNING: new redirection conflicts with existing -- ignoring it
--4874--     old: 0x0490dc60 (memalign            ) R-> (1011.0) 0x0484e080 memalign
--4874--     new: 0x0490dc60 (memalign            ) R-> (1017.0) 0x0484e050 aligned_alloc
==4874== WARNING: new redirection conflicts with existing -- ignoring it
--4874--     old: 0x0490dc60 (memalign            ) R-> (1011.0) 0x0484e080 memalign
--4874--     new: 0x0490dc60 (memalign            ) R-> (1017.0) 0x0484e020 aligned_alloc
==4874== WARNING: new redirection conflicts with existing -- ignoring it
--4874--     old: 0x0490dc60 (memalign            ) R-> (1011.0) 0x0484e080 memalign
--4874--     new: 0x0490dc60 (memalign            ) R-> (1017.0) 0x0484e050 aligned_alloc
==4874== WARNING: new redirection conflicts with existing -- ignoring it
--4874--     old: 0x0490dc60 (memalign            ) R-> (1011.0) 0x0484e080 memalign
--4874--     new: 0x0490dc60 (memalign            ) R-> (1017.0) 0x0484e020 aligned_alloc
--4874-- REDIR: 0x4910720 (libc.so.6:strnlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49109e0 (libc.so.6:strpbrk) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49102e0 (libc.so.6:strcmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x492ecd0 (libc.so.6:wcsnlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49116d0 (libc.so.6:memset) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x492d540 (libc.so.6:wcslen) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911c10 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x492d370 (libc.so.6:wcschr) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4910260 (libc.so.6:index) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4910960 (libc.so.6:rindex) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49115a0 (libc.so.6:memmove) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
==4874== Preferring higher priority redirection:
--4874--     old: 0x04a087c0 (__memcpy_avx_unalign) R-> (2018.0) 0x04850f90 __memcpy_avx_unaligned_erms
--4874--     new: 0x04a087c0 (__memcpy_avx_unalign) R-> (2018.1) 0x04852880 memmove
--4874-- REDIR: 0x492d3f0 (libc.so.6:wcscmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49119e0 (libc.so.6:stpncpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x492d9b0 (libc.so.6:wmemchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4910830 (libc.so.6:strncmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911a70 (libc.so.6:strcasecmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4910420 (libc.so.6:strcspn) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x492d470 (libc.so.6:wcscpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49101d0 (libc.so.6:strcat) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911b60 (libc.so.6:strncasecmp_l) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911480 (libc.so.6:bcmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4919570 (libc.so.6:memrchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4913010 (libc.so.6:strchrnul) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4910390 (libc.so.6:strcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911b10 (libc.so.6:strcasecmp_l) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49106a0 (libc.so.6:strlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49108d0 (libc.so.6:strncpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911950 (libc.so.6:stpcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49113f0 (libc.so.6:memchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4910b00 (libc.so.6:strspn) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x49117d0 (libc.so.6:mempcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4911ac0 (libc.so.6:strncasecmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4912f80 (libc.so.6:rawmemchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper)
--4874-- REDIR: 0x4a05610 (libc.so.6:__strrchr_avx2) redirected to 0x484e810 (rindex)
--4874-- REDIR: 0x490d0a0 (libc.so.6:malloc) redirected to 0x4848820 (malloc)
--4874-- REDIR: 0x4910fc0 (libc.so.6:__GI_strstr) redirected to 0x4853ae0 (__strstr_sse2)
--4874-- REDIR: 0x490d3e0 (libc.so.6:free) redirected to 0x484b210 (free)
--4874-- REDIR: 0x4a057e0 (libc.so.6:__strlen_avx2) redirected to 0x484ed10 (strlen)
--4874-- REDIR: 0x4a05400 (libc.so.6:__strchrnul_avx2) redirected to 0x4853330 (strchrnul)
--4874-- REDIR: 0x4a08780 (libc.so.6:__mempcpy_avx_unaligned_erms) redirected to 0x4853440 (mempcpy)
==4874== Conditional jump or move depends on uninitialised value(s)
==4874==    at 0x109D76: main (asd.c:195)
==4874==  Uninitialised value was created by a heap allocation
==4874==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==4874==    by 0x109A72: main (asd.c:160)
==4874== 
--4874-- REDIR: 0x4a087c0 (libc.so.6:__memcpy_avx_unaligned_erms) redirected to 0x4852880 (memmove)
==4874== 
==4874== HEAP SUMMARY:
==4874==     in use at exit: 1,562,760 bytes in 13,023 blocks
==4874==   total heap usage: 158,459 allocs, 145,436 frees, 13,990,336 bytes allocated
==4874== 
==4874== Searching for pointers to 13,023 not-freed blocks
==4874== Checked 107,456 bytes
==4874== 
==4874== 1,562,760 bytes in 13,023 blocks are definitely lost in loss record 1 of 1
==4874==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==4874==    by 0x10932D: createNode (asd.c:43)
==4874==    by 0x109CEB: main (asd.c:185)
==4874== 
==4874== LEAK SUMMARY:
==4874==    definitely lost: 1,562,760 bytes in 13,023 blocks
==4874==    indirectly lost: 0 bytes in 0 blocks
==4874==      possibly lost: 0 bytes in 0 blocks
==4874==    still reachable: 0 bytes in 0 blocks
==4874==         suppressed: 0 bytes in 0 blocks
==4874== 
==4874== ERROR SUMMARY: 10 errors from 2 contexts (suppressed: 0 from 0)
==4874== 
==4874== 9 errors in context 1 of 2:
==4874== Conditional jump or move depends on uninitialised value(s)
==4874==    at 0x109D76: main (asd.c:195)
==4874==  Uninitialised value was created by a heap allocation
==4874==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==4874==    by 0x109A72: main (asd.c:160)
==4874== 
==4874== ERROR SUMMARY: 10 errors from 2 contexts (suppressed: 0 from 0)
12
  • What is the space complexity of your algorithm? It sounds like you're running into combinatorial explosion and can't keep all the data for such large data sets. Commented Apr 11, 2024 at 19:43
  • 1
    The dominant factor in space complexity is the queue, which can grow a whole lot more than the number of items(N) At worse case senario, every item creates a node where it was added and one where it wasnt in the current selection. Therefore(i think), the overall space complexity of the algorithm is O(2^N). Commented Apr 11, 2024 at 19:55
  • 1
    And do you realize how big 2^50 is? Commented Apr 11, 2024 at 19:56
  • 2
    en.wikipedia.org/wiki/Wheat_and_chessboard_problem Commented Apr 11, 2024 at 19:58
  • Yeah, i know. The datasets arent created by me, and i cant think of a way to reduce it down. My initial idea was the optimistic_value, if the potential value of the node was smaller than the max value that has been found so far, to not crteate that node and move to the next to cut down on the number of nodes made. Commented Apr 11, 2024 at 20:00

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.