在编程和建模语言中,函数是一段独立的、可重复使用的代码块,用于执行特定任务。在MindOpt APL中,自定义函数的使用非常重要,因为它们提高了建模过程的效率、可读性和灵活性。
为何使用def自定义函数:
- 可重用性:定义函数允许我们在模型中的多个位置重复使用相同的逻辑或计算,既减少了重复代码的编写工作量,还确保了逻辑的一致性。
- 维护:随着模型变得更加复杂,维护起来可能会很困难。自定义函数使得逻辑变得模块化,可以单独测试和修改函数,而不必担心影响模型的其他部分。
- 清晰的逻辑片段:自定义函数创建了清晰定义的逻辑片段,这些片段可以在理解和调试模型时轻松定位和识别。
- 提高模型的模块化:通过def关键字定义的函数促进了模型的模块化,使得模型更容易管理和扩展,同时也便于适应不断变化的业务需求。
- 优化特定计算:def关键字定义的函数可以包含复杂的计算逻辑,使得这些逻辑从模型的主体中分离出来,有利于优化和改进特定计算。
MindOpt APL中的def自定义函数示例:
- 定义一个返回数值的小函数
def f(x) = if x>10 then x-1 else x+1 end; check f(1) == 2; check f(11) == 10; def g(x) = x*x; check g(2) == 4;
- 小函数 f,它接受一个参数 x。如果 x 大于 10,函数返回 x-1;否则返回 x+1。
- 小函数 g,它计算参数 x 的平方。
- 定义一个返回真假的小函数
- 例子1:
clear model; # 清空MAPL工作空间的模型 set I:= {1,2,3,4,5,6}; def f(x) := x in I; check f(1); check f(2); check not f(10);
- 小函数f,它接受一个参数x,并判断x是否属于集合I。然后我们使用check语句进行验证和测试,确保f函数的功能正常。在这个例子中,我们分别检查了f(1)、f(2)和f(10)的结果,验证了f函数的正确性。
- 例子2:
clear model; # 清空MAPL工作空间的模型 param flow = (1,2) 1, (2,2) 2; set edge = {(1,2), (2,2)}; def f(x) = sum{(o,x) in edge} : flow[o,x]; check f(2) == 3;
- 小函数f,它接受一个参数x,并计算指定节点和其他节点之间的流量总和。
- 例子3:
clear model; # 清空MAPL工作空间的模型 set I := 1 .. 5; set J := 1 .. 3; var x[I*J] >= 0; def dist(a,b) := a*a + b*b; subto c2: sum {(i,j) in I*J } dist(i,j) * x[i,j] >= 0;
- 小函数dist,它接受两个参数a和b,并计算它们的平方和。
- 定义部分目标
clear model; # 清空MAPL工作空间的模型 param a := 5; var b >= 0 <= 1; def sum1(x) := sum{i in 1..x} i; minimize obj: (sum1(a)) * b ;
- 小函数sum1,接受一个参数x。函数的作用是计算从1到x所有整数的累加和
- 定义动态集合
clear model; # 清空MAPL工作空间的模型 set K = 3 .. 7; var y[K] >= 0; def goodone(a,b) := a > b; def bigger(i) := {j in K with goodone(j,i)}; subto c3: sum {i in bigger(5)} : y[i] >= 0;
- 小函数goodone,接受两个参数 a 和 b,判断 a 是否大于 b,并返回一个布尔值。
- 小函数 bigger,接受一个参数 i,返回集合 K 中满足 goodone(j, i) 条件的元素 j 的子集。
- 约束条件 c3,要求在集合 K 中满足 bigger(5) 的元素 i,对应的变量 y[i] 的和大于等于 0。
- 定义递归函数
clear model; # 清空MAPL工作空间的模型 set M = 1..9; set N = 1..9; var x[M*N]; def ack(i,j) := if i == 0 then j + 1 else if j == 0 then ack(i - 1, 1) else ack(i - 1, ack(i, j - 1)) end end; subto c0: ack(3,3) * x[ack(1,3),ack(2,2)] >= 0;
- 小函数 ack ,接受两个参数 i 和 j,使用 Ackermann函数的定义来进行递归计算,并返回结果。
总结:
使用def关键字自定义小函数,可以在模型中重复的使用一些复杂的计算或者逻辑,这样不仅可以有效提高模型构建的效率,还使得模型更易于阅读和维护。通过自定义小函数,模型可以在确保相同逻辑性的同时,变得更加灵活