Problem: Binary RS Band Weighted Veg Indices

The problem aims to create C++ functions that find a binary imagery file AA in test_data paths, read and vertically flip red, NIR, and blue bands, compute weighted vegetation indices (NDVI, RVI, DVI, EVI) with Gaussian/distance weights, and return aggregated results or a composite score for vegetation assessment.


Input/Output: The problem takes integer inputs (band_red, band_nir, optionally band_blue) specifying indices for red, near-infrared (NIR), and blue bands. It locates a 600x600 unsigned char binary file "AA" in three paths: "test_data/AA", "../test_data/AA", or "../../test_data/AA". For each subproblem, it reads the specified bands (vertically flipping rows), computes Gaussian- or distance-weighted vegetation indices (NDVI, RVI, DVI, EVI, or their combination), and returns a double or int: problem_13_1 returns Gaussian-weighted NDVI mean; problem_13_2 returns Gaussian-weighted NIR/red ratio mean (skip zero red); problem_13_3 returns average distance-weighted DVI sum (int); problem_13_4 returns Gaussian-weighted NIR/red ratio mean (skip zero red); problem_13_5 returns Gaussian-weighted EVI mean; problem_13_6 returns weighted sum of normalized indices (0.3 NDVI + 0.25 RVI + 0.2 DVI + 0.25 EVI). If the file is not found, it returns an error value (-1.0 or -1); if weight sums are negligible, it returns 0.0.

Required dependencies:
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <algorithm>
using namespace std;

