选择满足条件的子集的算法

时间:2018-09-07 13:23:54

标签: algorithm subset

我有一些客户参考,每个参考都有一些属性:

  1. 添加时。
  2. 解决方案(例如人力资源,医疗保健,控制等)。
  3. 工业(例如运输,能源,电子等)。
  4. 它是否来自强大的品牌。
  5. 地区(例如国家/大陆)。

现在,我想选择要显示在主页上的部分参考。引用应该随机选择,以便每次有人访问我的主页时它们都不同。同时,我希望所选参考文献满足某些条件:

  1. 最近添加的参考文献被选中的可能性更高。
  2. 解决方案应该有多种选择。
  3. 行业应该多种多样。
  4. 参考文献是否来自强势品牌应该有多种选择。
  5. 该地区应该有多种选择。

如何创建这样的选择算法?

编辑2018-09-08

数据库结构

| Column           | Type   | Key type    |
|------------------|--------|-------------|
| ReferenceId      | int    | Primary key |
| AuthorName       | string |             |
| OrganisationName | string |             |
| Content          | string |             |
| AddedDate        | date   |             |
| SolutionId       | int    | Foreign key |
| IndustryId       | int    | Foreign key |
| BrandIsStrong    | bool   |             |
| RegionId         | int    | Foreign key |

解决方案

1。分配权重

一般思路:为参考分配权重,并根据参考权重组合选择参考。例如这样的

  1. 为每个参考分配权重DateWeight。参考值越大,权重越低。
  2. 对于每个解决方案,以随机顺序遍历属于该解决方案的每个引用,并为每个引用分配一个权重SolutionWeight。对于每次迭代,减少分配的权重。最后,每个解决方案中都有一个引用,其中SolutionWeight高,SolutionWeight稍低,依此类推。如果现在通过减小SolutionWeight查看所有引用,解决方案的差异会很大。
  3. 按照步骤2的步骤进行操作,但是针对行业而不是解决方案,我们将权重称为IndustryWeight而不是SolutionWeight
  4. 按照步骤2进行操作,但要针对强品牌而不是强品牌而不是解决方案,我们将权重称为BrandWeight而不是SolutionWeight
  5. 按照步骤2的步骤进行操作,但要针对区域而不是解决方案,然后将权重称为RegionWeight而不是SolutionWeight
  6. 每个参考现在有5个权重。这些应合并为一个(例如,通过加法或乘法),然后选择n个引用以显示在主页上。例如,这可以通过以下方式完成:
    1. 选择权重最高的参考文献。
    2. 一个迭代过程,其中在每次迭代中选择一个参考,并且每个参考的选择概率均相对于其总权重。

2。迭代选择

一般思想:遍历每个约束,一次选择一个参考。

  1. Unselected为尚未选择的参考集。
  2. 选择Unselected中的最新参考文献。
  3. 对于每个解决方案,在Unselected中选择一个属于该解决方案的随机引用。
  4. 对于每个行业,在Unselected中选择一个属于该行业的随机引用。
  5. 从强品牌中选择一个参考,从非强品牌中选择一个参考。
  6. 对于每个区域,在Unselected中选择一个属于该区域的随机参考。
  7. 重复步骤2至6,直到选择了n个引用为止。

此解决方案的缺点是,如果约束之一包含许多选项(例如,不同行业的数量大于n)。然后,该过程将在甚至完成一次迭代之前停止。

3。调整重量

一般思想:对于每个选定的参照,请减少分配给与选定参照具有相同属性的参照的权重。

  1. 为每个参考分配相同的权重。
  2. 使用加权随机选择来选择参考。
  3. 使用与所选参考相同的解决方案减少所有参考的权重。
  4. 减少与所选参考文献具有相同行业的所有参考文献的权重。
  5. 如果所选参考来自强品牌,请减少所有来自强品牌的参考的权重。如果所选参考不是来自强品牌,请减少所有非来自强品牌的参考的权重。
  6. 减少与所选参考区域相同的所有参考的权重。
  7. 重复步骤2至7,直到选择了n个引用为止。

1 个答案:

答案 0 :(得分:1)

我认为这主要取决于如何量化可接受的解决方案以及如何定义约束There should be a variety in [...]。您还必须决定在数据高度相关的情况下该怎么做:例如,如果大多数“强品牌”参考来自一个“行业”,那么由于您希望代表许多行业,因此只有一小部分“品牌”元素。在这种情况下,您将无法同时拥有两者。

让我们假设您需要在页面上显示n个项目。这是一个外部约束,可能由包含项目列表的Web元素的大小定义;其余约束由您选择。

