GUSS 求解器文档


Gather-Update-Solve-Scatter (GUSS)

目录

引言

GUSS (Gather-Update-Solve-Scatter) 是 GAMS 的一个特殊求解器,专门用于高效地批量求解多个相关的优化问题(场景)。它通过在求解过程中执行 Gather(收集数据)→ Update(更新参数)→ Solve(求解模型)→ Scatter(分散结果)四个步骤,避免了重复的模型生成和求解开销,大大提高了多场景分析的效率。

GUSS 的核心价值在于:当需要求解大量相似但参数不同的优化问题时,传统方法需要为每个场景重新生成并求解模型,而 GUSS 只需生成模型一次,之后通过内存中的快速数据交换来切换场景,可将求解效率提升数十倍甚至数百倍。

GUSS 概念

2.1 工作流程

GUSS 将问题求解过程分为四个步骤:

  1. Gather(收集):从 GAMS 符号中收集模型输入数据,包括目标函数的系数、约束矩阵的元素、变量的边界等。
  2. Update(更新):根据当前场景的定义,更新模型中的参数。GUSS 支持对任何模型输入数据的修改,包括目标系数、约束系数、右侧值(RHS)、变量边界等。
  3. Solve(求解):调用底层求解器(如 CPLEX、Gurobi、CONOPT 等)求解当前场景的优化模型。
  4. Scatter(分散):将求解结果(变量水平、对偶变量、约简成本等)写回 GAMS 符号中,供后续分析使用。

2.2 主要优势

  • 极高的求解效率:避免重复的模型生成和加载,场景切换仅在内存中完成,速度提升可达 10-100 倍。
  • 灵活的场景定义:支持任意数量的场景和参数变化,可以通过 GAMS 集合和参数动态生成场景。
  • 完整的数据集成:与 GAMS 的数据处理和报告生成功能无缝集成,结果可直接用于后续分析。
  • 支持多种求解器:GUSS 作为"wrapper"求解器,可以调用 GAMS 支持的任何底层求解器,包括 LP、MIP、NLP、MCP 等。
  • 内存高效:只加载模型一次,所有场景共享同一个模型实例,大幅降低内存使用。

2.3 适用场景

  • 敏感性分析:改变目标系数或约束右侧值,观察最优解的变化。
  • 多周期优化:同一模型在不同时间段或不同数据切面上的求解。
  • 随机规划:处理多种随机情景(如需求不确定、价格波动等)的优化问题。
  • 参数扫描:系统地变化一组参数,生成解空间的热力图或趋势图。
  • 鲁棒优化:在各种参数组合下验证解的可行性和质量。
  • 投资组合优化:在不同风险偏好或市场假设下求解最优资产配置。

架构与工作原理

3.1 内部架构

GUSS 作为 GAMS 求解器体系中的"元求解器"(meta-solver),其架构分为三层:

  • GUSS 控制层:负责场景调度、数据传递和结果收集。该层根据用户定义的场景数据文件(以 GAMS 参数形式提供)确定场景数量和每个场景的参数变化。
  • GAMS 模型层:包含实际的优化数学模型。模型只需编译一次,之后 GUSS 通过修改内存中的模型数据来切换场景。
  • 底层求解器层:GUSS 调用用户指定的底层求解器(如 LP 用 CPLEX、NLP 用 CONOPT 等)来实际求解每个场景的优化问题。

3.2 场景执行流程

GUSS 在执行场景时的具体流程如下:

  1. 读取场景数据定义,确定场景数量和每个场景的索引。
  2. 编译并加载模型到内存(仅一次)。
  3. 对每个场景:
    1. 根据场景定义更新模型中的参数值。
    2. 调用底层求解器求解当前模型。
    3. 收集求解结果,按照 GUSS Dictionary 的映射关系,将结果写入对应的 GAMS 符号。
  4. 所有场景求解完毕后,将累积的结果数据传递回 GAMS 环境。

3.3 性能特征

