You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CPLEX决策变量显示“No Value”问题及模型修正请求

急诊室资源优化随机MIP模型修正(CPLEX OPL)

首次使用CPLEX Studio IDE v22.1.0开展大学项目,通过随机混合整数规划(Stochastic Mixed Integer Program)优化5类医院资源(医生、护士、实验室人员、影像设备、床位)以缓解急诊室拥挤问题。已完成模型编写,但运行后决策变量显示“No Value”,请求修正后的模型。


原模型代码

{string} resources = {"Doctors", "Nurses", "Lab Scientists", "Imaging", "Beds"};
int capacity[resources] = [2, 3, 4, 2, 10];

// 定义时间段与队列索引
//=====================================================
int t = ...;
int q = ...;
range timeperiods = 1..3;
range queues = 1..5;

// 定义场景
//=======================
range scenarios = 1..3;

// 定义患者到达率与资源服务能力
//============================================================
int arrivalrate[scenarios][timeperiods][queues] = ...;
int servicecapacity[scenarios][timeperiods][queues] = ...;

// 定义决策变量
//===============================
dvar int R[timeperiods][resources];
dvar int W[scenarios][timeperiods][queues];
dvar int S[scenarios][timeperiods][queues];

// 目标函数
//=========
// 表达式
dexpr int WP = sum (s in scenarios, t in timeperiods, q in queues) W[s][t][q];
dexpr int SP = sum (s in scenarios, t in timeperiods, q in queues) S[s][t][q];
dexpr int NWP = WP - SP;

// 目标函数
//===================
minimize NWP;

// 约束条件
//===========
subject to {
// 初始化各场景下每个队列的等待患者数
//=====================================================
forall (s in scenarios, t1 in timeperiods, q1, q2, q3, q4, q5, q in queues) {
W[s][t1][q1] == arrivalrate[s][1][q];
W[s][t1][q2] == 0;
W[s][t1][q3] == 0;
W[s][t1][q4] == 0;
W[s][t1][q5] == 0;
S[s][t1][q1] == 0;
S[s][t1][q2] == 0;
S[s][t1][q3] == 0;
S[s][t1][q4] == 0;
S[s][t1][q5] == 0;
}

// 更新各时间段每个队列的患者数
//==============================================================
forall (s in scenarios, t2, t3 in timeperiods, q1 in queues) {
    W[s][t][q1] == W[s][t-1][q1] + arrivalrate[s][t][1] - S[s][t-1][q1];
}

forall (s in scenarios, t2, t3 in timeperiods, q1, q2 in queues) {
    W[s][t][q2] == W[s][t-1][q2] + S[s][t-1][q1] - S[s][t-1][q2];
}

forall (s in scenarios, t2, t3 in timeperiods, q1, q3 in queues) {
    W[s][t][q3] == W[s][t-1][q3] + S[s][t-1][q1] - S[s][t-1][q3];
}

forall (s in scenarios, t2, t3 in timeperiods, q2, q3, q4 in queues) {
    W[s][t][q4] == W[s][t-1][q4] + S[s][t-1][q2] + S[s][t-1][q3] - S[s][t-1][q4];
}

forall (s in scenarios, t2, t3 in timeperiods, q2, q3, q5 in queues) {
    W[s][t][q5] == W[s][t-1][q5] + S[s][t-1][q2] + S[s][t-1][q3] - S[s][t-1][q5];
}

// 单时间段服务患者数上限
//=================================================
forall (s in scenarios, t in timeperiods, q in queues) {
    S[s][t][q] <= W[s][t][q];  
}

// 各时间段每个队列的服务患者数限制
//=============================================================
forall (s in scenarios, t in timeperiods, q1 in queues) {
    S[s][t][q1] <= sum (s in scenarios, t in timeperiods, q in queues) servicecapacity[s][t][1] * 1;    
}

forall (s in scenarios, t in timeperiods, q2 in queues) {
    S[s][t][q2] <= sum (s in scenarios, t in timeperiods, q in queues) servicecapacity[s][t][2] * 1;
}

forall (s in scenarios, t in timeperiods, q3 in queues) {
    S[s][t][q3] <= sum (s in scenarios, t in timeperiods, q in queues) servicecapacity[s][t][3] * 1;
}

forall (s in scenarios, t in timeperiods, q4 in queues) {
    S[s][t][q4] <= sum (s in scenarios, t in timeperiods, q in queues) servicecapacity[s][t][4] * 1;
}

forall (s in scenarios, t in timeperiods, q5 in queues, r5 in resources) {    
    S[s][t][q5] <= R[t][r5];
}

// 人力资源可用工时限制(每人8小时)
//==============================================================
forall (r1 in resources) {
sum (t in timeperiods) R[t][r1] <= 8;
}

forall (r2 in resources) {
sum (t in timeperiods) R[t][r2] <= 8;
}

forall (r3 in resources) {
sum (t in timeperiods) R[t][r3] <= 8;
}

// 各时间段每种资源至少配置1个
//============================================================
forall (t in timeperiods, r1 in resources) {
R[t][r1] >= 1;
}

forall (t in timeperiods, r2 in resources) {
R[t][r2] >= 1;
}

forall (t in timeperiods, r3 in resources) {
R[t][r3] >= 1;
}

forall (t in timeperiods, r4 in resources) {
R[t][r4] >= 1;
}

forall (t in timeperiods, r5 in resources) {
R[t][r5] >= 1;
}
}

原测试数据