跳转到底部的 tl; dr 部分以跳过详细信息。

解决方案1:便宜且(通常)有效:100%随机

您可以简单地随机选择n个引用,然后由Universe决定将哪些项添加到您的页面。如果您的数据或多或少均匀地分布在各个列中,并且如果n“足够大”,则大多数时候您将获得足够的数据。如果需要快速实现,这也使您的代码很容易维护/升级,因此可以在有更好算法的情况下稍后再使用。

现在这不能解决

  

最近添加的参考文献被选中的可能性更高

部分,所以我们可以做得更好

解决方案2:不是100%随机

这是第一个解决方案的略微修改版本。在这一步中,您从最新的“ ReferenceId”开始,并按照“ ReferenceId”的降序,沿数据集进行迭代。每个项目都有被选择的概率p,选择的可能性是使n元素通常位于数据集的N最近的元素内。如果您在选择n元素之前到达底部,则只需从顶部重新开始(或增加p)。

在Java中,它看起来像:

for (Object item : items) {
    if (random.nextDouble() < p) {
        result.add(item);
    }
    if (result.size() == n) {
        break;
    }
}

但是,如果您的数据不是均匀分布(可能是这种情况,因为您是在问这个问题),那么您就不能仅依靠随机性来生成项目集。在继续进行解决方案3之前,请检查此解决方案是否对您有用。如果没有,

解决方案3:制定约束条件并尝试满足约束条件,贪婪的方法

您现在要做的是定义一组大小n以满足全局数据集要求的含义。

您必须知道,由于要调整最终组合中每个被选中项目的几率,因此您可能无法真正拥有

  

每次有人访问我的主页时,它们都是不同的

要真正确定这一点,请想象一个示例,其中“区域”之一仅由整个数据集中的一项表示:由于您要强制采用多样性,因此它很可能始终位于最终选择的子集中。还有一个事实是,由于您对最近添加的引用具有特权,因此您的数据分布将更紧密地反映最新条目的数据分布。

因此,现在您不必总是具有 true 随机性统一表示,就可以放心了,让我们制定约束条件。列的约束可以采用“我希望在最终子集中与该列至少具有n/10个不同的元素”的形式。您可以使用函数(S, n, k) -> {true, false}将约束的状态评估为“满意”或“不满意”,其中:

  • S是当前所选项目集
  • n是所选项目的所需大小
  • k是该列的基数

说“给定当前的元素子集,此约束是否得到满足?”。您还可以评估元素是否有助于满足约束条件,例如:“给定元素的当前子集,如果添加此项,我们是否更接近满足该约束条件?”。

就像上面的解决方案2一样进行迭代,并保留每个元素的随机性,还添加了约束Set约束的检查。满足约束后,将其从约束集中删除。

没有实现细节,您将得到类似的信息:

for (Object item : items) {
    // every item still has some probability of being chosen or not
    if (random.nextDouble() < p && helpsSatsfyAtLeastOne(remainingConstraints, item, result, n)) {
        result.add(item);                       
    }
    for (/* Appropriate data structure */ constraint : remainingConstraints) {
        if (constraint.isSatisfied(result, n)) {
            constraints.remove(constraint);
        }
    }
    if (result.size() == n) {
        break;
    }
}
System.out.println("Unsatisfied constraints: " + remainingConstraints);

您可以实施helpsSatsfyAtLeastOne(...)来强制执行约束的顺序,以满足需要优先排序的约束,或者只是使它以不特定的顺序遍历约束。

这是一种贪婪的方法,您不能保证最终结果将是100%完美的。如果最后仍然不能满足某些约束条件,请尝试在这些约束条件中强制执行优先级。

tl; dr

这种方法很简单,大多数情况下应该可以给您足够好的结果。如果不是这样,并且您的数据集如此具体,以至于您需要更精确的解决方案,那么还有更多工作要做。但我认为情况并非如此,因为您只想要网页上一组不错的多样化元素。

  1. 量化满足约束的含义(根据 基数,代表一个元素的相对/绝对数量 列等)
  2. 通过递减日期顺序(最新) 首先)
  3. 每个项目都有被选中的p可能性
    1. 如果选择了一个项目(通过概率过程),请检查是否添加了 它对结果造成了至少一个约束(即: 会增加someColumn的数量?)。如果是这样,请将其添加到 结果。
    2. 然后检查该元素现在是否满足一些约束 被添加(即“我的结果中是否有someColumn 个? 设置?”)。删除这些约束。
  4. 如果满足所有约束条件,但您仍然可以向集合中添加元素,则可以按照自己喜欢的方式随机添加一些元素。