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

Pyomo模型约束公式代码内文档化的最佳实践与方案问询

Pyomo约束文档化(含LaTeX公式)的最佳实践与Sphinx兼容方案

核心需求是在代码内用LaTeX编写Pyomo约束的数学表达式,并让这些文档能被Sphinx autodoc识别提取。针对你提到的@decorator语法下Sphinx无法识别内部函数文档的问题,以下是几种可行的解决方案:

方案1:将约束规则重构为类方法(最成熟兼容)

摒弃__init__内的装饰器写法,把约束规则定义为类的静态/实例方法,再在__init__中关联到Pyomo模型。这种方式能让Sphinx直接抓取方法的文档字符串,同时尽量减少冗余:

import pyomo.environ as pyo

class Model:
    def __init__(self, **kwargs):
        self.model = pyo.ConcreteModel()
        self.model.T = pyo.RangeSet(1, 24)
        self.model.x = pyo.Var(self.model.T, within=pyo.NonNegativeReals)
        # 关联约束规则到模型组件
        self.model.Example_Constraint = pyo.Constraint(rule=self.example_constraint_rule)

    @staticmethod
    def example_constraint_rule(model):
        """示例约束:总产出下限约束
        
        .. math::
            \sum_{t \in T} x_{t} \geq 100
        """
        return sum(model.x[t] for t in model.T) >= 100
  • 优势:Sphinx autodoc可直接识别example_constraint_rule的文档,LaTeX公式正常渲染;静态方法避免实例依赖,代码结构清晰;仅需一次规则关联操作,冗余度低。
  • 注意:约束组件名(如Example_Constraint)和规则方法名保持对应即可,便于维护。

方案2:自定义装饰器同步文档到Pyomo组件

保留装饰器语法的同时,自定义装饰器将内部函数的文档字符串同步到Pyomo约束组件的doc属性,再通过Sphinx扩展提取该属性:

自定义装饰器代码

import pyomo.environ as pyo

def documented_constraint(model):
    def decorator(rule_func):
        # 创建约束组件并绑定规则
        constraint = pyo.Constraint(rule=rule_func)
        # 将规则函数的文档字符串赋值给约束组件的doc属性
        constraint.doc = rule_func.__doc__
        # 将约束添加到模型,使用规则函数的名称作为组件名
        setattr(model, rule_func.__name__, constraint)
        return constraint
    return decorator

class Model:
    def __init__(self, **kwargs):
        self.model = pyo.ConcreteModel()
        self.model.T = pyo.RangeSet(1, 24)
        self.model.x = pyo.Var(self.model.T, within=pyo.NonNegativeReals)

        @documented_constraint(self.model)
        def Example_Constraint(model):
            """示例约束:总产出下限约束
            
            .. math::
                \sum_{t \in T} x_{t} \geq 100
            """
            return sum(model.x[t] for t in model.T) >= 100

Sphinx扩展配置

编写简单的Sphinx扩展来提取Pyomo约束的doc属性:

  1. 在项目中创建sphinx_ext/pyomo_docs.py:
from sphinx.ext.autodoc import AttributeDocumenter
import pyomo.environ as pyo

class PyomoConstraintDocumenter(AttributeDocumenter):
    @classmethod
    def can_document_member(cls, member, membername, isattr, parent):
        return isinstance(member, pyo.Constraint)

    def add_content(self, more_content, no_docstring=False):
        # 提取约束的doc属性并添加到文档
        if not no_docstring and hasattr(self.object, 'doc') and self.object.doc:
            self.add_line('', '<autodoc>')
            for line in self.object.doc.splitlines():
                self.add_line(line, '<autodoc>')
        super().add_content(more_content, no_docstring)

def setup(app):
    app.add_autodocumenter(PyomoConstraintDocumenter)
  1. 在Sphinx的conf.py中添加扩展:
extensions = [
    # 其他已有扩展
    'sphinx_ext.pyomo_docs'
]
  • 优势:保留了装饰器的简洁语法,无需额外定义类方法;通过扩展实现Sphinx对Pyomo组件文档的支持。

方案3:手动为约束组件赋值文档字符串(小项目快速实现)

无需额外工具,直接在定义约束后手动将LaTeX文档字符串赋值给约束的doc属性,再通过上述Sphinx扩展提取:

import pyomo.environ as pyo

class Model:
    def __init__(self, **kwargs):
        self.model = pyo.ConcreteModel()
        self.model.T = pyo.RangeSet(1, 24)
        self.model.x = pyo.Var(self.model.T, within=pyo.NonNegativeReals)

        # 定义约束规则
        def example_constraint_rule(model):
            return sum(model.x[t] for t in model.T) >= 100
        # 创建约束组件
        self.model.Example_Constraint = pyo.Constraint(rule=example_constraint_rule)
        # 手动添加包含LaTeX的文档字符串
        self.model.Example_Constraint.doc = """示例约束:总产出下限约束
        
        .. math::
            \sum_{t \in T} x_{t} \geq 100
        """
  • 优势:实现简单,适合小型项目;无需修改原有代码结构过多。
  • 劣势:文档字符串与规则分离,维护时需同步修改。

内容的提问来源于stack exchange,提问作者Roderick Go

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:55:15