t = 3;
q = 5;
arrivalrate = [
[[14,10,95,34,23],
    [90,80,60,34,23],
    [50,30,20,34,23]],
[[14,13,11,34,23],
    [50,30,20,34,23],
    [12,31,27,34,23]],
[[14,10,95,34,23],
    [90,80,60,34,23],
    [50,30,20,34,23]],
];
servicecapacity = [
[[14,10,95,34,23],
    [90,80,60,34,23],
    [50,30,20,34,23]],
[[14,13,11,34,23],
    [50,30,20,34,23],
    [12,31,27,34,23]],
[[14,10,95,34,23],
    [90,80,60,34,23],
    [50,30,20,34,23]],
];

错误核心问题

  1. 初始化约束矛盾:遍历所有时间段初始化等待人数,且用多队列变量重复赋值,导致同一决策变量被强制赋予多个冲突值,模型直接不可行。
  2. 队列更新逻辑混乱:未限定更新仅针对t>=2的时间段,且硬编码队列索引,未匹配对应队列的到达/流转逻辑。
  3. 服务能力约束逻辑错误:将所有场景、时间段的服务能力求和作为单时间段单队列的上限,完全不符合业务逻辑。
  4. 资源匹配约束错误:让队列5的服务人数小于等于所有资源配置,未对应到实际关联的床位资源。
  5. 冗余重复约束:多次重复相同的资源总量、下限约束,无意义且增加模型复杂度。

修正后的模型代码

{string} resources = {"Doctors", "Nurses", "Lab Scientists", "Imaging", "Beds"};
int capacity[resources] = [2, 3, 4, 2, 10];

// 定义时间段与队列索引
range timeperiods = 1..3;
range queues = 1..5;

// 定义场景
range scenarios = 1..3;

// 定义患者到达率与资源服务能力
int arrivalrate[scenarios][timeperiods][queues] = ...;
int servicecapacity[scenarios][timeperiods][queues] = ...;

// 定义决策变量(添加非负约束,符合实际意义)
dvar int R[timeperiods][resources];  // 各时间段各资源配置数量
dvar int W[scenarios][timeperiods][queues] >= 0;  // 各场景各时间段各队列等待患者数
dvar int S[scenarios][timeperiods][queues] >= 0;  // 各场景各时间段各队列服务患者数

// 目标函数:最小化所有场景下的总等待患者数(贴合急诊拥挤优化核心需求)
minimize sum (s in scenarios, t in timeperiods, q in queues) W[s][t][q];

// 约束条件
subject to {
    // 初始化:仅第一个时间段,等待人数等于对应场景到达率,服务人数为0
    forall (s in scenarios, q in queues) {
        W[s][1][q] == arrivalrate[s][1][q];
        S[s][1][q] == 0;
    }

    // 队列流转更新:仅针对t>=2的时间段
    forall (s in scenarios, t in timeperiods: t > 1) {
        // 队列1:新到达患者 + 上周期等待 - 上周期服务
        W[s][t][1] == W[s][t-1][1] + arrivalrate[s][t][1] - S[s][t-1][1];
        // 队列2:来自队列1的完成患者 + 上周期等待 - 上周期服务
        W[s][t][2] == W[s][t-1][2] + S[s][t-1][1] - S[s][t-1][2];
        // 队列3:来自队列1的完成患者 + 上周期等待 - 上周期服务
        W[s][t][3] == W[s][t-1][3] + S[s][t-1][1] - S[s][t-1][3];
        // 队列4:来自队列2、3的完成患者 + 上周期等待 - 上周期服务
        W[s][t][4] == W[s][t-1][4] + S[s][t-1][2] + S[s][t-1][3] - S[s][t-1][4];
        // 队列5:来自队列2、3的完成患者 + 上周期等待 - 上周期服务
        W[s][t][5] == W[s][t-1][5] + S[s][t-1][2] + S[s][t-1][3] - S[s][t-1][5];
    }

    // 服务人数不超过当前队列等待人数
    forall (s in scenarios, t in timeperiods, q in queues) {
        S[s][t][q] <= W[s][t][q];
    }

    // 各队列服务能力上限:当前场景当前时间段的对应队列服务能力
    forall (s in scenarios, t in timeperiods, q in queues) {
        S[s][t][q] <= servicecapacity[s][t][q];
    }

    // 资源-队列匹配约束(按业务逻辑关联)
    forall (s in scenarios, t in timeperiods) {
        S[s][t][1] <= R[t]["Doctors"];      // 队列1(接诊)关联医生
        S[s][t][2] <= R[t]["Nurses"];       // 队列2(护理)关联护士
        S[s][t][3] <= R[t]["Lab Scientists"];// 队列3(检验)关联实验室人员
        S[s][t][4] <= R[t]["Imaging"];      // 队列4(影像)关联影像设备
        S[s][t][5] <= R[t]["Beds"];         // 队列5(住院)关联床位
    }

    // 人力资源总工时限制(每人每天8小时,非人力资源无需此约束)
    forall (r in resources: r != "Beds") {
        sum(t in timeperiods) R[t][r] <= 8;
    }

    // 资源配置上下限:至少1个,不超过最大容量
    forall (t in timeperiods, r in resources) {
        R[t][r] >= 1;
        R[t][r] <= capacity[r];
    }
}

修正说明

  • 明确队列流转逻辑,消除约束矛盾,确保模型可行;
  • 调整目标函数为最小化总等待人数,贴合急诊拥挤优化的核心目标;
  • 补充资源-队列的实际关联约束,符合业务逻辑;
  • 添加决策变量非负约束,匹配实际场景;
  • 简化冗余约束,提升模型可读性与求解效率。

内容的提问来源于stack exchange,提问作者Yusuf Bello Hammanyero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:35:54