GUSS 的性能优势随着场景数量和模型规模的增加而更加显著:

  • 对于小型模型(数百个变量)和少量场景(10-100 个),加速比约为 5-10 倍。
  • 对于中型模型(数千个变量)和中等数量场景(100-1000 个),加速比约为 10-50 倍。
  • 对于大型模型(数万个变量)和大量场景(1000+ 个),加速比可达 50-100 倍以上。
  • 性能提升主要来源于:节省模型编译时间、节省模型生成时间、更好的内存局部性。

场景数据定义

4.1 场景集合(Scenario Set)

场景集合是 GUSS 场景定义的基础。用户需要定义一个集合来索引所有场景:

  Set s / s1*s10 /;     * 定义 10 个场景
  Set ds(s) / s2, s5, s8 /;  * 仅对部分场景求解

4.2 场景参数(Scenario Parameters)

场景参数用于定义每个场景中模型输入数据的值。GUSS 使用特殊的 GAMS 参数来传递场景数据:

  Parameter
    scen_data(s, *) 场景数据表
    /
      s1, demand   100
      s1, cost     2.5
      s2, demand   120
      s2, cost     2.8
      s3, demand   150
      s3, cost     3.0
    /;

4.3 场景字典(GUSS Dictionary)

GUSS Dictionary 是连接场景数据和模型之间的桥梁。它定义了哪些模型数据将被更新、哪些结果将被收集,以及数据在场景参数中的位置:

  Parameter
    dict(*) / 'demand'   . 'scen_data'
              'scen_data'. 'demand'
              'cost'     . 'scen_data'
              'scen_data'. 'cost'
              'x'        . 'result_data'
              'result_data'. 'x'
              /;

GUSS Dictionary 的每个条目遵循 <符号名称> . <数据表名称> 的格式:

  • 左侧为模型中的符号名称(参数、变量或方程)
  • 右侧为场景数据或结果数据的参数名称
  • 输入数据:<模型参数> . <场景数据参数>
  • 输出数据:<场景数据参数> . <模型变量/方程>

使用方法

5.1 基本用法

在 GAMS 中使用 GUSS 求解器,首先需要设置相应的模型类型:

  OPTION LP = GUSS;
  OPTION NLP = GUSS; 
  OPTION MIP = GUSS;
  OPTION RMIP = GUSS;
  OPTION RMINLP = GUSS;

然后定义场景数据、字典,并执行求解:

  Set s / s1*s5 /;
  
  Parameter
    scen_data(s, *) 场景数据
    /
      s1, demand, 100
      s2, demand, 120
      s3, demand, 150
      s4, demand, 200
      s5, demand, 250
    /;
  
  Parameter
    dict(*) / 'demand' . 'scen_data'
              'scen_data' . 'demand'  /;
  
  Parameter
    result_data(s, *);    * 存放结果
  
  Solve simple_model using LP minimizing obj;

5.2 完整调用流程

  * 步骤 1:定义模型(和平常一样)
  Variables x, obj;
  Equations eq1, eq2;
  ...
  Model mymodel /all/;
  
  * 步骤 2:定义场景集合和数据
  Set s / s1*s100 /;
  Parameter input_data(s, *) 场景输入数据;
  
  * 步骤 3:定义 GUSS Dictionary
  Parameter guss_dict(*) / ... /;
  
  * 步骤 4:准备结果数据容器
  Parameter output_data(s, *);
  
  * 步骤 5:设置 GUSS 为求解器
  OPTION LP = GUSS;
  
  * 步骤 6:求解
  Solve mymodel using LP minimizing obj;
  
  * 步骤 7:分析结果
  Display output_data;

选项与参数

6.1 关键选项

GUSS 通过 GAMS 选项和自身特有的参数控制行为。以下是最常用的选项:

选项名称 默认值 描述
GUSS dictionary "" 指定 GUSS Dictionary 参数的名称,定义场景数据和模型数据之间的映射关系。
GUSS scenario set "" 指定场景集合的名称。如果未指定,则默认使用字典中第一个数据参数的索引集合。
GUSS update data "*" 控制在每个场景中更新的数据类型:"*" 更新所有,"input" 仅更新输入参数,"output" 仅更新输出结果。
GUSS keep unsolved 0 当某个场景求解失败时,是否保留该场景的结果(0=丢弃,1=保留)。
GUSS skip invalid 0 是否跳过无效的场景定义(0=报错,1=跳过并继续)。
GUSS log frequency 1 控制日志输出频率,每隔 N 个场景输出一次求解状态。0 表示不输出。
GUSS solve link 0 是否启用求解链接模式(0=标准模式,1=链接模式)。链接模式下 GUSS 会在场景之间保持求解器的状态,加速收敛。

6.2 在 GAMS 中设置选项

  * 通过 Option 语句设置
  Option gussDict = "dict";
  Option gussSSet = "s";
  Option gussLogFrequency = 10;
  
  * 或通过 Solve 语句的选项字符串设置
  Solve mymodel using LP minimizing obj
    option gussDict = "dict", option gussLogFrequency = 10;

6.3 底层求解器选项

GUSS 将底层求解器的选项传递给实际的求解器。可以通过标准 GAMS 选项或求解器选项文件来控制底层求解器的行为:

  * 设置底层求解器选项(以 CPLEX 为例)
  Option LP = GUSS;
  Option reslim = 100;
  Option optcr = 0.05;
  
  $onecho > cplex.opt
    threads 4
    mipgap 0.01
    timelimit 60
  $offecho
  Option cplex = "cplex.opt";

GUSS Dictionary 详解

7.1 字典结构

GUSS Dictionary 是 GUSS 求解器的核心配置。它是一个 GAMS 参数,定义了模型符号和场景数据/结果数据之间的映射关系。字典的每个条目为一个两元组 (key, value)

  Parameter dict(*) /
  'demand'          . 'scen_input'    * 模型参数 -> 输入数据表
  'scen_input'      . 'demand'        * 输入数据表 -> 模型参数
  'x'               . 'scen_output'   * 模型变量 -> 输出数据表
  'scen_output'     . 'x'             * 输出数据表 -> 模型变量
  /;

7.2 字典条目类型

字典条目根据数据类型分为以下几类:

  • 输入参数映射<模型参数> . <数据参数><数据参数> . <模型参数>。将场景数据表中的值更新到模型参数中。
  • 变量映射<模型变量> . <数据参数><数据参数> . <模型变量>。将求解后的变量水平值写入结果数据表。
  • 方程映射<模型方程> . <数据参数><数据参数> . <模型方程>。将求解后的方程对偶值、slack 值等写入结果数据表。
  • 特殊值映射<特殊属性> . <数据参数>。用于将模型的整体属性(如目标函数值、求解状态等)写入结果数据表。特殊属性包括:
    • modelstat:模型状态
    • solvestat:求解状态
    • objval:目标函数值
    • resusd:资源使用量
    • iterusd:迭代次数
    • nodusd:节点使用量

7.3 完整的字典示例

  Parameter dict(*) /
  * --- 输入映射 ---
  'demand'          . 'scen_data'
  'scen_data'       . 'demand'
  'cost_coef'       . 'scen_data'
  'scen_data'       . 'cost_coef'
  
  * --- 变量映射 ---
  'x'               . 'scen_result'
  'scen_result'     . 'x'
  'y'               . 'scen_result'
  'scen_result'     . 'y'
  
  * --- 方程映射 ---
  'supply'          . 'scen_result'
  'scen_result'     . 'supply'
  
  * --- 特殊值映射 ---
  'objval'          . 'scen_result'
  'scen_result'     . 'objval'
  'modelstat'       . 'scen_result'
  'scen_result'     . 'modelstat'
  'solvestat'       . 'scen_result'
  'scen_result'     . 'solvestat'
  /;

完整示例

8.1 传感器布局优化(参数敏感性分析)

