【问题标题】:Could this problem be solved using mixed integer non-linear programming or any other optimization technique?可以使用混合整数非线性规划或任何其他优化技术来解决这个问题吗?
【发布时间】:2020-11-18 00:36:58
【问题描述】:

问题来了:

  • 在一个有限集合 = [1, 10, 20, 40, 100, 200] 中有 4 个整数变量。
  • 当所有 4 个连接在一起时(比如 1 || 1 || 10 || 20 = 111020),结果可以被 13 整除。

我尝试了 Python 的 pyomo 库,但找不到解决方案,因为没有模运算来决定数字是否可以被 13 整除。

【问题讨论】:

  • 您不需要任何库。这是一项可以通过 Python 中的简单函数来解决的任务。也不需要“优化”或任何其他数值算法。唯一的数字是检查一个数字是否能被 13 整除。剩下的就是字符串连接。
  • 同意以上评论。优化引擎将是一个糟糕的选择,因为满足条件的测试非常奇怪并且非常非线性。只需通过排列暴力破解它,然后在它运行时去喝杯咖啡。
  • 抱歉含糊不清。这些不是实际数字,它们只是样本。实际数字远不止于此,无法使用暴力破解。
  • 模数很简单。连接对我来说似乎更难(数值而不是字符串)。
  • Here 是解决此问题的 MINLP 模型。

标签: python concatenation pyomo nonlinear-optimization mixed-integer-programming


【解决方案1】:

这可以使用MiniZinc 建模语言以与Erwin Kalvelagen 在cmets 中完成的模型类似的方式相当直接地建模。主要思想是为每个数字建立因子,并将其全部相乘。 MiniZinc 原生支持 mod 运算符,但并非所有求解器都能处理它。

使用 MiniZinc IDE 2.4.3 版中的内置 Gecode 6.1.1 求解器为您的实例找到了 108 个解决方案。 Chuffed 和 COIN-BC 内置求解器都无法处理该模型。

这种建模方式的主要缺点是它需要建立串联的全部值。由于求解器通常具有有限的值范围 可以表示,这对值的数量和大小设置了上限。例如,Gecode 基本上可以处理 32 位整数作为值。

这里给出了你的问题的完整模型

include "globals.mzn";

%
% Problem data
%

% The set of allowed values
set of int: Values = {1, 10, 20, 40, 100, 200};

% The number of value to concatenate
int: n = 4;


%
% Derived data
%

% The available values as an index set
set of int: Index = 1..card(Values);
% The values as an array
array[Index] of int: values = [v | v in Values];
% The length of values in decimal notation
array[Index] of int: lengths = [ceil(log10(v+1)) | v in Values];
% A mapping table from values to the widths of the numbers
array[Index, 1..2] of int: value_to_widths = array2d(Index, 1..2, [
    [values[i], 10^lengths[i]][v_or_w]
    | i in Index, v_or_w in 1..2]);
% The numbers as an index set
set of int: N = 1..4;


%
% Variables
%

% The numbers to choose
array[N] of var Values: numbers;
% The widths of the numbers
array[N] of var int: widths;
% The factors to use for concatenation
array[1..n] of var int: factors;
% The concatenation of the numbers
var int: concatenation;


%
% Constraints
%

% For each number, find the widths of it using the mapping table
constraint forall (i in N) (
    table([numbers[i], widths[i]], value_to_widths) 
);

% Find the factors to multiply numbers with for the concatenation
constraint factors[n] == 1;
constraint forall (i in 1..n-1) (factors[i] == widths[i+1] * factors[i+1]);

% Concatenate the numbers using the factors
constraint concatenation == sum(i in N) (numbers[i] * factors[i]);

% Problem constraint, the concatenation should be evenly divisible by 13
constraint concatenation mod 13 == 0;


%
% Solve and output
%

% Find solutions using standard search
% 636 failures to find all solutions using Gecode 6.1.1
%solve satisfy;

% Find solution by setting the least significant number first
% 121 failures to find all solutions using Gecode 6.1.1
solve :: int_search(reverse(numbers), input_order, indomain_min) satisfy;

% Find the smallest concatenation using the numbers
%solve minimize concatenation;

% Find the largest concatenation using the numbers
%solve maximize concatenation;

% Output both data and variables
output [
  "values=", show(values), "\n",
  "lengths=", show(lengths), "\n",
  "v_to_w={ "] ++ [show(value_to_widths[i, 1]) ++ "->" ++ show(value_to_widths[i, 2]) ++ " "|i in Index] ++ ["}\n",
  "numbers=", show(numbers), "\n",
  "widths=", show(widths), "\n",
  "factors=", show(factors), "\n",
  "concatenation=", show(concatenation), "\n",
];

当找到所有解决方案并打印统计数据时,以下输出包括第一个和最后一个解决方案

values=[1, 10, 20, 40, 100, 200]
lengths=[1, 2, 2, 2, 3, 3]
v_to_w={ 1->10 10->100 20->100 40->100 100->1000 200->1000 }
numbers=[20, 1, 1, 1]
widths=[100, 10, 10, 10]
factors=[1000, 100, 10, 1]
concatenation=20111
----------
[... lots of more solutions printed ...]
----------
values=[1, 10, 20, 40, 100, 200]
lengths=[1, 2, 2, 2, 3, 3]
v_to_w={ 1->10 10->100 20->100 40->100 100->1000 200->1000 }
numbers=[10, 40, 200, 200]
widths=[100, 100, 1000, 1000]
factors=[100000000, 1000000, 1000, 1]
concatenation=1040200200
----------
==========
%%%mzn-stat: initTime=0.000603
%%%mzn-stat: solveTime=0.003856
%%%mzn-stat: solutions=108
%%%mzn-stat: variables=15
%%%mzn-stat: propagators=12
%%%mzn-stat: propagations=8098
%%%mzn-stat: nodes=457
%%%mzn-stat: failures=121
%%%mzn-stat: restarts=0
%%%mzn-stat: peakDepth=7
%%%mzn-stat-end
Finished in 253msec

【讨论】:

    猜你喜欢
    • 2020-08-20
    • 2020-11-21
    • 2016-01-24
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    相关资源
    最近更新 更多