Python CVXPY是否有办法将变量约束为偶数?
我试图写一个搜索时钟频率和除数的程序来生成目标频率。 然而一个限制是由于硬件的限制,除数必须是偶数,我找不到一种方法来建模 没有模运算符支持 TypeError:不支持%的操作数类型:'Variable'和'int' 以下使用除法和乘法的黑客尝试无效:Python CVXPY是否有办法将变量约束为偶数?,python,python-3.x,cvxpy,Python,Python 3.x,Cvxpy,我试图写一个搜索时钟频率和除数的程序来生成目标频率。 然而一个限制是由于硬件的限制,除数必须是偶数,我找不到一种方法来建模 没有模运算符支持 TypeError:不支持%的操作数类型:'Variable'和'int' 以下使用除法和乘法的黑客尝试无效: wantipp = cp.Parameter(name = 'wantedipp') # Desired IPP div = cp.Variable(integer = True, name = 'div') # Divisor must b
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)
i、 它的除数是739等等
请注意,我从一个固定的时钟开始,稍后它会改变
我正在MacOSX 10.14.6上使用CVXPY 1.0.25和Python 3.7.5。为了回答您的互动程序中的问题,没有办法以本机方式创建这样的约束。如果您可以直接施加这样的约束,您将不再有凸包作为解决方案空间 这里的基本问题是,不能创建使范围采样不连续的约束。这在接口中以两种方式显示:也不能对依赖于包含该变量的表达式的变量进行约束,并且没有为表达式定义运算符//和% 针对特定情况的解决方法是在您求解的变量和您希望从中获得的值之间创建一个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
更好的是,使用更现代的f字符串代替老式的插值:
print(f'IPP {i:.3f} nsec ({1e9 / i:.3f} Hz) -> Divisor {2 * div.value} {ipp.value:.3f} nsec ({1e9 / ipp.value:.3f} Hz)')
要回答互动程序中的问题,没有办法以本机方式创建这样的约束。如果您可以直接施加这样的约束,您将不再有凸包作为解决方案空间 这里的基本问题是,不能创建使范围采样不连续的约束。这在接口中以两种方式显示:也不能对依赖于包含该变量的表达式的变量进行约束,并且没有为表达式定义运算符//和% 针对特定情况的解决方法是在您求解的变量和您希望从中获得的值之间创建一个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
更好的是,使用更现代的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。创建约束为偶数的变量x的完全标准方法是添加一个整数变量y和约束x=2y。考虑在使用数字的任何地方添加一个因子2,而不是一个限制例如,objective=cp.Minimizecp.abs2*ipp-wantippI突然想到了这个想法,它确实奏效,但感觉很糟糕。为什么?这在数学上是合理的。Try div//2*2==div./不会约束任何内容,因为它是真正的除法。让我知道这是怎么回事,我会给出一个答案。TypeError失败:不支持//:“Variable”和“int”的操作数类型。我还尝试了cp.floordiv/2*2==div,但是我得到了floordiv/2.0的DCP错误,考虑到在使用数字而不是约束的地方添加因子2。例如,objective=cp.Minimizecp.abs2*ipp-wantippI突然想到了这个想法,它确实奏效,但感觉很糟糕。为什么?这在数学上是合理的。Try div//2*2==div./不会约束任何内容,因为它是真正的除法。让我知道这是怎么回事,我会给出一个答案。TypeError失败:不支持//:“Variable”和“int”的操作数类型。我还尝试了cp.floordiv/2*2==div,但是我得到了floordiv/2.0的DCP错误