Algorithm 如何找到一组特定大小的元素,其中包括集合集合中可能的最大集合?
给定基数介于1和6之间的有限集族,它们本身是更大的有限可能元素集的子集,我的目标是创建包含性最强的元素集,即,创建集的元素可用于从集合族中创建最可能的集合。我不完全确定我是否正确地陈述了这个问题,因为我在学校研究这类问题已经有很长时间了,但让我试着通过一个例子来澄清 以下是最大元素数为6的集合族示例:Algorithm 如何找到一组特定大小的元素,其中包括集合集合中可能的最大集合?,algorithm,set,mathematical-optimization,Algorithm,Set,Mathematical Optimization,给定基数介于1和6之间的有限集族,它们本身是更大的有限可能元素集的子集,我的目标是创建包含性最强的元素集,即,创建集的元素可用于从集合族中创建最可能的集合。我不完全确定我是否正确地陈述了这个问题,因为我在学校研究这类问题已经有很长时间了,但让我试着通过一个例子来澄清 以下是最大元素数为6的集合族示例: {1029} {1029} {1049} {1029,1049} {1029,1049,1118,1125} {1029,1112,1125,1505} {1029,1049,1094,1112,
{1029}
{1029}
{1049}
{1029,1049}
{1029,1049,1118,1125}
{1029,1112,1125,1505}
{1029,1049,1094,1112,1505,1525}
{1029,1125,1138,1505,1525}
{1049,1094,1125,1182,1525,1531}
这些集合由较大的有限元素集创建:
{1029,1049,1094,1112,1118,1125,1138,1182,1505,1525,1531}
目标是创建不超过6个图元的集合,这些图元可用于重新创建族中最大数量的集合。以下是答案集的示例:
Created Set 1: {1029,1049,1112,1118,1125,1505}
创建的集合元素可用于重新创建族中的6个集合
{1029}
{1029}
{1049}
{1029,1049}
{1029,1049,1118,1125}
{1029,1112,1125,1505}
希望这是有道理的。显然,集合的族和可能元素的集合要大得多。我还需要重复创建集合的过程,直到可以重新创建族中的所有集合
我真的在寻找一个算法解决方案,用任何编程语言或伪代码编写都会特别有帮助,但即使是我可以用来翻译成代码的数学公式也很有帮助。如果我能找出这类问题的名称,我甚至会很高兴,这样我就能自己对它进行更有效的研究。谢谢大家! 在我看来,这很简单。作为一个术语,我将把你们的给定集合称为原始集合,你们制造的集合称为选择的集合。这与集合覆盖问题的关键区别在于,您不需要从原始集合中选取所选集合
当且仅当原始集是所选集的子集时,才能从所选集“创建”原始集。类似地,如果原始集是所选集并集的子集,则可以从所选集的集合创建原始集。因此,当原始集合的并集是所选集合的并集的子集时,可以创建所有原始集合。因此,你可以通过将原始集合的并集,然后以你喜欢的任何方式,将该并集划分为不超过6个元素的集合来制造所选集合。好的,所以我找到了一个答案,尽管它可能不是有史以来最优化的解决方案。如果有人能帮我更快地完成这篇文章,或者帮我写这篇文章,让它能够找到最佳的前三名,我将不胜感激。这是我的代码,请注意,我使用的是数据结构“Set”,可从
class ProductionOptimizer{
私有整数$基数=6;
私有组合站点生成器$CombinationsIterator;
私人阵列元门票;
私有设置$threads;
公共函数构造(数组$array){
$this->tickets=$array;
$start=microtime(真);
$this->threads=newset();
foreach($ticketThreads形式的数组){
foreach($ticketThreads作为$thread)
$this->threads->add($thread);
}
$end=微时间(真);
//打印($this->threads);
echo PHP_EOL.“创建集合需要“$end-$start.”秒才能完成;
$this->combinationsIterator=new-combinationsIterator($this->gethreadsaarray(),6);
}
公共函数输出线程():void{
打印($this->threads);
}
公共函数getThreadsAsArray():数组{
返回$this->threads->toArray();
}
公共函数getCombinationsIterator():CombinationsIterator{
返回$this->combinationsIterator;
}
公共函数createNewCombinationsIterator(数组$array,int$subsetCardinality=null):组合SiteRator{
如果(为空($subsetCardinality))$subsetCardinality=$this->CARDINALITY;
$this->combinationsIterator=new combinationsIterator($array,$subsetCardinality);
返回$this->combinationsIterator;
}
公共函数removeFromSet(数组$array){
//变量转储($this->threads);
echo“正在删除线程(在计数之前):“.this->Threads->count()”...PHP_EOL;
$this->threads->remove(…$array);
//变量转储($this->threads);
echo“正在删除线程(在计数之后):“.this->Threads->count()”…….PHP\u EOL;
$this->combinationsIterator=new-combinationsIterator($this->gethreadsaarray(),6);
}
公共函数getSet():Set{
返回$this->threads;
}
公共函数getThreads():Set{
返回$this->threads;
}
/*如果使用Set类,则不需要*/
/*
设置:
代码用了4.50611111450195E-5秒完成。
此功能:
代码用了0.0054061412811279秒完成。
*/
公共功能重复数据消除阵列($array){
array_walk_recursive($array,function($v)use(&$r){$r[]=$v;});
返回数组_值(数组_唯一($r));
}
}
类组合Siterator实现迭代器
{
受保护的$c=null;
受保护的$s=null;
受保护的$n=0;
受保护$k=0;
受保护的$pos=0;
函数构造($s,$k){
if(is_数组($s)){
$this->s=array\u值($s);
$this->n=计数($this->s);
}否则{
$this->s=(字符串)$s;
$this->n=strlen($this->s);
}
$this->k=$k;
$this->revind();
}
函数键(){
返回$this->pos;
}
函数电流(){
$r=数组();
对于($i=0;$i<$this->k;$i++)
$r[]=$this->s[$this->c[$i]];
返回为数组($this->s)$r:内爆(“”,$r);
}
函数next(){
如果($this->_next())
$this->pos++;
其他的
$this->pos=-1;
class ProductionOptimizer{
private int $CARDINALITY=6;
private CombinationsIterator $combinationsIterator;
private array $tickets;
private Set $threads;
public function __construct(array $array){
$this->tickets=$array;
$start = microtime(TRUE);
$this->threads=new Set();
foreach ($array as $ticketThreads){
foreach ($ticketThreads as $thread)
$this->threads->add($thread);
}
$end = microtime(TRUE);
// print_r($this->threads);
echo PHP_EOL."Creating the Set took " . ($end - $start) . " seconds to complete.";
$this->combinationsIterator=new CombinationsIterator($this->getThreadsAsArray(),6);
}
public function outputThreads() : void {
print_r($this->threads);
}
public function getThreadsAsArray() : array {
return $this->threads->toArray();
}
public function getCombinationsIterator() : CombinationsIterator{
return $this->combinationsIterator;
}
public function createNewCombinationsIterator(array $array, int $subsetCardinality=null) : CombinationsIterator {
if(is_null($subsetCardinality)) $subsetCardinality=$this->CARDINALITY;
$this->combinationsIterator=new CombinationsIterator($array, $subsetCardinality);
return $this->combinationsIterator;
}
public function removeFromSet(array $array){
// var_dump($this->threads);
echo "Removing Threads(before count :".$this->threads->count().")...".PHP_EOL;
$this->threads->remove(...$array);
// var_dump($this->threads);
echo "Removing Threads(after count: ".$this->threads->count().")...".PHP_EOL;
$this->combinationsIterator=new CombinationsIterator($this->getThreadsAsArray(),6);
}
public function getSet() : Set {
return $this->threads;
}
public function getThreads() : Set {
return $this->threads;
}
/* not need if using Set class */
/*
Set:
The code took 4.5061111450195E-5 seconds to complete.
This Function:
The code took 0.0054061412811279 seconds to complete.
*/
public function deduplicateArray($array){
array_walk_recursive($array, function($v) use (&$r){$r[]=$v;});
return array_values(array_unique($r));
}
}
class CombinationsIterator implements Iterator
{
protected $c = null;
protected $s = null;
protected $n = 0;
protected $k = 0;
protected $pos = 0;
function __construct($s, $k) {
if(is_array($s)) {
$this->s = array_values($s);
$this->n = count($this->s);
} else {
$this->s = (string) $s;
$this->n = strlen($this->s);
}
$this->k = $k;
$this->rewind();
}
function key() {
return $this->pos;
}
function current() {
$r = array();
for($i = 0; $i < $this->k; $i++)
$r[] = $this->s[$this->c[$i]];
return is_array($this->s) ? $r : implode('', $r);
}
function next() {
if($this->_next())
$this->pos++;
else
$this->pos = -1;
}
function rewind() {
$this->c = range(0, $this->k);
$this->pos = 0;
}
function valid() {
return $this->pos >= 0;
}
protected function _next() {
$i = $this->k - 1;
while ($i >= 0 && $this->c[$i] == $this->n - $this->k + $i)
$i--;
if($i < 0)
return false;
$this->c[$i]++;
while($i++ < $this->k - 1)
$this->c[$i] = $this->c[$i - 1] + 1;
return true;
}
}
function humanReadableMemory($size)
{
$unit=array('b','kb','mb','gb','tb','pb');
return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];
}
$tickets = [
[1029],
[1029],
[1029],
[1029],
[1029],
[1029],
[1029],
[1029, 1049],
[1029, 1049],
[1029, 1049, 1080, 1112, 1125, 1188],
[1029, 1049, 1125],
[1029, 1049, 1188, 1278],
[1029, 1056, 1138, 1158, 1182, 1514, 1531],
[1029, 1071, 1076],
[1029, 1074, 1075, 1092, 1093, 1242, 1523, 1525],
[1029, 1094, 1125, 1138, 1158],
[1029, 1094, 1125, 1278],
[1029, 1094, 1182, 1221, 1242, 1505],
[1029, 1094, 1278, 1298],
[1029, 1094, 1298],
[1029, 1112, 1125, 1298, 1516],
[1029, 1112, 1125, 1505],
[1029, 1112, 1505],
[1029, 1125],
[1029, 1125],
[1029, 1125, 1138],
[1029, 1138, 1188, 1514, 1517],
[1029, 1138, 1242, 1317, 1505, 1525],
[1029, 1242],
[1029, 1242],
[1029, 1242, 1270, 1524],
[1029, 1242, 1370, 1505],
[1029, 1298],
[1029, 1298, 1505],
[1029, 1317],
[1029, 1505],
[1029, 1505],
[1029, 1505, 1525],
[1038, 1076, 1177, 1182],
[1045, 1048, 1097, 1100],
[1046, 1125, 1182, 1242, 1278],
[1049],
[1049],
[1049],
[1049],
[1049],
[1049],
[1049],
[1049],
[1049]
];
$po=new ProductionOptimizer($tickets);
$start = microtime(TRUE);
$end = microtime(TRUE);
echo "Current Memory Usage: ".humanReadableMemory(memory_get_usage()).PHP_EOL;
echo "Peak Memory Usage: ".humanReadableMemory(memory_get_peak_usage()).PHP_EOL;
echo "Starting Iterations and Combination Testing...".PHP_EOL;
$rankedOutput=[];
$start = microtime(TRUE);
for ($i=0;$i<3;$i++) {
$matchCountArray=[];$bestChoice=0;$bestChoiceId=-1;
foreach ($po->getCombinationsIterator() as $comboTest){
$combinationString=implode(",",$comboTest);
$matchCountArray[$combinationString]=0;
$comboTestSet=new Set($comboTest);
foreach ($tickets as $ticketIdx=>$ticketElements) {
$ticketElementsSet = new Set($ticketElements);
$testsArray[$combinationString]+=($comboTestSet->contains(...$ticketElements) ? 1 : 0);
}
if ($matchCountArray[$combinationString]>$bestChoice) {
$bestChoice = $matchCountArray[$combinationString];
$bestChoiceId=$combinationString;
} else {
//trying to save memory
unset($matchCountArray[$combinationString]);
}
}
$currentBestChoiceSet=new Set(explode(",",$bestChoiceId));
$currentUniverseSet=$po->getSet()->copy();
for($tmpJ=0;$tmpJ<$currentUniverseSet->count();$tmpJ++){
$testAgainstSet=$currentUniverseSet->get($tmpJ);
if ($currentBestChoiceSet->contains(...$testAgainstSet->toArray())){
$currentUniverseSet->remove($testAgainstSet);
}
}
$tickets = [];
foreach ($currentUniverseSet as $singleSet){
$tickets[]=$singleSet->toArray();
}
$po=new ProductionOptimizer($tickets);
$rankedOutput[$i]=["greatest_matching_sequence"=>$bestChoiceId, "coverage_count"=>$bestChoice];
}
echo "RankedOutput:".PHP_EOL;
var_dump($rankedOutput);
echo PHP_EOL;
$end = microtime(TRUE);
echo PHP_EOL."The code took " . ($end - $start) . " seconds to complete.".PHP_EOL;