0

我目前正在开发一个求解器,以根据项目响应理论 3pl 方程返回一组优化的问题。

最初,我在约束中没有任何“弹性”来开发它,以满足特定目标。然而,我发现结果经常被认为是不可行的,尽管它工作正常。约束目标的不灵活性导致了问题。

我已经进行了一些重构以利用弹性约束来允许每个目标的范围 +/-。

下面列出了一个示例(仅显示一个目标约束......但是有几个):

self.solver_run.items = #list of items
self.solver_run.bundles = #list of bundles

# setup vars
items = LpVariable.dicts(
    "Item", [item.id for item in self.solver_run.items],
    lowBound=1,
    upBound=1,
    cat='Binary')
bundles = LpVariable.dicts(
    "Bundle", [bundle.id for bundle in self.solver_run.bundles],
    lowBound=1,
    upBound=1,
    cat='Binary')

problem = LpProblem("ata-form-generate", LpMinimize)
problem_objective_functions = []

# constraints - limit number of items used (for example 10)
problem += lpSum(
    [
        bundle.count * bundles[bundle.id]
        for bundle in self.solver_run.bundles
    ] + [
        1 * items[item.id]
        for item in self.solver_run.unbundled_items()
    ]
) == self.solver_run.total_form_items, 'Total bundle form items for form'

# create objective function
tcc = lpSum([
    bundle.trf(self.solver_run.irt_model, target.theta) *
    bundles[bundle.id] for bundle in self.solver_run.bundles
] + [
    item.irf(self.solver_run, target.theta) * items[item.id]
    for item in self.solver_run.items
])
...
problem_objective_functions.append(tcc)

e = LpAffineExpression(
    [(bundles[bundle.id],
      bundle.trf(self.solver_run.irt_model, target.theta))
     for bundle in self.solver_run.bundles] +
      [(items[item.id], item.irf(self.solver_run, target.theta))
     for item in self.solver_run.items])
constraint = LpConstraint(
    e=e,
    sense=0,
    name=f'trf theta ({target.theta}) @{target.value}',
    rhs=target.value)
elastized_constraint = constraint.makeElasticSubProblem(
    penalty=1, proportionFreeBound=0.25)
problem.extend(elastized_constraint)
...

problem.sequentialSolve(problem_objective_functions)

我为右侧提供的目标值为LpConstraint20.00,但我知道在测试结果总和时约为 0.01 - 0.02。我设置了这个目标以确保优化失败。不过还是过去了。

在检查构造问题时,我看到:

...

SUBJECT TO
Total_bundle_form_items_for_form: 3 Bundle_1 + 3 Bundle_2 + 5 Bundle_3
 + Bundle_4 + 4 Bundle_5 + 2 Bundle_6 + Item_20 + Item_21 + Item_22 + Item_23
 + Item_24 + Item_25 + Item_26 + Item_27 + Item_28 + Item_29 + Item_30
 + Item_34 = 10

...

tcc_theta_(_2.5)_@20.0_elastic_SubProblem_Constraint: 0.0102267186003 Bundle_1
+ 0.00689950699362 Bundle_2 + 0.0114991783227 Bundle_3
+ 0.00229983566454 Bundle_4 + 0.00919934265816 Bundle_5
+ 0.00459967132908 Bundle_6 + 0.00229983566454 Item_10
+ 0.00229983566454 Item_11 + 0.00229983566454 Item_12
+ 0.00229983566454 Item_13 + 0.00229983566454 Item_14
+ 0.00229983566454 Item_15 + 0.00229983566454 Item_16
+ 0.00229983566454 Item_17 + 0.00229983566454 Item_18
+ 0.00229983566454 Item_19 + 0.00229983566454 Item_20
+ 0.00229983566454 Item_21 + 0.00229983566454 Item_22
+ 0.00229983566454 Item_23 + 0.00229983566454 Item_24
+ 0.00229983566454 Item_25 + 0.00229983566454 Item_26
+ 0.00229983566454 Item_27 + 0.00229983566454 Item_28
+ 0.00229983566454 Item_29 + 0.00229983566454 Item_30
+ 0.00229983566454 Item_32 + 0.00229983566454 Item_33
+ 0.00229983566454 Item_34 + 0.00562704727121 Item_4
+ 0.00229983566454 Item_6 + 0.00229983566454 Item_7
+ 0.00229983566454 Item_75 + 0.00229983566454 Item_8
+ 0.00229983566454 Item_9
+ tcc_theta_(_2.5)_@20.0_elastic_SubProblem_free_bound
+ tcc_theta_(_2.5)_@20.0_elastic_SubProblem_neg_penalty_var
+ tcc_theta_(_2.5)_@20.0_elastic_SubProblem_pos_penalty_var = 20