以下是一个完整的 GUSS 示例,解决一个传感器覆盖问题,分析不同预算对最优传感器布局的影响:

  * ===== 传感器布局优化 - GUSS 场景分析示例 =====
  
  Sets
    i    传感器候选位置 / location1*location20 /
    j    目标区域     / area1*area50 /
    s    场景           / s1*s10 /;
  
  Parameters
    cov(i,j)    覆盖矩阵(1=可覆盖,0=不可覆盖)
    area_val(j) 区域价值系数
    cost(i)     传感器安装成本
    budget(s)   各场景的预算限制
    /
      s1  500
      s2  600
      s3  700
      s4  800
      s5  900
      s6  1000
      s7  1200
      s8  1400
      s9  1600
      s10 2000
    /;
  
  * 生成覆盖矩阵(实际应用中使用真实数据)
  cov(i,j) = uniform(0,1) > 0.7;
  area_val(j) = uniform(10, 100);
  cost(i) = uniform(20, 100);
  
  Variables
    x(i)        是否在位置 i 安装传感器(0-1 变量)
    covered(j)  区域 j 是否被覆盖
    z           总覆盖价值;
  
  Binary Variable x;
  Integer Variable covered;
  
  Equations
    budget_eq  预算约束
    cover_eq(j) 覆盖约束
    obj         目标函数;
  
  obj ..          z =e= sum(j, area_val(j) * covered(j));
  cover_eq(j) ..  sum(i, cov(i,j) * x(i)) =g= covered(j);
  budget_eq ..    sum(i, cost(i) * x(i)) =l= budget("s1");
  
  Model sensor_placement /all/;
  
  * --- 定义 GUSS 场景数据和字典 ---
  Parameter
    scen_data(s, *)   场景数据
    scen_result(s, *) 场景结果;
  
  * 将预算数据加载到场景数据参数中
  scen_data(s, 'budget') = budget(s);
  
  Parameter dict(*) /
  'budget'         . 'scen_data'
  'scen_data'      . 'budget'
  'z'              . 'scen_result'
  'scen_result'    . 'z'
  'modelstat'      . 'scen_result'
  'scen_result'    . 'modelstat'
  'solvestat'      . 'scen_result'
  'scen_result'    . 'solvestat'
  /;
  
  * --- 使用 GUSS 批量求解所有场景 ---
  Option MIP = GUSS;
  Option gussDict = "dict";
  Option gussLogFrequency = 1;
  
  Solve sensor_placement using MIP maximizing z;
  
  * --- 输出结果 ---
  Display scen_result;
  
  * 按预算排序显示覆盖价值
  Parameter results(s, *) 分析结果;
  results(s, 'budget') = budget(s);
  results(s, 'total_value') = scen_result(s, 'z');
  results(s, 'status') = scen_result(s, 'modelstat');
  
  Display results;

8.2 运输问题(多场景需求变化)

以下是一个运输问题的 GUSS 示例,分析不同需求情景下的最优运输方案:

  * ===== 运输问题 - GUSS 多场景分析 =====
  
  Sets
    i  工厂   / plant1*plant3 /
    j  市场   / market1*market5 /
    s  场景   / base, high_demand, low_demand, peak /;
  
  Parameters
    sup(i)     供应能力
    dem(j,s)   各场景下的市场需求
    dist(i,j)  运输距离
    cost_tr(i,j) 单位运输成本;
  
  * 基本数据
  sup(i)       = [500, 800, 600];
  dem(j, 'base')        = [200, 250, 150, 180, 220];
  dem(j, 'high_demand') = [300, 350, 200, 280, 320];
  dem(j, 'low_demand')  = [150, 180, 120, 140, 160];
  dem(j, 'peak')        = [400, 450, 250, 350, 400];
  
  dist(i,j) = uniform(100, 1000);
  cost_tr(i,j) = 0.05 * dist(i,j);
  
  Variables
    ship(i,j)    运输量
    total_cost   总运输成本;
  
  Positive Variable ship;
  
  Equations
    supply_eq(i)     供应约束
    demand_eq(j,s)   需求约束(注意场景索引)
    cost_obj         成本目标;
  
  supply_eq(i) ..   sum(j, ship(i,j)) =l= sup(i);
  demand_eq(j,s) .. sum(i, ship(i,j)) =g= dem(j,s);
  cost_obj ..       total_cost =e= sum((i,j), cost_tr(i,j) * ship(i,j));
  
  Model transport /all/;
  
  * --- GUSS 场景配置 ---
  Parameter
    scen_demand(j, s) 场景需求数据;
  
  scen_demand(j, s) = dem(j, s);
  
  Parameter
    guss_dict(*) /
    'demand_eq'      . 'scen_demand'
    'scen_demand'    . 'demand_eq'
    'total_cost'     . 'scen_result'
    'scen_result'    . 'total_cost'
    'ship'           . 'scen_result'
    'scen_result'    . 'ship'
    'modelstat'      . 'scen_result'
    'scen_result'    . 'modelstat'
    'objval'         . 'scen_result'
    'scen_result'    . 'objval'
    /;
  
  Parameter scen_result(s, *);
  
  Option LP = GUSS;
  Option gussDict = "guss_dict";
  Option gussSset = "s";
  
  Solve transport using LP minimizing total_cost;
  
  * 结果分析
  Parameter summary(s, *);
  summary(s, 'obj')     = scen_result(s, 'objval');
  summary(s, 'status')  = scen_result(s, 'modelstat');
  
  Display summary;
  
  * 查看基准场景的最优运输方案
  Parameter ship_base(i,j);
  ship_base(i,j) = scen_result('base', 'ship');
  Display ship_base;

高级功能

9.1 求解链接模式(Solve Link)

求解链接模式允许 GUSS 在场景之间保持底层求解器的内部状态。对于连续的场景(如时间序列优化),这种模式可以显著加速求解过程,因为求解器可以利用前一个场景的最优解作为当前场景的初始解:

  Option gussSolveLink = 1;

使用求解链接模式的注意事项:

  • 仅适用于连续的 LP 和 NLP 模型。
  • 场景之间的参数变化不宜过大,否则热启动效果会降低。
  • 对于 MIP 模型,链接模式可以保留之前的可行解作为上界参考。

9.2 部分场景求解

当场景定义中包含大量场景时,可以选择仅求解其中的子集。这在开发和调试阶段特别有用:

  Set s    全体场景 / s1*s1000 /;
  Set ds(s)调试场景 / s1, s50, s100, s500 /;
  
  Option gussSset = "ds";  * 只求解 ds 中定义的场景

9.3 多维度场景分析

GUSS 支持多维度参数变化的场景定义。例如,同时改变供应和需求参数:

  Set param_dim / supply, demand /;
  
  Parameter multi_scen(s, param_dim);
  multi_scen(s, 'supply') = ... ;  * 各场景的供应参数
  multi_scen(s, 'demand') = ... ;  * 各场景的需求参数
  
  * 在字典中分别映射
  Parameter dict(*) /
    'sup'    . 'multi_scen'
    'multi_scen' . 'sup'
    'dem'    . 'multi_scen'
    'multi_scen' . 'dem'
    ...

9.4 结果后处理与聚合

GUSS 求解完成后,可以利用 GAMS 强大的数据处理能力对结果进行聚合分析和可视化输出:

  * 计算统计摘要
  Parameter stats(*, *);
  stats('min', s) = smin(s, scen_result(s, 'z'));
  stats('max', s) = smax(s, scen_result(s, 'z'));
  stats('avg', s) = sum(s, scen_result(s, 'z')) / card(s);
  stats('std', s) = sqrt(sum(s, sqr(scen_result(s, 'z') - stats('avg', s))) / (card(s)-1));
  
  * 导出到 GDX 文件便于外部工具分析
  Execute_unload 'scenario_results.gdx', scen_result;

9.5 使用条件场景

有时需要根据前一个场景的结果决定是否求解后续场景。GUSS 支持通过条件判断来控制场景执行:

  * 如果某个场景的目标值超过阈值,跳过后续场景
  Parameter skip_scenario(s);
  skip_scenario(s) = no;
  
  * 在 GAMS 中使用循环和 GUSS 结合实现条件场景求解
  Option LP = GUSS;
  
  * 第一次求解:基准场景
  s_active(s) = sameas(s, 'base');
  Option gussSset = "s_active";
  Solve mymodel using LP minimizing obj;
  
  * 根据基准结果决定是否求解其他场景
  If (scen_result('base', 'modelstat') = 1,
    s_active(s) = yes;
    Option gussSset = "s_active";
    Solve mymodel using LP minimizing obj;
  );

常见问题与排错

10.1 常见错误及解决方法

错误信息 可能原因 解决方法
Dictionary not found GUSS Dictionary 参数未正确定义或名称错误。 检查 Option gussDict 指定的参数名称是否正确,并确认该参数已在模型中定义。
Scenario set is empty 场景集合中没有任何元素。 检查场景集合的定义,确保至少包含一个场景。
Symbol mapping error 字典中的符号名称与模型中的符号不匹配。 验证字典中使用的所有符号名称(参数、变量、方程)与模型定义一致。
Dimension mismatch 场景数据参数与模型符号的维度不一致。 确保场景数据参数包含了模型符号所需的所有索引维度。
No solver available 未为模型类型指定有效的底层求解器。 检查是否有适合当前模型类型的底层求解器许可证及安装。
Out of memory 场景数据量过大,超出内存限制。 减少场景数量或使用更紧凑的数据表示方式。

10.2 性能优化建议

  • 减少不必要的输出:通过 Option gussLogFrequency = 0 关闭日志输出,减少 I/O 开销。
  • 合理组织场景顺序:将相似参数值的场景放在一起求解,利用求解链接模式的加速效果。
  • 使用紧凑的数据结构:避免在场景数据参数中使用稀疏度极高的数据格式。
  • 分批处理:对于超大规模的场景集(10,000+),考虑分成多个批次处理。
  • 选择合适的底层求解器:对于 LP 模型,使用 CPLEX 或 Gurobi;对于 NLP 模型,使用 CONOPT 或 SNOPT。

10.3 调试技巧

  • 先用 2-3 个场景测试 GUSS 配置,确认字典和场景数据正确后再扩展到全部场景。
  • 使用 Display 语句输出场景数据参数,验证输入数据是否正确加载。
  • 使用 Option gussLogFrequency = 1 查看每个场景的求解状态,快速定位出问题的场景。
  • 对于复杂的模型,可以先在非 GUSS 模式下求解一个场景,验证模型和求解器设置的正确性。
  • 使用 Option sysout = on 查看底层求解器的详细求解过程信息。

 


 

在线留言

尊敬的客户朋友,如您有任何意见建议,请通过下表反馈给我们,我们会尽快与您联系。

 

 

 

 

联系我们

 

微信公众号

咨询微信

企业店铺

400-621-1085

(节假日期间办公室座机如无人接听,请选择其他联系方式,感谢理解!祝您节日快乐!)

 

联系我们 快速链接 相关产品 上海卡贝信息技术有限公司

©2025  上海卡贝信息技术有限公司

产品中心

下载中心

站点地图

隐私政策

 

销售QQ咨询

产品QQ咨询

淘宝店铺

 

GAMS:概述

最近更新

相关文档

下载试用

购买咨询

Berkeley Madonna

iThink

Stella Architect

IBM SPSS Modeler

DecisionTools Suite

NeuralTools

Frontier Analyst

Vensim

RISKOptimizer

PrecisionTree

LINGO

LINDO API

What'sBest!

@RISK

BARON

BayesiaLab

Oracle Crystal Ball

GEMPACK

GTAP Database

TreeAge