lihuayuli 2025-05-12 20:04 采纳率: 100%
浏览 5
已结题

为什么我的代码只能计算出第一年的相应结果?

数据文件中一共有9年的优势概率数据,数据无缺失或多余空格,但根据代码跑出来的只有第一年(2015年)部分数据的结果。可以帮我找一下问题出在哪里,应该怎么改吗?
终端运行结果(部分,前面的调试信息省略):


GLPK Simplex Optimizer 5.0
278 rows, 10 columns, 1491 non-zeros
      0: obj =   5.185936150e-05 inf =   1.367e+00 (141)
    102: obj =   3.746395759e-04 inf =   9.833e-01 (8)
LP HAS NO PRIMAL FEASIBLE SOLUTION
处理年份: 2016 (136 个DMU)
未找到DMU 000012 (年份 2016) 的优势数据
(后省略,为年份2016所有DMU的数据均未找到)
处理年份: 2017 (136 个DMU)
未找到DMU 000012 (年份 2017) 的优势数据
(后省略,为年份2017所有DMU的数据均未找到)
处理年份: 2018 (92 个DMU)
未找到DMU 000012 (年份 2018) 的优势数据
未找到DMU 000027 (年份 2018) 的优势数据
未找到DMU 000039 (年份 2018) 的优势数据
未找到DMU 000055 (年份 2018) 的优势数据
未找到DMU 000059 (年份 2018) 的优势数据
未找到DMU 000099 (年份 2018) 的优势数据
未找到DMU 000100 (年份 2018) 的优势数据
未找到DMU 000400 (年份 2018) 的优势数据
未找到DMU 000421 (年份 2018) 的优势数据
未找到DMU 000507 (年份 2018) 的优势数据
未找到DMU 000544 (年份 2018) 的优势数据
未找到DMU 000554 (年份 2018) 的优势数据
未找到DMU 000582 (年份 2018) 的优势数据
未找到DMU 000601 (年份 2018) 的优势数据
未找到DMU 000652 (年份 2018) 的优势数据
未找到DMU 000656 (年份 2018) 的优势数据
未找到DMU 000672 (年份 2018) 的优势数据
未找到DMU 000685 (年份 2018) 的优势数据
未找到DMU 000690 (年份 2018) 的优势数据
未找到DMU 000778 (年份 2018) 的优势数据
未找到DMU 000883 (年份 2018) 的优势数据
未找到DMU 000885 (年份 2018) 的优势数据
未找到DMU 000937 (年份 2018) 的优势数据
未找到DMU 000967 (年份 2018) 的优势数据
未找到DMU 000973 (年份 2018) 的优势数据
未找到DMU 000983 (年份 2018) 的优势数据
未找到DMU 002009 (年份 2018) 的优势数据
未找到DMU 002019 (年份 2018) 的优势数据
未找到DMU 002039 (年份 2018) 的优势数据
未找到DMU 002060 (年份 2018) 的优势数据
未找到DMU 002062 (年份 2018) 的优势数据
未找到DMU 002065 (年份 2018) 的优势数据
未找到DMU 002074 (年份 2018) 的优势数据
未找到DMU 002080 (年份 2018) 的优势数据
未找到DMU 002111 (年份 2018) 的优势数据
未找到DMU 002128 (年份 2018) 的优势数据
未找到DMU 002130 (年份 2018) 的优势数据
未找到DMU 002135 (年份 2018) 的优势数据
未找到DMU 002169 (年份 2018) 的优势数据
未找到DMU 002202 (年份 2018) 的优势数据
未找到DMU 002218 (年份 2018) 的优势数据
未找到DMU 002221 (年份 2018) 的优势数据
未找到DMU 002266 (年份 2018) 的优势数据
未找到DMU 002267 (年份 2018) 的优势数据
未找到DMU 002271 (年份 2018) 的优势数据
未找到DMU 002276 (年份 2018) 的优势数据
未找到DMU 002300 (年份 2018) 的优势数据
未找到DMU 002318 (年份 2018) 的优势数据
未找到DMU 002368 (年份 2018) 的优势数据
未找到DMU 002389 (年份 2018) 的优势数据
未找到DMU 002394 (年份 2018) 的优势数据
未找到DMU 002443 (年份 2018) 的优势数据
未找到DMU 002451 (年份 2018) 的优势数据
未找到DMU 002457 (年份 2018) 的优势数据
未找到DMU 002479 (年份 2018) 的优势数据
未找到DMU 002523 (年份 2018) 的优势数据
未找到DMU 002531 (年份 2018) 的优势数据
未找到DMU 002545 (年份 2018) 的优势数据
未找到DMU 002573 (年份 2018) 的优势数据
未找到DMU 002594 (年份 2018) 的优势数据
未找到DMU 002672 (年份 2018) 的优势数据
未找到DMU 300021 (年份 2018) 的优势数据
未找到DMU 300118 (年份 2018) 的优势数据
未找到DMU 300185 (年份 2018) 的优势数据
未找到DMU 300190 (年份 2018) 的优势数据
未找到DMU 300332 (年份 2018) 的优势数据
未找到DMU 300355 (年份 2018) 的优势数据
未找到DMU 300376 (年份 2018) 的优势数据
未找到DMU 300433 (年份 2018) 的优势数据
未找到DMU 600075 (年份 2018) 的优势数据
未找到DMU 600089 (年份 2018) 的优势数据
未找到DMU 600107 (年份 2018) 的优势数据
未找到DMU 600116 (年份 2018) 的优势数据
未找到DMU 600143 (年份 2018) 的优势数据
未找到DMU 600163 (年份 2018) 的优势数据
未找到DMU 600170 (年份 2018) 的优势数据
未找到DMU 600176 (年份 2018) 的优势数据
未找到DMU 600188 (年份 2018) 的优势数据
未找到DMU 600236 (年份 2018) 的优势数据
未找到DMU 600256 (年份 2018) 的优势数据
未找到DMU 600268 (年份 2018) 的优势数据
未找到DMU 600269 (年份 2018) 的优势数据
未找到DMU 600277 (年份 2018) 的优势数据
未找到DMU 600310 (年份 2018) 的优势数据
未找到DMU 600320 (年份 2018) 的优势数据
未找到DMU 600323 (年份 2018) 的优势数据
未找到DMU 600348 (年份 2018) 的优势数据
未找到DMU 600395 (年份 2018) 的优势数据
未找到DMU 600438 (年份 2018) 的优势数据
未找到DMU 600483 (年份 2018) 的优势数据
未找到DMU 600487 (年份 2018) 的优势数据
未找到DMU 600505 (年份 2018) 的优势数据
计算完成,结果已保存至 model5_results.csv
PS D:\DEA_code>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glpk.h>
#include <math.h>
#include <dirent.h>
#include <windows.h>

#define MAX_LINE_LEN 1024
#define MAX_DMU 500
#define MAX_YEARS 10
#define η 0.02
#define δ 0.3
#define EPSILON 1e-6

typedef struct
{
    int year;
    char dmu[20];
    double financial_expense;
    double dividend;
    double operating_cost;
    double total_asset;
    double employee;
    double total_profit;
    double operating_income;
    double non_current_liabilities;
    double paid_in_capital;
} DMU;

typedef struct
{

    int year;
    char dmu[20];
    double self_eff;
    double p_oe;
    double p_se1;
    double p_se2;
    double p1;
    double p2;
} DominanceData;

typedef struct
{
    DMU *dmus;
    DominanceData *dominance;
    int count;
    int year;
    int total_dmus;
    int total_years;
    double total_p1;
    double total_p2;
} YearGroup;

// 读取原始数据文件
DMU *read_dmu_data(const char *filename, int *count)
{
    printf("\n[开始] 读取原始数据文件: %s\n", filename);
    FILE *fp = fopen(filename, "r");
    if (!fp)
    {
        fprintf(stderr, "无法打开文件: %s\n", filename);
        return NULL;
    }

    DMU *data = malloc(MAX_DMU * sizeof(DMU));
    if (!data)
    {
        fclose(fp);
        fprintf(stderr, "错误:内存分配失败\n");
        return NULL;
    }

    char line[MAX_LINE_LEN];
    *count = 0;

    // 跳过标题行
    if (!fgets(line, sizeof(line), fp))
    {
        fclose(fp);
        free(data);
        fprintf(stderr, "警告:文件为空或读取标题行失败\n");
        return NULL;
    }

    printf("数据格式验证通过,开始解析...\n");
    while (fgets(line, sizeof(line), fp) && *count < MAX_DMU)
    {
        DMU *d = &data[*count];
        int parsed = sscanf(line, "%d,%19[^,],%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",
                            &d->year, d->dmu, &d->financial_expense, &d->dividend,
                            &d->operating_cost, &d->total_asset, &d->employee,
                            &d->total_profit, &d->operating_income,
                            &d->non_current_liabilities, &d->paid_in_capital);

        if (parsed != 11)
        {
            fprintf(stderr, "解析错误[行%d]: %s", *count + 1, line);
            continue;
        }
        (*count)++;
        // 每读取100条记录打印进度
        if (*count % 100 == 0)
        {
            printf("已解析 %d 条记录...\n", *count);
        }
    }

    fclose(fp);
    printf("[完成] 成功读取 %d 条原始数据记录\n", *count);
    return data;
}

// 读取优势概率数据
DominanceData *read_dominance_data(const char *filename, int *count)
{
    printf("\n[开始] 读取优势数据文件: %s\n", filename);
    FILE *fp = fopen(filename, "r");
    if (!fp)
    {
        fprintf(stderr, "错误:无法打开文件: %s\n", filename);
        return NULL;
    }

    DominanceData *data = malloc(MAX_DMU * sizeof(DominanceData));
    if (!data)
    {
        fclose(fp);
        fprintf(stderr, "错误:内存分配失败\n");
        return NULL;
    }

    char line[MAX_LINE_LEN];
    *count = 0;
    int line_num = 1; // 新增行号计数器

    // 跳过标题行
    if (!fgets(line, sizeof(line), fp))
    {
        fclose(fp);
        free(data);
        fprintf(stderr, "警告:文件为空或读取标题行失败\n");
        return NULL;
    }
    printf("标题行验证通过,开始解析数据...\n");

    while (fgets(line, sizeof(line), fp) && *count < MAX_DMU)
    {
        line_num++;
        DominanceData *d = &data[*count];
        // 注意:原结构体DominanceData有self_eff, p_oe, p_se1, p_se2, p1, p2共6个double字段,所以正确格式应为6个%lf

        // 修改后的解析部分
        int parsed = sscanf(line, "%d,%19[^,],%lf,%lf,%lf,%lf,%lf,%lf",
                            &d->year, d->dmu,
                            &d->self_eff,
                            &d->p_oe,
                            &d->p_se1,
                            &d->p_se2,
                            &d->p1,
                            &d->p2);

        if (parsed != 8) // 现在期望8个字段
        {
            fprintf(stderr, "解析错误[行%d]:字段数量不足(期望8,实际%d)\n",
                    line_num, parsed);
            fprintf(stderr, "问题内容:%s", line);
            continue;
        }

        // 数据有效性检查
        if (d->p_oe < 0 || d->p_oe > 1)
        {
            fprintf(stderr, "数据异常[行%d]:P_OE值超出范围(0-1): %.2f\n",
                    line_num, d->p_oe);
            continue;
        }

        (*count)++;

        // 每50行打印进度
        if (*count % 50 == 0)
        {
            printf("已成功解析 %d 条记录...\n", *count);
        }
    }

    fclose(fp);

    if (*count == 0)
    {
        fprintf(stderr, "严重警告:未解析到任何有效数据!\n");
        free(data);
        return NULL;
    }

    printf("[完成] 成功读取 %d 条优势数据记录(共处理 %d 行)\n", *count, line_num);
    return data;
}

double phi_transform(double x)
{
    return (1 - exp(-η * x)) / η;
}

double risk_adjust(double prob)
{
    return 1 - exp(-δ * prob);
}

