CVXPY是否有办法将变量约束为偶数?

2024-05-19 07:42:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图写一个时钟频率和除数搜索生成一个目标频率。 然而,一个限制是除数需要是偶数(由于硬件限制),我找不到一种方法来建模。你知道吗

没有模运算符支持

"TypeError: unsupported operand type(s) for %: 'Variable' and 'int'"

以下使用除法和乘法的黑客尝试无效:

wantipp = cp.Parameter(name = 'wantedipp')  # Desired IPP

div = cp.Variable(integer = True, name = 'div') # Divisor must be integral
ipp = cp.Variable(pos = True, name = 'ipp') # nsec
constraints = [
        ipp == 1e9 / 6e6 * div,     # Constrain IPP to divisor
        div >= 2, div <= 65536,     # Divisor must be 2-65536
        div / 2 * 2 == div,         # Divisor must be even (doesn't actually work)
        ]
objective = cp.Minimize(cp.abs(ipp - wantipp))  # Find closest possible IPP
prob = cp.Problem(objective, constraints);

for i in (1e3, 2e3, 1e6, 2e6, 123123, 5412341, 1233, 12541):
    wantipp.value = i
    prob.solve()
    print('IPP %.3f nsec (%.3f Hz) -> Divisor %d %.3f nsec (%.3f Hz)' % (
          i, 1e9 / i, div.value, ipp.value, 1e9 / ipp.value
          ))

IPP 1000.000 nsec (1000000.000 Hz) -> Divisor 6 1000.000 nsec (1000000.000 Hz)
IPP 2000.000 nsec (500000.000 Hz) -> Divisor 12 2000.000 nsec (500000.000 Hz)
IPP 1000000.000 nsec (1000.000 Hz) -> Divisor 6000 1000000.000 nsec (1000.000 Hz)
IPP 2000000.000 nsec (500.000 Hz) -> Divisor 12000 2000000.000 nsec (500.000 Hz)
IPP 123123.000 nsec (8121.959 Hz) -> Divisor 739 123166.667 nsec (8119.080 Hz)
IPP 5412341.000 nsec (184.763 Hz) -> Divisor 32474 5412333.333 nsec (184.763 Hz)
IPP 1233.000 nsec (811030.008 Hz) -> Divisor 7 1166.667 nsec (857142.857 Hz)
IPP 12541.000 nsec (79738.458 Hz) -> Divisor 75 12500.000 nsec (80000.000 Hz)

也就是说,它的除数是739等等

(请注意,我从一个固定的时钟开始,稍后它会改变)

我在CVXPY 1.0.25Python 3.7.5上使用MacOSX 10.14.6。你知道吗


Tags: namedivvaluebe时钟variablecpdivisor
2条回答

要回答tile中的问题,没有任何方法可以本机创建这样的约束。如果您可以直接施加这样的约束,您将不再有一个凸包作为您的解决方案空间。你知道吗

这里的基本问题是,不能创建使范围采样不连续的约束。这在接口中以两种方式表现出来:您也不能对依赖于包含该变量的表达式的变量设置约束,并且没有为表达式定义运算符//%。你知道吗

针对特定情况的解决方法是在求解的变量和希望从中获得的值之间创建1对1的映射。偶数只是整数乘以2,因此您可以删除显式的均匀度约束并执行以下操作

constraints = [
        ipp == 1e9 / 3e6 * div,     # Constrain IPP to divisor
        div >= 1, div <= 32768,     # Divisor must be 2-65536
        ]
objective = cp.Minimize(cp.abs(ipp - wantipp))  # Find closest possible IPP

打印解决方案时,显示两倍的已解决值:

print('IPP %.3f nsec (%.3f Hz) -> Divisor %d %.3f nsec (%.3f Hz)' % (
          i, 1e9 / i, 2 * div.value, ipp.value, 1e9 / ipp.value
          ))

更好的是,使用更现代的f字串代替老式的插值:

print(f'IPP {i:.3f} nsec ({1e9 / i:.3f} Hz) -> Divisor {2 * div.value} {ipp.value:.3f} nsec ({1e9 / ipp.value:.3f} Hz)')

创建约束为偶数的变量x的完全标准方法是添加整数变量y和约束x=2y

相关问题 更多 >

    热门问题