Sub-steps:
step_number: 1
step_description_prompt: Please write a C++ function named problem_13_1 that takes two integers (band_red, band_nir) as input and returns a double, which computes the Gaussian-weighted NDVI mean from a binary file.
The function is defined as double problem_13_1(int band_red, int band_nir);
Algorithm flow:
1. Check three file paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to find the existing binary file; if none exist, output error and return -1.0.
2. Read 600x600 red band: skip (band_red - 1)*600*600 bytes from file start, read 600 rows each with 600 unsigned char values, store with rows reversed (rows-1-i).
3. Read 600x600 nir band similarly using band_nir.
4. Compute Gaussian-weighted NDVI: center at (300.0, 300.0), sigma = 150.0; for each pixel, if red[i][j]+nir[i][j]>1e-6, calculate NDVI=(nir[i][j]-red[i][j])/(nir[i][j]+red[i][j]), weight=exp(-((i-300.0)^2+(j-300.0)^2)/(2*sigma*sigma)), accumulate weighted_sum_ndvi (NDVI*weight) and weight_sum.
5. Return weighted_sum_ndvi/weight_sum if weight_sum>1e-10 else 0.0.
Functions like ifstream, vector, exp, max are already defined.
function_header: double problem_13_1(int band_red, int band_nir)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 13.1" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    double correct1 = -0.289903;  // Expected value
    int band_red1 = 1, band_nir1 = 4;
    double result1 = problem_13_1(band_red1, band_nir1);
    if (abs(result1 - correct1) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    double correct2 = 0.153520;  // Expected value
    int band_red2 = 2, band_nir2 = 5;
    double result2 = problem_13_1(band_red2, band_nir2);
    if (abs(result2 - correct2) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct2 << ", Got: " << result2 << endl;
    }

    // Test 3
    double correct3 = 0.506923;  // Expected value
    int band_red3 = 3, band_nir3 = 6;
    double result3 = problem_13_1(band_red3, band_nir3);
    if (abs(result3 - correct3) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct3 << ", Got: " << result3 << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 2
step_description_prompt: Please write a C++ function named problem_13_2 that takes two integers band_red and band_nir as inputs and returns a double. This function calculates the Gaussian-weighted mean ratio of NIR to Red bands from a binary data file, including file path searching and band data loading.
Function definition: double problem_13_2(int band_red, int band_nir);
Algorithm flow: 1. Search for the binary file "AA" in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"}; if no path is valid, output "Error: Cannot find data file AA" to cerr and return -1.0. 2. Read Red band data (rows=600, cols=600): open the file, skip (band_red-1)*rows*cols bytes, read each row into a buffer, then store in red array with rows reversed (rows-1-i). 3. Read NIR band data similarly using band_nir. 4. Compute Gaussian-weighted mean: center at (rows/2.0, cols/2.0), sigma=max(rows,cols)/4.0; for each pixel where red[i][j]>0, calculate ratio=nir/red, weight=exp(-dist_sq/(2*sigma²)) (dist_sq is squared distance to center); sum ratio*weight and weight, return their ratio if weight sum >1e-10, else 0.0.
Note: Use ios::binary for file operations. Skip bytes with seekg, read each row of cols bytes, and reverse rows when storing data. Predefined functions are available.
function_header: double problem_13_2(int band_red, int band_nir)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 13.2" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    double correct1 = 0.564936;  // Expected value
    int band_red1 = 1, band_nir1 = 4;
    double result1 = problem_13_2(band_red1, band_nir1);
    if (abs(result1 - correct1) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    double correct2 = 1.527206;  // Expected value
    int band_red2 = 2, band_nir2 = 5;
    double result2 = problem_13_2(band_red2, band_nir2);
    if (abs(result2 - correct2) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct2 << ", Got: " << result2 << endl;
    }

    // Test 3
    double correct3 = 3.173716;  // Expected value
    int band_red3 = 3, band_nir3 = 6;
    double result3 = problem_13_2(band_red3, band_nir3);
    if (abs(result3 - correct3) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct3 << ", Got: " << result3 << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 3
step_description_prompt: Please write a C++ function named problem_13_3 that takes two int parameters (band_red, band_nir) and returns an int. This function calculates the average of distance-weighted DVI values from a specific binary data file.

Function definition: int problem_13_3(int band_red, int band_nir);

Algorithm flow: 1. Check three paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to find the existing file (open in binary mode). If no file exists, output "Error: Cannot find data file AA" and return -1. 2. Read red band data: use seekg to skip (band_red-1)*600*600 bytes, read each row into a buffer, then assign to red[rows-1-i][j] (rows=600, cols=600, red is a 2D vector of unsigned char initialized to 0). 3. Read nir band data similarly with band_nir. 4. For each pixel (i,j), compute DVI = (int)nir[i][j] - (int)red[i][j]. Calculate squared distance to center (center_i=300.0, center_j=300.0), then weight = 1.0 + 0.1*exp(-dist_sq/(2.0*10000.0)). Accumulate sum_dvi as (long long)(dvi*weight). 5. Return (sum_dvi / (600*600)) as int.

Note: Use ifstream for binary file operations. Use new/delete for the buffer (unsigned char* buf, size cols). The exp function is available. The red and nir data are stored with reversed rows (rows-1-i).
function_header: int problem_13_3(int band_red, int band_nir)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 13.3" << endl;
    
    int correct_count = 0;
    
    // Test 1
    int correct1 = -35;  // Expected value
    int band_red1 = 1, band_nir1 = 4;
    int result1 = problem_13_3(band_red1, band_nir1);
    if (result1 == correct1) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    int correct2 = 19;  // Expected value
    int band_red2 = 2, band_nir2 = 5;
    int result2 = problem_13_3(band_red2, band_nir2);
    if (result2 == correct2) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct2 << ", Got: " << result2 << endl;
    }

    // Test 3
    int correct3 = 86;  // Expected value
    int band_red3 = 3, band_nir3 = 6;
    int result3 = problem_13_3(band_red3, band_nir3);
    if (result3 == correct3) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct3 << ", Got: " << result3 << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 4
step_description_prompt: Please write a C++ function named problem_13_4 that takes two integers (band_red, band_nir) and returns a double, which computes the Gaussian-weighted mean of NIR/Red ratio using data from a binary file.

Function definition: double problem_13_4(int band_red, int band_nir);

Algorithm flow: 1. Check three paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to find the existing binary file. If none exists, output "Error: Cannot find data file AA" to cerr and return -1.0. 2. Read 600x600 unsigned char data for band_red and band_nir: skip (band-1)*600*600 bytes, read each row (600 bytes), store rows in reverse order (rows-1-i). 3. For pixels where red[i][j]>0, compute ratio = nir[i][j]/red[i][j], weight = exp(-( (i-300.0)^2 + (j-300.0)^2 )/(2*150^2)), sum ratio*weight and weight. Return sum(ratio*weight)/sum(weight) if sum(weight)>1e-10, else 0.0.

File operations: Use ifstream to verify file existence and read binary data. Skip prior bands with seekg, read each row as 600 bytes, reverse rows during storage.
function_header: double problem_13_4(int band_red, int band_nir)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 13.4" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    double correct1 = 0.564936;  // Expected value
    int band_red1 = 1, band_nir1 = 4;
    double result1 = problem_13_4(band_red1, band_nir1);
    if (abs(result1 - correct1) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    double correct2 = 1.527206;  // Expected value
    int band_red2 = 2, band_nir2 = 5;
    double result2 = problem_13_4(band_red2, band_nir2);
    if (abs(result2 - correct2) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct2 << ", Got: " << result2 << endl;
    }

    // Test 3
    double correct3 = 3.173716;  // Expected value
    int band_red3 = 3, band_nir3 = 6;
    double result3 = problem_13_4(band_red3, band_nir3);
    if (abs(result3 - correct3) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct3 << ", Got: " << result3 << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 5
step_description_prompt: Please write a C++ function named problem_13_5 that calculates the Gaussian-weighted Enhanced Vegetation Index (EVI) mean from a multi-band image file. The function takes three integers representing the band indices of red, NIR, and blue bands, and returns a double value.
Function definition: double problem_13_5(int band_red, int band_nir, int band_blue);
Algorithm flow: 
1. Check three paths ("test_data/AA", "../test_data/AA", "../../test_data/AA") to find the existing binary file "AA". If no file is found, output "Error: Cannot find data file AA" to cerr and return -1.0.
2. Read red, NIR, and blue bands from the file: each band starts at (band index - 1) * 600 * 600 bytes offset. Read 600x600 unsigned char values, store rows in reverse vertical order (rows-1 - i) into 2D vectors.
3. Calculate Gaussian weights using center (600/2.0, 600/2.0) and sigma = max(600,600)/4.0. Compute EVI with 2.5*(NIR_val - red_val)/(NIR_val + 6.0*red_val -7.5*blue_val +1.0). If denominator > 1e-6, accumulate weighted EVI (EVI * weight) and weight sum.
4. Return weighted_sum_evi / weight_sum if weight_sum >1e-10, else 0.0.
function_header: double problem_13_5(int band_red, int band_nir, int band_blue)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 13.5" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    double correct1 = 25.360874;  // Expected value
    int band_red1 = 1, band_nir1 = 4, band_blue1 = 1;
    double result1 = problem_13_5(band_red1, band_nir1, band_blue1);
    if (abs(result1 - correct1) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    double correct2 = 10.268689;  // Expected value
    int band_red2 = 2, band_nir2 = 5, band_blue2 = 2;
    double result2 = problem_13_5(band_red2, band_nir2, band_blue2);
    if (abs(result2 - correct2) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct2 << ", Got: " << result2 << endl;
    }

    // Test 3
    double correct3 = 3.406348;  // Expected value
    int band_red3 = 3, band_nir3 = 6, band_blue3 = 3;
    double result3 = problem_13_5(band_red3, band_nir3, band_blue3);
    if (abs(result3 - correct3) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct3 << ", Got: " << result3 << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

step_number: 6
step_description_prompt: Please write a C++ function named problem_13_6 that takes three integers (band_red, band_nir, band_blue) as input and returns a double. This function calculates a weighted composite score of four vegetation indices (NDVI, RVI, DVI, EVI) using Gaussian or custom weights after reading band data from a binary file.
The function is defined as double problem_13_6(int band_red, int band_nir, int band_blue).
1. Check file existence in paths {"test_data/AA", "../test_data/AA", "../../test_data/AA"}. If not found, output "Error: Cannot find data file AA" to cerr and return -1.0.
2. Read 3 bands (red, nir, blue) with 600 rows and 600 columns: for each band, seek to offset (band-1)*600*600, read each row, and store with reversed row order (rows-1-i).
3. Calculate weighted averages:
   - NDVI: Gaussian weight (sigma = max(rows, cols)/4), formula (nir-red)/(nir+red) (denominator > 1e-6).
   - RVI: Same Gaussian weight, formula nir/red (red > 0).
   - DVI: Weight = 1 + 0.1*exp(-dist²/(2*10000)), formula nir-red; divide result by 255 after average.
   - EVI: Same Gaussian weight, formula 2.5*(nir-red)/(nir+6*red-7.5*blue+1) (denominator > 1e-6).
4. Normalize indices: NDVI=(ndvi+1)/2, RVI=min(1.0, rvi/10), DVI=(dvi+1)/2, EVI=(evi+1)/2.
5. Compute composite score: 0.3*normalized_ndvi + 0.25*normalized_rvi + 0.2*normalized_dvi + 0.25*normalized_evi. Return the score.
function_header: double problem_13_6(int band_red, int band_nir, int band_blue)
test_cases: // ==================== Main function: Testing ====================
int main() {
    srand(42);
    cout << fixed << setprecision(6);
    cout << "Problem 13.6" << endl;
    
    int correct_count = 0;
    const double tolerance = 1e-5;
    
    // Test 1
    double correct1 = 3.502099;  // Expected value
    int band_red1 = 1, band_nir1 = 4, band_blue1 = 1;
    double result1 = problem_13_6(band_red1, band_nir1, band_blue1);
    if (abs(result1 - correct1) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
    }

    // Test 2
    double correct2 = 1.727502;  // Expected value
    int band_red2 = 2, band_nir2 = 5, band_blue2 = 2;
    double result2 = problem_13_6(band_red2, band_nir2, band_blue2);
    if (abs(result2 - correct2) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct2 << ", Got: " << result2 << endl;
    }

    // Test 3
    double correct3 = 0.989496;  // Expected value
    int band_red3 = 3, band_nir3 = 6, band_blue3 = 3;
    double result3 = problem_13_6(band_red3, band_nir3, band_blue3);
    if (abs(result3 - correct3) < tolerance) {
        cout << "Correct" << endl;
        correct_count++;
    } else {
        cout << "Wrong" << endl;
        cout << "Expected: " << correct3 << ", Got: " << result3 << endl;
    }
    
    if (correct_count == 3) {
        cout << "Completely correct!" << endl;
    }
    
    return 0;
}

General solution:

General tests: