124 lines
4.6 KiB
LLVM
124 lines
4.6 KiB
LLVM
; 0/1 Knapsack Problem (Recursive solution)
|
|
; * Input: array of weights, array of values, and a capacity of a knapsack
|
|
; * Output: the maximum value that can be obtained by selecting items,
|
|
; while keeping the total weight within the capacity of the knapsack.
|
|
|
|
; operates on a struct of an array
|
|
; uses recursion
|
|
; one helper function with use of call instruction
|
|
|
|
%arraystruct = type { [5 x i64] }
|
|
|
|
; Test 1: Basic functionality / correctness
|
|
|
|
@weights1 = global %arraystruct {[5 x i64] [i64 2, i64 3, i64 4, i64 5, i64 6]}
|
|
@values1 = global %arraystruct {[5 x i64] [i64 3, i64 4, i64 5, i64 6, i64 7]}
|
|
@capacity1 = global i64 5
|
|
|
|
@expected1 = global i64 7
|
|
|
|
; Test 2: Balance between maximizing the value and staying within the capacity limit
|
|
|
|
@weights2 = global %arraystruct {[5 x i64] [i64 1, i64 2, i64 3, i64 4, i64 5]}
|
|
@values2 = global %arraystruct {[5 x i64] [i64 1, i64 3, i64 4, i64 5, i64 6]}
|
|
@capacity2 = global i64 8
|
|
|
|
@expected2 = global i64 10
|
|
|
|
; Test 3: Lower weights have higher values
|
|
|
|
@weights3 = global %arraystruct {[5 x i64] [i64 5, i64 4, i64 3, i64 2, i64 1]}
|
|
@values3 = global %arraystruct {[5 x i64] [i64 6, i64 5, i64 4, i64 3, i64 2]}
|
|
@capacity3 = global i64 10
|
|
|
|
@expected3 = global i64 14
|
|
|
|
|
|
define i64 @knapsack(i64 %n, %arraystruct* %weights, %arraystruct* %values, i64 %capacity) {
|
|
; %n_minus_1 = sub i64 %n, 1
|
|
; %1 = getelementptr %arraystruct, %arraystruct* %weights, i32 0, i32 0, i64 %n_minus_1
|
|
; %2 = load i64, i64* %1
|
|
; ret i64 %2
|
|
|
|
%is_n_0 = icmp eq i64 %n, 0
|
|
%is_n_1 = icmp eq i64 %capacity, 0
|
|
%base_case = or i1 %is_n_0, %is_n_1
|
|
br i1 %base_case, label %base_case_end, label %continue1
|
|
|
|
base_case_end:
|
|
ret i64 0
|
|
|
|
continue1:
|
|
%n_minus_1 = sub i64 %n, 1
|
|
%w_n_minus_1_ptr = getelementptr %arraystruct, %arraystruct* %weights, i32 0, i32 0, i64 %n_minus_1
|
|
%w_n_minus_1 = load i64, i64* %w_n_minus_1_ptr
|
|
|
|
%2 = icmp sgt i64 %w_n_minus_1, %capacity
|
|
br i1 %2, label %recursive_case1, label %continue2
|
|
|
|
recursive_case1:
|
|
%knapsack_with_n_minus_1 = call i64 @knapsack(i64 %n_minus_1, %arraystruct* %weights, %arraystruct* %values, i64 %capacity)
|
|
ret i64 %knapsack_with_n_minus_1
|
|
|
|
continue2:
|
|
|
|
%val_at_n_minus_1_ptr = getelementptr %arraystruct, %arraystruct* %values, i32 0, i32 0, i64 %n_minus_1
|
|
%val_at_n_minus_1 = load i64, i64* %val_at_n_minus_1_ptr
|
|
|
|
%new_capacity = sub i64 %capacity, %w_n_minus_1
|
|
%knapsack_with_n_minus_1_new_capacity = call i64 @knapsack(i64 %n_minus_1, %arraystruct* %weights, %arraystruct* %values, i64 %new_capacity)
|
|
%left_for_max = add i64 %val_at_n_minus_1, %knapsack_with_n_minus_1_new_capacity
|
|
%right_for_max = call i64 @knapsack(i64 %n_minus_1, %arraystruct* %weights, %arraystruct* %values, i64 %capacity)
|
|
|
|
|
|
%max = icmp sgt i64 %left_for_max, %right_for_max
|
|
br i1 %max, label %include_item, label %dont_include_item
|
|
|
|
include_item:
|
|
ret i64 %left_for_max
|
|
|
|
dont_include_item:
|
|
ret i64 %right_for_max
|
|
}
|
|
|
|
define void @main(i64 %argc, i8** %arcv) {
|
|
; get result of Test 1
|
|
%ptr_weights1 = getelementptr %arraystruct, %arraystruct* @weights1, i32 0
|
|
%ptr_values1 = getelementptr %arraystruct, %arraystruct* @values1, i32 0
|
|
%capacity1_val = load i64, i64* @capacity1
|
|
%res1 = call i64 @knapsack(i64 5, %arraystruct* %ptr_weights1, %arraystruct* %ptr_values1, i64 %capacity1_val)
|
|
|
|
; whether Test 1 passed or not (i1)
|
|
%expected1_val = load i64, i64* @expected1
|
|
%res1_pass = icmp eq i64 %res1, %expected1_val
|
|
|
|
|
|
; get result of Test 2
|
|
%ptr_weights2 = getelementptr %arraystruct, %arraystruct* @weights2, i32 0
|
|
%ptr_values2 = getelementptr %arraystruct, %arraystruct* @values2, i32 0
|
|
%capacity2_val = load i64, i64* @capacity2
|
|
%res2 = call i64 @knapsack(i64 5, %arraystruct* %ptr_weights2, %arraystruct* %ptr_values2, i64 %capacity2_val)
|
|
|
|
; whether Test 2 passed or not (i1)
|
|
%expected2_val = load i64, i64* @expected2
|
|
%res2_pass = icmp eq i64 %res2, %expected2_val
|
|
|
|
|
|
|
|
; get result of Test 3
|
|
%ptr_weights3 = getelementptr %arraystruct, %arraystruct* @weights3, i32 0
|
|
%ptr_values3 = getelementptr %arraystruct, %arraystruct* @values3, i32 0
|
|
%capacity3_val = load i64, i64* @capacity3
|
|
%res3 = call i64 @knapsack(i64 5, %arraystruct* %ptr_weights3, %arraystruct* %ptr_values3, i64 %capacity3_val)
|
|
|
|
; whether Test 3 passed or not (i1)
|
|
%expected3_val = load i64, i64* @expected3
|
|
%res3_pass = icmp eq i64 %res3, %expected3_val
|
|
|
|
|
|
|
|
; return 1 if all tests passed
|
|
%res1_and_res2_pass = and i1 %res1_pass, %res2_pass
|
|
%all_pass = and i1 %res1_and_res2_pass, %res3_pass
|
|
ret i64 %all_pass
|
|
}
|