...

 VARIABLES
 0 <= Bundle_1 <= 1 Integer
 0 <= Bundle_2 <= 1 Integer
 0 <= Bundle_3 <= 1 Integer
 0 <= Bundle_4 <= 1 Integer
 0 <= Bundle_5 <= 1 Integer
 0 <= Bundle_6 <= 1 Integer
 0 <= Item_10 <= 1 Integer
 0 <= Item_11 <= 1 Integer
 0 <= Item_12 <= 1 Integer
 0 <= Item_13 <= 1 Integer
 0 <= Item_14 <= 1 Integer
 0 <= Item_15 <= 1 Integer
 0 <= Item_16 <= 1 Integer
 0 <= Item_17 <= 1 Integer
 0 <= Item_18 <= 1 Integer
 0 <= Item_19 <= 1 Integer
 0 <= Item_20 <= 1 Integer
 0 <= Item_21 <= 1 Integer
 0 <= Item_22 <= 1 Integer
 0 <= Item_23 <= 1 Integer
 0 <= Item_24 <= 1 Integer
 0 <= Item_25 <= 1 Integer
 0 <= Item_26 <= 1 Integer
 0 <= Item_27 <= 1 Integer
 0 <= Item_28 <= 1 Integer
 0 <= Item_29 <= 1 Integer
 0 <= Item_30 <= 1 Integer
 0 <= Item_32 <= 1 Integer
 0 <= Item_33 <= 1 Integer
 0 <= Item_34 <= 1 Integer
 0 <= Item_4 <= 1 Integer
 0 <= Item_6 <= 1 Integer
 0 <= Item_7 <= 1 Integer
 0 <= Item_75 <= 1 Integer
 0 <= Item_8 <= 1 Integer
 0 <= Item_9 <= 1 Integer
 -5 <= tcc_theta_(_2.5)_@20.0_elastic_SubProblem_free_bound <= 5 Continuous
 -inf <= tcc_theta_(_2.5)_@20.0_elastic_SubProblem_neg_penalty_var <= 0 Continuous
 tcc_theta_(_2.5)_@20.0_elastic_SubProblem_pos_penalty_var Continuous

penalty这可能是我对属性的工作原理或一般弹性约束的工作原理缺乏了解。它似乎正确地创建了自由绑定(-5 <= tcc_theta_(_2.5)_@20.0_elastic_SubProblem_free_bound <= 5 Continuous)。那么为什么即使总和的结果超出目标范围,它也总是返回呢?Optimal

参考:

https://coin-or.github.io/pulp/guides/how_to_elastic_constraints.html

https://coin-or.github.io/pulp/technical/pulp.html#pulp.LpConstraint

https://groups.google.com/g/pulp-or-discuss/c/_qH73ylmhME/m/nuufhPDcGB4J

如何将纸浆中的弹性子问题用作约束?

4

1 回答 1

0

您的示例在几个方面令人困惑且不完整,因此无法很好地复制它。我建议将其编辑为精简的内容,以重现您所看到的行为。

也就是说,您不正确地限制了变量。对于您中的二进制变量,pulp您隐含地具有 [0, 1] 的界限。您不必要地声明它们,并且您将 a 设置lowbound为 1,所以现在,您的所有变量都固定为 1。首先尝试修复它,如果有必要,也许将您的示例缩减为更容易重现的东西。

于 2022-02-14T22:33:09.293 回答