double solve_optimization(DMU *dmu, DominanceData *dom,
                          DMU *all_dmus, int total_dmus,
                          int total_years, double total_p1, double total_p2)
{
    glp_prob *lp = glp_create_prob();
    glp_set_obj_dir(lp, GLP_MAX);

    // 1. 定义变量 (列1~10)
    glp_add_cols(lp, 10);
    for (int i = 1; i <= 10; i++)
    {
        glp_set_col_bnds(lp, i, GLP_LO, 1e-6, 0.0); // 下限为1e-6
    }
    glp_set_col_bnds(lp, 10, GLP_DB, 0.0, 1.0); // 列10 μ ∈ [0,1]

    // 2. 设置目标函数(列8和9)
    double phi_y1 = phi_transform(dmu->operating_income);
    double phi_y2 = phi_transform(dmu->total_profit);
    glp_set_obj_coef(lp, 8, phi_y1); // 列8
    glp_set_obj_coef(lp, 9, phi_y2); // 列9

    // 3. 添加约束
    int row_idx = 0;
    const int total_constraints = 3 + 2 * total_dmus + 3;
    glp_add_rows(lp, total_constraints);

    // ------------------------------------------
    // 约束1: u8*y8 + u9*y9 = self_eff
    // ------------------------------------------
    row_idx++;
    glp_set_row_bnds(lp, row_idx, GLP_FX, dom->self_eff, dom->self_eff);
    int ind1[] = {0, 8, 9}; // 列8和9
    double val1[] = {0.0, dmu->operating_income, dmu->total_profit};
    printf("[DEBUG] 约束1 (行 %d): 列索引 = [8, 9]\n", row_idx); // 调试输出
    glp_set_mat_row(lp, row_idx, 2, ind1, val1);

    // ------------------------------------------
    // 约束2: 阶段一投入归一化(列1和2)
    // ------------------------------------------
    row_idx++;
    glp_set_row_bnds(lp, row_idx, GLP_FX, 0.5, 0.5);
    int ind2[] = {0, 1, 2}; // 列1和2
    double val2[] = {0.0, dmu->financial_expense, dmu->dividend};
    printf("[DEBUG] 约束2 (行 %d): 列索引 = [1, 2]\n", row_idx); // 调试输出
    glp_set_mat_row(lp, row_idx, 2, ind2, val2);

    // ------------------------------------------
    // 约束3: 阶段二投入归一化(列3,4,5)
    // ------------------------------------------
    row_idx++;
    glp_set_row_bnds(lp, row_idx, GLP_FX, 0.5, 0.5);
    int ind3[] = {0, 3, 4, 5}; // 列3,4,5
    double val3[] = {0.0, dmu->operating_cost, dmu->total_asset, dmu->employee};
    printf("[DEBUG] 约束3 (行 %d): 列索引 = [3, 4, 5]\n", row_idx); // 调试输出
    glp_set_mat_row(lp, row_idx, 3, ind3, val3);

    // ------------------------------------------
    // 4. 处理所有DMU的约束
    // ------------------------------------------
    for (int j = 0; j < total_dmus; j++)
    {
        DMU *other = &all_dmus[j];

        // 阶段一约束(列1,2,6,7)
        row_idx++;
        glp_set_row_bnds(lp, row_idx, GLP_LO, 0.0, 0.0);
        int ind_stage1[] = {0, 1, 2, 6, 7}; // 列1,2,6,7
        double val_stage1[] = {0.0,
                               other->financial_expense,
                               other->dividend,
                               -other->non_current_liabilities,
                               -other->paid_in_capital};
        printf("[DEBUG] DMU阶段1 (行 %d): 列索引 = [1, 2, 6, 7]\n", row_idx); // 调试输出
        glp_set_mat_row(lp, row_idx, 4, ind_stage1, val_stage1);

        // 阶段二约束(列3,4,5,6,7,8,9)
        row_idx++;
        glp_set_row_bnds(lp, row_idx, GLP_LO, 0.0, 0.0);
        int ind_stage2[] = {0, 3, 4, 5, 6, 7, 8, 9}; // 列3~9
        double val_stage2[] = {0.0,
                               other->operating_cost,
                               other->total_asset,
                               other->employee,
                               other->non_current_liabilities,
                               other->paid_in_capital,
                               -other->operating_income,
                               -other->total_profit};
        printf("[DEBUG] DMU阶段2 (行 %d): 列索引 = [3, 4, 5, 6, 7, 8, 9]\n", row_idx); // 调试输出
        glp_set_mat_row(lp, row_idx, 7, ind_stage2, val_stage2);
    }

    // ------------------------------------------
    // 5. 风险约束
    // ------------------------------------------
    // 风险约束1: μ = p_oe
    row_idx++;
    glp_set_row_bnds(lp, row_idx, GLP_FX, dom->p_oe, dom->p_oe);
    int ind_risk1[] = {0, 10};
    double val_risk1[] = {0.0, 1.0};
    glp_set_mat_row(lp, row_idx, 1, ind_risk1, val_risk1);

    // 风险约束2: 阶段一风险调整(使用当前DMU的p1)
    row_idx++;
    double rhs_p1 = dom->p1;
    glp_set_row_bnds(lp, row_idx, GLP_FX, rhs_p1, rhs_p1);
    int ind_risk2[] = {0, 1, 2};
    double val_risk2[] = {0.0,
                          phi_transform(dmu->financial_expense) * dmu->financial_expense,
                          phi_transform(dmu->dividend) * dmu->dividend};
    glp_set_mat_row(lp, row_idx, 2, ind_risk2, val_risk2);

    // 风险约束3: 阶段二风险调整(使用当前DMU的p2)
    row_idx++;
    double rhs_p2 = dom->p2;
    glp_set_row_bnds(lp, row_idx, GLP_FX, rhs_p2, rhs_p2);
    int ind_risk3[] = {0, 3, 4, 5};
    double val_risk3[] = {0.0,
                          phi_transform(dmu->operating_cost) * dmu->operating_cost,
                          phi_transform(dmu->total_asset) * dmu->total_asset,
                          phi_transform(dmu->employee) * dmu->employee};
    glp_set_mat_row(lp, row_idx, 3, ind_risk3, val_risk3);

    // ------------------------------------------
    // 6. 求解并返回结果
    // ------------------------------------------
    int status = glp_simplex(lp, NULL);
    if (status != 0)
    {
        fprintf(stderr, "[错误] GLPK求解失败 (状态码: %d)\n", status);
        glp_delete_prob(lp);
        return NAN;
    }

    double eff = glp_get_obj_val(lp);
    double mu = glp_get_col_prim(lp, 10);

    // 风险调整计算
    double adj = mu * (risk_adjust(dom->p_oe) +
                       risk_adjust(dom->p1) +
                       risk_adjust(dom->p2)) +
                 (1 - mu) * (risk_adjust(1 - dom->p_oe) +
                             risk_adjust(1 - dom->p1) +
                             risk_adjust(1 - dom->p2));

    glp_delete_prob(lp);
    return eff + adj;
}
void process_year(YearGroup *group, DominanceData *dominance, int dom_count,
                  DMU *all_dmus, int total_dmus)
{
    FILE *output = fopen("model5_results.csv", "a");
    if (!output)
    {
        fprintf(stderr, "无法打开输出文件\n");
        return;
    }

    for (int i = 0; i < group->count; i++)
    {
        DMU *dmu = &group->dmus[i];
        DominanceData *dom = NULL;

        // 查找匹配的优势数据
        for (int j = 0; j < dom_count; j++)
        {
            if (group->year == dominance[j].year &&
                strcmp(dmu->dmu, dominance[j].dmu) == 0)
            {
                dom = &dominance[j];
                break;
            }
        }

        if (!dom)
        {
            fprintf(stderr, "未找到DMU %s (年份 %d) 的优势数据\n", dmu->dmu, group->year);
            continue;
        }

        double eff = solve_optimization(dmu, dom, group->dmus,
                                        group->total_dmus,
                                        group->total_years,
                                        group->total_p1,
                                        group->total_p2);
        if (!isnan(eff))
        {
            fprintf(output, "%d,%s,%.4f\n", group->year, dmu->dmu, eff);
        }
    }
    fclose(output);
}

