Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.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
Swift 将集合A中的所有元素连接到集合B中的至少一个元素的最低成本解决方案_Swift_Algorithm_Graph Theory - Fatal编程技术网

Swift 将集合A中的所有元素连接到集合B中的至少一个元素的最低成本解决方案

Swift 将集合A中的所有元素连接到集合B中的至少一个元素的最低成本解决方案,swift,algorithm,graph-theory,Swift,Algorithm,Graph Theory,我需要找到最短的路径集,将集合A的每个元素与集合B的至少一个元素连接起来。允许在A或B中重复(但不能同时重复),并且任何元素都不能保持不连接。大概是这样的: 我将元素表示为整数,因此连接的“成本”只是差值的绝对值。我还有一个穿越路径的成本,所以如果设置a=[60,64]和设置B=[63,67],那么(60->67)会产生额外的成本。两个集合中可以有任意数量的元素 我已经计算了过渡和成本表(距离和交叉点),但我找不到找到最低成本解决方案的算法。我总是以太多的连接(即A和B中的重复)或忽略元素的贪

我需要找到最短的路径集,将集合A的每个元素与集合B的至少一个元素连接起来。允许在A或B中重复(但不能同时重复),并且任何元素都不能保持不连接。大概是这样的:

我将元素表示为整数,因此连接的“成本”只是差值的绝对值。我还有一个穿越路径的成本,所以如果设置a=[60,64]和设置B=[63,67],那么(60->67)会产生额外的成本。两个集合中可以有任意数量的元素

我已经计算了过渡和成本表(距离和交叉点),但我找不到找到最低成本解决方案的算法。我总是以太多的连接(即A和B中的重复)或忽略元素的贪婪解决方案(例如,当A和B不重叠时)结束。我还没能在网上找到这类问题的确切例子,所以我希望这里的人能够帮助我,或者至少为我指明正确的方向。我不是一个图论家(显然!),我是用Swift写的,所以用Swift(或伪代码)编写代码示例将非常受欢迎

更新:@Daniel提供的解决方案几乎可以正常工作,但偶尔会添加不必要的副本。我认为这可能与priorityQueue的排序有关——重复项总是包含相同成本的相同元素。我的第一个想法是在成本中添加某种“位置编码”(是的,Transformer是这样说的),这样成本就可以被它们的位置抵消(当然,这并不能保证唯一的成本)。我想我会在这里发布我的Swift版本,以防有人有任何想法:

public static func voiceLeading(from chA: [Int], to chB: [Int]) -> Set<[Int]> {
        var result: Set<[Int]> = Set()
        let im = intervalMatrix(chA, chB: chB)
        if im.count == 0 { return [[0]] }
        let vc = voiceCrossingCostsMatrix(chA, chB: chB, cost: 4)
        // NOTE: cm contains the weights
        let cm = VectorUtils.absoluteAddMatrix(im, toMatrix: vc)

        var A_links: [Int:Int] = [:]
        var B_links: [Int:Int] = [:]
        var priorityQueue: [Entry] = []
        for (i, a) in chA.enumerated() {
            for (j, b) in chB.enumerated() {
                priorityQueue.append(Entry(a: a, b: b, cost: cm[i][j]))
                if A_links[a] != nil {
                    A_links[a]! += 1
                } else {
                    A_links[a] = 1
                }
                if B_links[b] != nil {
                    B_links[b]! += 1
                } else {
                    B_links[b] = 1
                }
            }
        }
        priorityQueue.sort { $0.cost > $1.cost }
        while priorityQueue.count > 0 {
            let entry = priorityQueue[0]
            if A_links[entry.a]! > 1 && B_links[entry.b]! > 1 {
                A_links[entry.a]! -= 1
                B_links[entry.b]! -= 1
            } else {
                result.insert([entry.a, (entry.b - entry.a)])
            }
            priorityQueue.remove(at: 0)
        }
        
        return result
    }
publicstaticfunc语音引导(从chA:[Int]到chB:[Int])->Set{
变量结果:Set=Set()
设im=间隔矩阵(chA,chB:chB)
如果im.count==0{返回[[0]]}
设vc=voiceCrossingCostsMatrix(chA,chB:chB,成本:4)
//注:cm包含重量
设cm=VectorUtils.absoluteAddMatrix(im,toMatrix:vc)
变量A_链接:[Int:Int]=[:]
变量B_链接:[Int:Int]=[:]
var priorityQueue:[条目]=[]
对于chA.enumerated()中的(i,a){
对于chB.enumerated()中的(j,b){
追加(条目(a:a,b:b,成本:cm[i][j]))
如果A_链接[A]!=nil{
A_链接[A]!+=1
}否则{
A_链接[A]=1
}
如果B_链接[B]!=nil{
B_链接[B]!+=1
}否则{
B_链接[B]=1
}
}
}
priorityQueue.sort{$0.cost>$1.cost}
而priorityQueue.count>0{
let entry=priorityQueue[0]
如果A_链接[entry.A]!>1和&B_链接[entry.B]!>1{
A_链接[entry.A]!-=1
B_链接[entry.B]!-=1
}否则{
结果.插入([条目a,(条目b-条目a)])
}
priorityQueue.remove(位于:0)
}
返回结果
}
当然,由于复制品的分数相同,所以删除多余的部分应该不会有问题,但感觉有点不太对劲

