1

我正在寻找一种二维组合算法......如果这是正确的措辞。我对 PHP 非常有经验,但对算法和高级数学没有经验,所以请多多包涵。

我有一组元素,我想将它们与另一组元素组合并计算所有可能的组合,以便之后进行分析。集合中元素的数量永远不会改变,两个集合总是有五个元素:

$set1= array('A', 'B', 'C', 'D', 'E');
$set2= array('One', 'Two', 'Three', 'Four', 'Five');

不知道这是否是正确的措辞,但我想查看Set 1 项目的所有组合,在 Set 2 的项目之间进行划分。两个集合中的所有元素只能在每种可能性中使用一次,并且 Set 1 元素可以在 Set 2 元素中组合在一起,因此我得到一个看起来像这样的结果数组(一些随机值作为示例):

$possibilities= array(
  0 => array(
    'One' => array('A'),
    'Two' => array('B'),
    'Three' => array('C'),
    'Four' => array('D'),
    'Five' => array('E'),
  ),
  1 => array(
    'One' => array('A', 'B', 'C'),
    'Two' => array('D'),
    'Three' => array('E'),
    'Four' => array(),
    'Five' => array(),
  ),
  2 => array(
    'One' => array('C'),
    'Two' => array(),
    'Three' => array('A'),
    'Four' => array('B'),
    'Five' => array('D', 'E'),
  ),
  3 => array(
    'One' => array(),
    'Two' => array(),
    'Three' => array('A', 'B', 'C', 'D', 'E'),
    'Four' => array(),
    'Five' => array(),
  ),
);

等等……那些价值观。欢迎对此提出任何反馈,特别是:

  • 如何在 PHP 中编写这样的代码?通过递归函数?我是否使用笛卡尔积算法?
  • 有多少种组合可能?5^10 ?
  • 根据前一点:在 Web 应用程序中实时处理这些数据是否可行?如果我有 1000 万个组合,我想我可能需要事先进行计算,保存结果分析并在实时应用程序执行期间使用它?
  • 有一些限制(例如:Set 2 items 'One', 'Two' and 'Three' should always have at least one item from Set 1)但无用的组合将在之后的分析过程中被丢弃,因此无需将其包含在组合算法,除非它可以通过在那时构建这些来减少计算时间?

我的问题可能不是很清楚,所以请问我是否需要提供更多或更好的信息。

提前致谢


2012 年 2 月 28 日更新

我已经尝试了我在互联网上找到的 Power Set 和笛卡尔积函数的 PHP 实现(这种东西有点超出我自己尝试和编码的能力)。所以当我执行这段代码时:

$powerset= powerSet(array('A', 'B', 'C'));
$cartesian = cartesian(array(
    'Set1' => $powerset,
    'Set2' => array('One', 'Two', 'Three')
));

这是 powerSet 函数在 $powerset 中的内容:

Array (
      [0] => Array ()
      [1] => Array (
        [0] => A
      )
      [2] => Array (
        [0] => B
      )
      [3] => Array (
        [0] => B
        [1] => A
      )
      ...

这就是笛卡尔函数返回的内容:

Array (
      [0] => Array (
        [Set1] => Array ()
        [Set2] => One
      )
      [1] => Array (
        [Set1] => Array (
          [0] => A
        )
        [Set2] => One
      )
      [2] => Array (
        [Set1] => Array (
          [0] => B
        )
        [Set2] => One
      )
      [3] => Array (
        [Set1] => Array (
          [0] => B
          [1] => A
        )
        [Set2] => One
      )
      ...

所以它有点像我想要的,但不是最难的部分。它“单独”考虑组合并且不在 Set2 中分配 Set1,确保所有三个 Set2 项目都使用所有 Set1 项目。


另一个更新:在没有编程参考的情况下重述问题

这个问题与我为战略游戏创建的分析工具有关。每次使用该工具时,玩家可以从大量单位中选择 5 个不同的单位。这些单元可以以多种方式与其他(静态)实体(我们称这些“池”)组合。如果将这些单位与某些池相结合,这些单位具有可能会或可能不会改善玩家策略的特征。例如:

  • A单元喜欢在1号池,但不喜欢在2号池
  • 单元 B 讨厌在池 1 中,除非单元 A 也在那里
  • ETC..

该工具的目的是找到哪些单元进入哪个池的最佳组合。这些是规则:

  • 从大约 50 个集合中总是选择 5 个不同的单元。所有这些单元都有不同的特性。
  • 总是有相同的 5 个池。它们具有不同的特征,但池不是从更大的集合中选择的,它们总是相同的。
  • 每个池可以包含多个单元,从 0 到 5。
  • 每个单元只能在一个池中。

输入是:

  • 5 个变量单位的列表:A、B、C、D、E
  • 5 个静态池的列表:Pool1、Pool2、Pool3、Pool4、Pool5

根据上述规则,输出应该是这两个列表之间的所有可能组合。一些例子:

组合1

  • 池 1:A
  • 池 2:B
  • 池 3:C
  • 池 4:D
  • 池 5:E

组合2

  • 池 1:A、B、C
  • 池 2:D
  • 池 3:E
  • 池 4:
  • 池 5:

组合3

  • 池 1:C
  • 池 2:
  • 池 3:A
  • 池 4:B
  • 第 5 组:D、E

组合4

  • 池 1:
  • 池 2:
  • 第 3 组:A、B、C、D、E
  • 池 4:
  • 池 5:

ETC...

所以我想做的是:

  1. 采用存在的所有可能的单元和池组合。
  2. 遍历它们并根据单元和池之间的协同作用为组合分配“战略价值”。
  3. 选取“策略价值”最高的前 10 个组合

第 2 步和第 3 步没有问题。我遇到的问题是生成池中单元的所有可能组合。

希望这是对问题的更清晰的描述

4

2 回答 2

1

好的,所以现在我想我已经知道你想做什么了。单位的集合不是单位集的幂集的元素,它们是(几乎)单位集的分区的元素。我写“几乎”是因为,严格来说,空集不是集合的分区集合的成员。现在我认为你的问题是计算一组 5 个单元的所有分区;该分区最多有 5 个元素(每个元素包含一个单元)。对于您的问题,本身不具有 5 个成员的单元集的任何分区都应填充出现的空集。

现在您必须将这些分区映射到池的顺序。您的第一个组合将池映射到单元集分区的元素,因此:{1->{A}, 2->{B}, 3->{C}, 4->{D}, 5->{E}}. 如果您还想要将池映射到单元集的同一分区的其他组合(例如,{2->{A}, 3->{B}, 4->{C}, 5->{D}, 1->{E}}您必须计算池的所有排列并将每个排列映射到单元集的同一分区。

重复直到完成。

于 2012-02-27T13:28:30.217 回答
0

您可以使用 kd-tree 或 treemap 算法。这种算法可以很好地找到最近的邻居,最近的点对或寻址空间,平铺空间。

于 2012-02-28T10:42:37.507 回答