简体   繁体   English

生成有向图而无需在Java中返回边

[英]Generate directed graph without returning edges in java

I'm trying to make a directed graph generator to use it in LJF algorithm. 我正在尝试制作一个有向图生成器以在LJF算法中使用它。 The thing is that I have no idea how to avoid the returning edges (eg. if I got 1 -> 2 I don't want to have 2 -> 1). 问题是我不知道如何避免返回边缘(例如,如果我得到1-> 2,我不想拥有2-> 1)。 I only made a statement in if to avoid edges to the same node (eg. 1 -> 1). 我只是在声明if避免边缘到同一节点(例如1-> 1)。 Another problem is that my generator sometimes leaves some nodes alone without any edges but I need at least one edge per node. 另一个问题是我的生成器有时会留下一些没有任何边缘的节点,但是每个节点至少需要一个边缘。 What I want to reach is something similar to BST but there is no rule to have max 2 edges, it can be more. 我想达到的效果与BST类似,但是没有最大2条边的规则,它可以更多。

public class Graph {

private final int maxT = 3;
private final int chance = 30;  //chance to connect edges
Map<Task, List<Transmission>> tasks = new HashMap<Task, List<Transmission>>();

public Graph() {

    Random r = new Random();

    int range = r.nextInt(maxT) + 3; // number of nodes
    for(int i = 0; i<range; i++){
        List<Transmission> trans = new ArrayList<Transmission>();
        tasks.put(new Task(i), trans);
    }
    System.out.println("Number of tasks: " + tasks.size());

    for(Task key1 : tasks.keySet()){
        for(Task key2 : tasks.keySet()){
            if(key1 != key2 && r.nextInt(100) < chance)
                tasks.get(key1).add(new Transmission(key1,key2));
        }
    }

}

public void printGraph(){
    System.out.println("Generated graph:\n");
    for(Task key : tasks.keySet()){
        System.out.println(key.getId());
        for(Transmission ts : tasks.get(key)){
            System.out.println("\t" + ts.getT1().getId() + " -> " + ts.getT2().getId());
        }
    }       
}
}

====EDIT==== ====编辑====

After adding order to iterations: 在为迭代添加顺序之后:

        List<Task> keys = new ArrayList<Task>(tasks.keySet());
    for(int i = 0; i < keys.size() - 1; i++){
        for(int j = i + 1; j < keys.size(); j++){
            tasks.get(i).add(new Transmission(keys.get(i), keys.get(j)));}
    }

I got java.lang.NullPointerException exception on this line: 我在此行上收到java.lang.NullPointerException异常:

tasks.get(i).add(new Transmission(keys.get(i), keys.get(j)));}

I see that my newly added list is full of null elements, I attach then Task class: 我看到新添加的列表中充满了null元素,然后附加Task类:

import java.util.Random;

public class Task extends Node{

Random r = new Random();
int tstart; // start time
int tend; // end time
int size; 
int deadline; 
public Task(int id) {
    super(id);
    tstart = r.nextInt(5);
    tend = r.nextInt(5);
    size = r.nextInt(10);
    deadline = r.nextInt(8);
}

public int getDeadline() {
    return deadline;
}
public int getTstart() {
    return tstart;
}
public int getTend() {
    return tend;
}
public int getSize() {
    return size;
}

} }

===EDIT==== ===编辑====

Now I got the problem that my generator gives me cycles which I don't want to have. 现在我遇到了一个问题,就是我的发电机给了我不想拥有的周期。 So, I added again chance to make a transmission but sometimes I got free nodes or to seperate graphs. 因此,我再次增加了进行传输的机会,但有时我得到了自由节点或分离了图表。

List<Task> keys = new ArrayList<Task>(tasks.keySet());
    for(int i = 0; i < keys.size() - 1; i++){
        for(int j = i + 1; j < keys.size(); j++){
            if(r.nextInt(100) < chance && tasks.get(keys.get(i)).isEmpty())
                tasks.get(keys.get(i)).add(new Transmission(keys.get(i), keys.get(j)));}
    }