更新2:稍微少一些黑客(但还是有点!);由于要求我的结果的基数应等于
max(|A |,|B |)
,因此当我达到目标基数时,我实际上可以停止向
结果添加条目。看起来还好

更新3:重新提出这个老问题,我最近遇到了一些问题,因为上面的算法不能满足我的要求
|S |==max(| A |,| B |)
(其中S是一组配对)。如果有人知道一个简单的方法来确保这一点,将不胜感激。(很明显,我会挑出可能的变化。)

我认为这个问题是“最小加权二部匹配”(虽然搜索“最大加权二部匹配”也会相关,但恰恰相反)

我认为这个问题是“最小加权二部匹配”(虽然搜索“最大加权二部匹配”也很重要,它正好相反)

这是一项简单的任务:

  • 将图形的所有边添加到
    优先级\u队列
    ,其中最大优先级是权重最大的边

  • 查看
    priority\u队列中的每条边
    e=(u,v,w)
    ,其中
    u
    A中,
    v
    B中,
    w
    是权重

  • 如果从图形中删除
    e
    不会使
    u
    v
    孤立,请将其删除

  • 否则,
    e
    就是答案的一部分

这对于您的情况应该足够了:

#include <bits/stdc++.h>
using namespace std;

struct edge {
    int u, v, w;
    edge(){}
    edge(int up, int vp, int wp){u = up; v = vp; w = wp;}
    void print(){ cout<<"("<<u<<", "<<v<<")"<<endl; }
    bool operator<(const edge& rhs) const {return w < rhs.w;}
};

vector<edge> E;             //edge set
priority_queue<edge> pq;
vector<edge> ans;
int grade[5] = {3, 3, 2, 2, 2};

int main(){

    E.push_back(edge(0, 2, 1)); E.push_back(edge(0, 3, 1)); E.push_back(edge(0, 4, 4));
    E.push_back(edge(1, 2, 5)); E.push_back(edge(1, 3, 2)); E.push_back(edge(1, 4, 0));
    for(int i = 0; i < E.size(); i++) pq.push(E[i]);

    while(!pq.empty()){
        edge e = pq.top();
        if(grade[e.u] > 1 && grade[e.v] > 1){
            grade[e.u]--; grade[e.v]--;
        }
        else ans.push_back(e);
        pq.pop();
    }

    for(int i = 0; i < ans.size(); i++) ans[i].print();

    return 0;
}
#包括
使用名称空间std;
结构边{
国际u,v,w;
边(){}
边(int-up,int-vp,int-wp){u=up;v=vp;w=wp;}
void print(){cout这是一项简单的任务:

  • 将图形的所有边添加到
    优先级\u队列
    ,其中最大优先级是权重最大的边

  • 查看
    priority\u队列中的每条边
    e=(u,v,w)
    ,其中
    u
    A中,
    v
    B中,
    w
    是权重

  • 如果从图形中删除
    e
    不会使
    u
    v
    孤立,请将其删除

  • 否则,
    e
    就是答案的一部分

这对于您的情况应该足够了:

#include <bits/stdc++.h>
using namespace std;

struct edge {
    int u, v, w;
    edge(){}
    edge(int up, int vp, int wp){u = up; v = vp; w = wp;}
    void print(){ cout<<"("<<u<<", "<<v<<")"<<endl; }
    bool operator<(const edge& rhs) const {return w < rhs.w;}
};

vector<edge> E;             //edge set
priority_queue<edge> pq;
vector<edge> ans;
int grade[5] = {3, 3, 2, 2, 2};

int main(){

    E.push_back(edge(0, 2, 1)); E.push_back(edge(0, 3, 1)); E.push_back(edge(0, 4, 4));
    E.push_back(edge(1, 2, 5)); E.push_back(edge(1, 3, 2)); E.push_back(edge(1, 4, 0));
    for(int i = 0; i < E.size(); i++) pq.push(E[i]);

    while(!pq.empty()){
        edge e = pq.top();
        if(grade[e.u] > 1 && grade[e.v] > 1){
            grade[e.u]--; grade[e.v]--;
        }
        else ans.push_back(e);
        pq.pop();
    }

    for(int i = 0; i < ans.size(); i++) ans[i].print();

    return 0;
}
#包括
使用名称空间std;
结构边{
国际u,v,w;
边(){}
边(int-up,int-vp,int-wp){u=up;v=vp;w=wp;}

作废打印(){coutcomputerscience.stackexchange.com