Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 以给定的最小权重最大化子图的数目_Algorithm_Theory_Graph Theory_Weighted - Fatal编程技术网

Algorithm 以给定的最小权重最大化子图的数目

Algorithm 以给定的最小权重最大化子图的数目,algorithm,theory,graph-theory,weighted,Algorithm,Theory,Graph Theory,Weighted,我有一个无向平面图,其中每个节点都有一个权重。我希望将图拆分为尽可能多的连通不相交子图(编辑:或达到子图的最小平均权重),条件是每个子图必须达到固定的最小权重(即其节点的权重之和)。仅包含单个节点的子图也可以(如果节点的权重大于固定的最小值) 到目前为止,我发现了一个启发: create a subgraph out of every node while there is an underweight subgraph: select the subgraph S with the low

我有一个无向平面图,其中每个节点都有一个权重。我希望将图拆分为尽可能多的连通不相交子图(编辑:或达到子图的最小平均权重),条件是每个子图必须达到固定的最小权重(即其节点的权重之和)。仅包含单个节点的子图也可以(如果节点的权重大于固定的最小值)

到目前为止,我发现了一个启发:

create a subgraph out of every node
while there is an underweight subgraph:
  select the subgraph S with the lowest weight
  find a subgraph N that has the lowest weight among the neighbouring subgraphs of S
  merge S to N
显然,这不是最优的。有谁有更好的解决办法吗?(也许我只是无知,这不是一个复杂的问题,但我从未学习过图论…)

编辑(更多背景详细信息):此图中的节点是要提供统计数据的低规模管理单元。但是,这些单位需要有一定的最低人口规模,以避免与个人数据立法发生冲突。我的目标是创建聚合,以便在过程中尽可能少地丢失信息。邻域关系用作图形边,因为生成的单元必须是连续的

集合中的大多数单元(节点)远高于最小阈值。如示例所示,约5-10%的尺寸在不同的阈值以下(最小尺寸50):


这是一个NP难优化问题。例如,可以很容易地将平面减少到这一点(平面度特性不会引起问题)。因此,一个计算最优解的算法(你似乎在评论中要求一个最优解)不太可能适用于“成千上万的节点”

如果你实际上并不需要一个最优的解决方案,而是一个好的解决方案,我会使用局部优化方法,比如禁忌搜索或模拟退火


因为子图的平均权重就是总图的权重除以子图的数量,唯一重要的是找到你能达到的最大子图数量。猜测这个数字,N,形成一个初始划分为N个子图,然后,例如,使用局部移动(1)将一个节点从一个子图移动到另一个子图,以及(2)在两个相邻子图之间交换两个节点,以搜索每个子图都具有所需最小权重的可接受解决方案。如果您根本找不到可接受的解决方案,请减少N(例如减少1),然后重新启动,直到找到解决方案。

该问题是NP难问题,然后我将重点介绍指数解决方案。这个解决方案有很多改进点,我将重点介绍一些

其整体思想是:顶点的每个分区都由一些边连接,如果您尝试使用所有可能的边集,则可以确保生成正确的图分区。您可以通过计算每个分区的集合数(最佳条件)找到最佳情况

在以前的方法中,您没有扩展搜索的域。对于该解决方案,使用了以下内容: -不相交集:划分表示 -幂集:用于查找所有可能的边集

public Partition Solve(Graph g, int min)
{
    int max = 0;
    Partition best;

    // Find all the possible partitions for Edges
    foreach(var S in PowerSet(g.Edges))
    {
        // Build the Vertexes partition
        var partition =  BuildPartition(S);

        // Test the min condition foreach component
        if (IsInvalid(partition, min))
            continue;

        // Continue if we already have something better
        if (max >= partition.Length)
            continue;

        // Update
        max = partition.Length;
        best = partition;
    }

    return best;
}

public Partition BuildPartition(Graph g, IEnumerable<Edge> edges)
{
    // Initially Every Vertex in alone in his partition
    var partition = new DisjointSet(g.Vertexes);

    foreach (var edge in edges)
    {
        // If the Vertexes of this edge are already in the same partition DO NOTHING
        if (partition.Find(edge.V1) == partition.Find(edge.V2))
            continue;

        // Join both subsets
        partition.Union(edge.V1, edge.V2);
    }

    return parition;
}

public bool IsInvalid(Partition p, int min)
{
    return p.Sets.Any(t => t.Sum(v => v.Weight) < min);
}
公共分区求解(图g,int-min)
{
int max=0;
分区最好;
//查找所有可能的边分区
foreach(功率集中的var S(g.Edges))
{
//构建顶点分区
var分区=构建分区;
//测试每个组件的最小条件
if(IsInvalid(分区,最小值))
继续;
//如果我们已经有更好的东西,请继续
如果(最大>=分区长度)
继续;
//更新
max=分区长度;
最佳=分区;
}
回报最好;
}
公共分区BuildPartition(图g,IEnumerable边)
{
//最初,每个顶点在其分区中都是单独的
var partition=新的不相交集(g.顶点);
foreach(边中的变量边)
{
//如果此边的顶点已在同一分区中,则不执行任何操作
if(partition.Find(edge.V1)=partition.Find(edge.V2))
继续;
//联接两个子集
并集(edge.V1,edge.V2);
}
返回分区;
}
公共布尔IsInvalid(分区p,最小整数)
{
返回p.set.Any(t=>t.Sum(v=>v.Weight)
您可以在以下方面改进解决方案: -将并行性添加到电源集和IsInvalid条件 -找到生成有效边集的更好方法 -对于权重大于最小值的顶点(始终位于单独的子图中)有一些起始情况

该算法的阶数由幂集给出。 -幂集:在这种情况下,对于N个顶点图,最坏的情况是3N-6条边,然后是O(2^N)。-构建分区:V+E*LogV然后是O(NLogN) -IsInvalid:O(V)

最后的解是O(2^N*N*LogN) 使用最后一个公式计算操作数


希望这有帮助

实例的细节改变了一切

如果顶点本身超过阈值,则称其为重顶点。有两个重顶点的子图是没有意义的,因为我们可以把它一分为二。因此,最优解中的子图数与不含重顶点的子图数相加


因此,我们可以删除沉重的顶点,集中精力从剩下的部分中生成尽可能多的有效子图。根据地图判断,剩下的将由许多连接的组件组成,每个组件只有少数几个顶点。有效的子图必须是连通的,因此这些组件可以独立求解。在小的情况下,可以(例如)枚举所有有效的子图,然后运行以找到最大基数填充。

如果没有平面性条件,这个问题肯定是强NP难的。我不希望有一种简单的方法来利用平面性,除了可能是一个动态程序,它的运行是指数级的√n(与n相反,使用平面图具有