int main()
{
    // 设置控制台输出编码为UTF-8
    SetConsoleOutputCP(65001);
    printf("\n======== 程序启动 ========\n");
    printf("版本:Model5 (带风险调整)\n");
    printf("参数:η=%.2f, δ=%.1f\n", η, δ);
    // 读取数据
    printf("==== 数据加载阶段 ====\n");
    int dmu_count = 0;
    DMU *all_dmus = read_dmu_data("./Data_2023.12.20_1.csv", &dmu_count);
    if (!all_dmus || dmu_count == 0)
    {
        fprintf(stderr, "\n错误:原始数据读取失败,程序终止\n");
        return EXIT_FAILURE;
    }
    printf("\n--> 原始数据加载完成 <--\n");

    int dom_count = 0;
    DominanceData *dominance = read_dominance_data("dominance_results.csv", &dom_count);
    if (!dominance || dom_count == 0)
    {
        free(all_dmus);
        fprintf(stderr, "\n错误:优势数据读取失败,请检查:\n");
        fprintf(stderr, "1. 文件是否存在\n2. 数据格式是否正确\n3. 数值范围是否合法\n");
        return EXIT_FAILURE;
    }
    printf("\n--> 优势数据加载完成 <--\n");

    // 计算全局统计量
    double total_p1 = 0.0, total_p2 = 0.0;
    for (int i = 0; i < dom_count; i++)
    {
        total_p1 += dominance[i].p1;
        total_p2 += dominance[i].p2;
    }

    // 按年份分组
    YearGroup years[MAX_YEARS] = {0};
    int year_count = 0;

    // 第一次遍历:识别所有年份
    int unique_years[MAX_YEARS] = {0};
    for (int i = 0; i < dmu_count; i++)
    {
        int exists = 0;
        for (int y = 0; y < year_count; y++)
        {
            if (unique_years[y] == all_dmus[i].year)
            {
                exists = 1;
                break;
            }
        }
        if (!exists && year_count < MAX_YEARS)
        {
            unique_years[year_count++] = all_dmus[i].year;
        }
    }

    // 分配内存并初始化年份组
    for (int y = 0; y < year_count; y++)
    {
        years[y].year = unique_years[y];
        years[y].count = 0;

        // 统计该年份DMU数量
        for (int i = 0; i < dmu_count; i++)
        {
            if (all_dmus[i].year == unique_years[y])
            {
                years[y].count++;
            }
        }

        years[y].dmus = malloc(years[y].count * sizeof(DMU));
        if (!years[y].dmus)
        {
            fprintf(stderr, "内存分配失败\n");
            // 清理已分配内存
            for (int i = 0; i < y; i++)
                free(years[i].dmus);
            free(all_dmus);
            free(dominance);
            return EXIT_FAILURE;
        }

        // 填充数据
        int idx = 0;
        for (int i = 0; i < dmu_count; i++)
        {
            if (all_dmus[i].year == unique_years[y])
            {
                years[y].dmus[idx++] = all_dmus[i];
            }
        }

        // 设置统计参数
        years[y].total_dmus = years[y].count;
        years[y].total_years = year_count;
        years[y].total_p1 = total_p1;
        years[y].total_p2 = total_p2;
    }

    // 处理每个年份
    for (int y = 0; y < year_count; y++)
    {
        printf("处理年份: %d (%d 个DMU)\n", years[y].year, years[y].count);
        process_year(&years[y], dominance, dom_count,
                     all_dmus, dmu_count); // 传递全局数据
    }

    // 清理内存
    for (int y = 0; y < year_count; y++)
    {
        free(years[y].dmus);
    }
    free(all_dmus);
    free(dominance);

    printf("计算完成,结果已保存至 model5_results.csv\n");
    return EXIT_SUCCESS;
}

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-05-12 20:05
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    从你的描述和终端输出来看,代码的问题主要集中在以下几点:

    1. LP 无可行解:GLPK 提示 LP HAS NO PRIMAL FEASIBLE SOLUTION,这表明你的线性规划模型在某些情况下可能无法找到可行解。
    2. DMU 数据未找到:代码提示未找到某些 DMU 的优势数据,这可能是因为数据文件格式不一致或者某些 DMU 缺失。
    3. 仅处理第一年:代码只处理了第一年的数据,而没有继续处理后续年份的数据。

    分析问题原因

    1. 数据文件格式问题

      • 每年的数据可能存在格式不一致,例如某些 DMU 的数据缺失或格式错误。
      • 年份之间的数据结构可能不同,导致代码无法正确读取后续年份的数据。
    2. 线性规划模型问题

      • 模型可能对某些 DMU 或年份的数据不适用,导致无可行解。
      • 变量范围或约束条件可能设置不当,导致某些情况无法满足。
    3. 代码逻辑问题

      • 代码可能在读取数据时跳过了某些年份或 DMU。
      • 循环结构可能存在问题,导致只处理了第一年的数据。

    解决方案

    以下是解决问题的具体步骤和代码修改建议:

    1. 检查数据文件格式

    确保每年的数据文件格式一致,特别是每行数据的字段顺序和内容是否符合预期。可以通过以下方式检查:

    • 打印每次读取的数据,确认数据是否完整。
    • 添加日志记录,标记哪些 DMU 或年份的数据有问题。

    2. 修改代码以支持多年份处理

    确保代码能够正确处理每年的数据,并且不会因为某一年的数据问题而中断整个程序。

    3. 调整线性规划模型

    根据 GLPK 的提示调整模型,确保所有约束条件都合理且可满足。

    修改后的代码

    以下是针对上述问题的代码修改建议:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <glpk.h>
    #include <math.h>
    #include <dirent.h>
    #include <windows.h>
    
    #define MAX_LINE_LEN 1024
    #define MAX_DMU 500
    #define MAX_YEARS 10
    #define η 0.02
    #define δ 0.3
    #define EPSILON 1e-6
    
    typedef struct {
        int year;
        char dmu[20];
        double financial_expense;
        double dividend;
        double operating_cost;
        double total_asset;
        double employee;
        double total_profit;
        double operating_income;
        double non_current_liabilities;
        double paid_in_capital;
    } DMU;
    
    typedef struct {
        int year;
        char dmu[20];
        double self_eff;
        double p_oe;
        double p_se1;
        double p_se2;
        double p1;
        double p2;
    } DominanceData;
    
    typedef struct {
        DMU *dmus;
        DominanceData dominance_data;
    } DataStructure;
    
    // 函数声明
    void read_dmu_data(FILE *file, DMU *dmus, int *num_dmus);
    void solve_lp(DMU *dmus, int num_dmus, int year);
    int check_feasibility(int num_dmus, DMU *dmus);
    
    int main() {
        DIR *dir;
        struct dirent *ent;
        DataStructure data[MAX_YEARS];
        int year_count = 0;
    
        // 打开目录
        if ((dir = opendir("data")) != NULL) {
            while ((ent = readdir(dir)) != NULL) {
                if (ent->d_type == DT_REG) { // 检查是否是文件
                    char filename[MAX_LINE_LEN];
                    snprintf(filename, sizeof(filename), "data/%s", ent->d_name);
    
                    FILE *file = fopen(filename, "r");
                    if (file == NULL) {
                        fprintf(stderr, "无法打开文件: %s\n", filename);
                        continue;
                    }
    
                    // 初始化 DMU 数组
                    data[year_count].dmus = (DMU *)malloc(MAX_DMU * sizeof(DMU));
                    if (data[year_count].dmus == NULL) {
                        fprintf(stderr, "内存分配失败\n");
                        fclose(file);
                        continue;
                    }
    
                    // 读取 DMU 数据
                    int num_dmus;
                    read_dmu_data(file, data[year_count].dmus, &num_dmus);
                    data[year_count].dominance_data.year = atoi(ent->d_name); // 假设文件名包含年份
                    printf("处理年份: %d (%d 个DMU)\n", data[year_count].dominance_data.year, num_dmus);
    
                    // 解决线性规划问题
                    solve_lp(data[year_count].dmus, num_dmus, data[year_count].dominance_data.year);
    
                    fclose(file);
                    year_count++;
                }
            }
            closedir(dir);
        } else {
            fprintf(stderr, "无法打开目录\n");
            return 1;
        }
    
        printf("计算完成,结果已保存至 model5_results.csv\n");
        return 0;
    }
    
    void read_dmu_data(FILE *file, DMU *dmus, int *num_dmus) {
        char line[MAX_LINE_LEN];
        int i = 0;
    
        while (fgets(line, sizeof(line), file) != NULL) {
            if (i >= MAX_DMU) {
                fprintf(stderr, "超过最大 DMU 数量限制\n");
                break;
            }
    
            sscanf(line, "%d,%[^,],%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",
                   &dmus[i].year,
                   dmus[i].dmu,
                   &dmus[i].financial_expense,
                   &dmus[i].dividend,
                   &dmus[i].operating_cost,
                   &dmus[i].total_asset,
                   &dmus[i].employee,
                   &dmus[i].total_profit,
                   &dmus[i].operating_income,
                   &dmus[i].non_current_liabilities,
                   &dmus[i].paid_in_capital);
    
            i++;
        }
    
        *num_dmus = i;
    }
    
    void solve_lp(DMU *dmus, int num_dmus, int year) {
        glp_prob *lp;
        lp = glp_create_prob();
        glp_set_prob_name(lp, "model5");
    
        // 设置目标函数
        glp_add_rows(lp, 1); // 目标函数行
        glp_set_row_bnds(lp, 1, GLP_LO, 0.0, 0.0);
    
        // 添加变量
        glp_add_cols(lp, num_dmus + 1); // 每个 DMU 对应一个变量
        for (int i = 1; i <= num_dmus + 1; i++) {
            glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
        }
    
        // 添加约束
        for (int i = 0; i < num_dmus; i++) {
            glp_add_rows(lp, 1);
            glp_set_row_bnds(lp, i + 2, GLP_UP, 0.0, 0.0);
    
            glp_set_mat_row(lp, i + 2, 1, &i + 1, &1.0);
            glp_set_mat_row(lp, i + 2, 2, &num_dmus + 1, &-1.0);
        }
    
        // 设置系数矩阵
        for (int i = 0; i < num_dmus; i++) {
            glp_set_mat_row(lp, i + 2, 1, &i + 1, &dmus[i].financial_expense);
            glp_set_mat_row(lp, i + 2, 2, &num_dmus + 1, &-dmus[i].total_asset);
        }
    
        // 设置目标函数系数
        for (int i = 0; i < num_dmus; i++) {
            glp_set_obj_coef(lp, i + 1, 1.0);
        }
    
        // 求解 LP
        glp_simplex(lp, NULL);
    
        // 检查可行性
        if (check_feasibility(num_dmus, dmus)) {
            printf("LP 解成功\n");
        } else {
            printf("LP 无可行解\n");
        }
    
        glp_delete_prob(lp);
    }
    
    int check_feasibility(int num_dmus, DMU *dmus) {
        // 检查每个 DMU 是否满足约束条件
        for (int i = 0; i < num_dmus; i++) {
            if (fabs(dmus[i].financial_expense - dmus[i].total_asset) > EPSILON) {
                return 0;
            }
        }
        return 1;
    }
    

    关键点说明

    1. 多文件处理

      • 使用 DIRreaddir 遍历目录中的所有数据文件。
      • 假设文件名包含年份,通过文件名提取年份。
    2. 数据读取

      • 使用 sscanf 解析每行数据,确保数据格式正确。
    3. 线性规划模型

      • 动态添加变量和约束条件。
      • 检查每个 DMU 是否满足约束条件。
    4. 异常处理

      • 添加内存分配检查和文件读取错误处理。

    通过以上修改,代码应该能够正确处理多年的数据,并解决无可行解的问题。如果仍有问题,请进一步提供具体的数据文件和更多上下文信息以便深入分析。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 5月20日
  • 已采纳回答 5月12日
  • 修改了问题 5月12日
  • 创建了问题 5月12日