It is simple to avoid (2 -> 1) edes if you have (1 -> 2). 如果您拥有(1-> 2),则避免(2-> 1)edes很简单。 For each edge (x -> y) assume that x < y. 对于每个边(x-> y)假设x <y。

Add ordering to iterations: 为迭代添加顺序:

List<T> keys = new ArrayList<>(map.keySet());
for (int i = 0; i < keys.size() - 1; i++) {
    for (int j = i + 1; j < keys.size(); j++) {
        make new Transmission(keys.get(i), keys.get(j));
    }
}

To solve the complete problem you need an alogorithm like this: 要解决完整的问题,您需要这样的算法:

  1. N - set of non visited vertexes. N未访问的顶点集。 All vertexes at the beginning. 开头的所有顶点。
  2. V - set of visited vertexes. V访问的顶点集。 Empty at the beginning. 一开始是空的。
  3. Take random vertex x from N . N取随机顶点x
  4. Add edge(s) (random vertex from V -> x ) from second iteration. 从第二次迭代中添加边(从V > x随机顶点)。
  5. Add x to V and remove x from N . x加到V并从N删除x
  6. Continue to step 3 or quit. 继续执行步骤3或退出。

Your graph will be oriented cycles-free. 您的图形将无周期定向。

Instead of a list of Transmission s for each Task , you could use a map, indexed by the destination node. 您可以使用按目标节点索引的映射来代替每个TaskTransmission列表。 Then, you can easily perform a check, whether a backwards-edge already exists. 然后,您可以轻松地执行检查,是否已经存在向后边缘。 Furthermore, you can add a condition to always generate an edge when the node has none: 此外,您可以添加条件以在节点没有节点时始终生成边:

public class Graph {

    private final int maxT = 3;
    private final int chance = 30;  //chance to connect edges
    Map<Task, Map<Task, Transmission>> tasks = new HashMap<>();

    public Graph() {

        Random r = new Random();

        int range = r.nextInt(maxT) + 3; // number of nodes
        for(int i = 0; i<range; i++){
            Map<Task, Transmission> trans = new HashMap<>();
            tasks.put(new Task(i), trans);
        }
        System.out.println("Number of tasks: " + tasks.size());

        for(Task key1 : tasks.keySet()){
            for(Task key2 : tasks.keySet()){
                if(key1 != key2
                        && !tasks.get(key2).containsKey(key1) // Don't generate an edge, if there already is a reverse edge
                        && (tasks.get(key1).isEmpty() // Always generate an edge, if there is none
                            || r.nextInt(100) < chance))
                {
                    tasks.get(key1).put(key2, new Transmission(key1,key2));
                }
            }
        }

    }

    public void printGraph(){
        System.out.println("Generated graph:\n");
        for(Task key : tasks.keySet()){
            System.out.println(key.getId());
            for(Transmission ts : tasks.get(key).values()){
                System.out.println("\t" + ts.getT1().getId() + " -> " + ts.getT2().getId());
            }
        }       
    }
}

EDIT 编辑

New solution trying to incorporate all requirements discussed in the various comments: 试图合并各种注释中讨论的所有要求的新解决方案:

public Graph() {

    Random r = new Random();

    int range = r.nextInt(maxT) + 3; // number of nodes
    for(int i = 0; i<range; i++){
        List<Transmission> trans = new ArrayList<Transmission>();
        tasks.put(new Task(i), trans);
    }
    System.out.println("Number of tasks: " + tasks.size());

    List<Task> keys = new ArrayList<Task>(tasks.keySet());
    for(int i = 0; i < keys.size() - 1; i++) {
        Task task1 = keys.get(i);
        List<Transmission> task1Transmissions = tasks.get(task1);
        task1Transmissions.add(new Transmission(task1, keys.get(i + 1)));
        for(int j = i + 2; j < keys.size(); j++) {
            if(r.nextInt(100) < chance)
                task1Transmissions.add(new Transmission(task1, keys.get(j)));
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM