1

我想实现这样的逻辑:

while (count loading_docks with [status == "free"] > 0 and trucks with [status == "free" and type == "20'" and capacity < 1000] > 0) {
   match a truck satisfying above 3 condidtions to a free dock for unloading cargo;
}

可以看出,查询需要在while循环中重复调用和更新,第二个查询由3个条件组成(这对于AndQuery()方法来说并不容易)。

这在 Netlogo 中很容易实现。什么是适合和更短的方式来实现?

更新 - 最初的尝试

    public void match_dock() {


        for (Truck t: this.getTruck_queue()) {
            if (this.Count_freeDock() > 0) {
                Query<Object> fit_dock = new AndQuery(
                                            new PropertyEquals(context, "status", 1), 
                                            new PropertyGreaterThanEquals(context, "max_veh", t.getTruck_type()));
                double min = 10000; 
                Dock match = null;
                for(Object o: fit_dock.query()) {
                    if (((Dock)o).getMax_veh() < min) {
                        match = (Dock)o;
                    }
                }
                match.setStatus(2);
                match.getServe_list().add(t.getReq_id());
                t.setServe_dock(match.getId());
//              if (t.getServe_dock() != -1) {
//                  this.getTruck_queue().remove(t);
//              }
            }
        }
    }



    public int Count_freeDock() {
        List<Dock> free_list = new ArrayList<Dock>();
        Query<Object> free_dock = new PropertyEquals<Object>(context, "status", 1);
        for (Object o : free_dock.query()) {
            if (o instanceof Dock) {
                free_list.add((Dock)o);
            }
        }
        return free_list.size();
    } 

需要解决三个问题:

1)特定代理集的查询必须考虑三个条件;AndQuery 只包含两个条件。是否有允许同时考虑两个以上条件的查询方法?

当前问题:

Query<Object> pre_fit = new AndQuery(
                            new PropertyEquals(context, "status", 1), 
                            new PropertyGreaterThanEquals(context, "max_veh", t.getTruck_type()));

Query<Object> fit_dock = new AndQuery(pre_fit, new PropertyEquals(context, "ops_type", 3));

两个条件的初始组合工作正常并且查询速度很快。但是,当我添加第三个条件“ops_type”时,查询速度变得非常慢。背后的原因是什么?或者这是构成三个条件的正确方法?

2)除了编写自定义计数函数(如示例所示)之外,是否有更简单的方法来查询特定代理集的大小(计数)?

3)将查询的代理集添加(或复制)到相关列表操作的列表中的最短方法是什么?

更新整个代码块:

    public void match_dock() {

        Iterator<Truck> truck_list = this.getTruck_queue().iterator();
        while(truck_list.hasNext() && this.Count_freeDock() > 0) {
            Truck t = truck_list.next();
//              Query<Object> pre_fit = new AndQuery(
//                                          new PropertyEquals(context, "status", 1), 
//                                          new PropertyGreaterThanEquals(context, "max_veh", t.getTruck_type()));
//              Query<Object> ops_fit = new OrQuery<>(
//                                          new PropertyEquals(context, "ops_type", 3), 
//                                          new PropertyEquals(context, "ops_type", this.getOps_type(t.getOps_type())));
//              Query<Object> fit_dock = new AndQuery(pre_fit, new PropertyEquals(context, "ops_type", 3));
//              Query<Object> fit_dock = new AndQuery(pre_fit, ops_fit);

                Query<Object> pre_fit = new AndQuery(
                        new PropertyEquals(context, "status", 1), 
                        new PropertyGreaterThanEquals(context, "max_veh", t.getTruck_type()));

                Query<Object> q = new PropertyEquals(context, "ops_type", 3);


                double min = 10000; 
                Dock match = null;
                for (Object o : q.query(pre_fit.query())) {
//              for(Object o: fit_dock.query()) {
                    if (((Dock)o).getMax_veh() < min) {
                        match = (Dock)o;
                    }
                }
                try {
                    match.setStatus(2);
                    match.getServe_list().add(t.getReq_id());
                    t.setServe_dock(match.getId());
                    if (t.getServe_dock() != -1) {
                        System.out.println("truck id " + t.getReq_id() + "serve dock: " + t.getServe_dock());
                        t.setIndock_tm(this.getTick());
                        truck_list.remove();
                    }
                }
                catch (Exception e){
//                  System.out.println("No fit dock found");
                }           
        }
    }



    public int Count_freeDock() {

        List<Dock> free_list = new ArrayList<Dock>();
        Query<Object> free_dock = new PropertyEquals<Object>(context, "status", 1);
        for (Object o : free_dock.query()) {
            if (o instanceof Dock) {
                free_list.add((Dock)o);
            }
        }
//      System.out.println("free trucks: " + free_list.size());
        return free_list.size();
    }

5/5 更新

为了更好地检测,我已将查询移到 while 循环之外。我发现速度慢主要是由于使用了“PropertyGreaterThanEquals”。无论查询的字段是 int 还是 double。

  1. 当您使用“PropertyGreaterThanEquals”查询时,无论查询的字段是 int 还是 double,查询都会运行得很慢。但是,它返回正确的结果。
  2. 当您使用“PropertyEquals”查询时,无论查询的字段是 int 还是 double,查询都会在不到一秒的时间内运行。但是,它返回的结果不正确,因为它需要考虑 ">="。

    public void match_dock() {
        System.out.println("current tick is: " + this.getTick());
        Iterator<Truck> truck_list = this.getTruck_queue().iterator();
    
        Query<Object> pre_fit = new AndQuery(
                new PropertyEquals(context, "status", 1), 
                new PropertyGreaterThanEquals(context, "max_veh", 30));
                //new PropertyEquals(context, "max_veh", 30));
    
        Query<Object> q = new PropertyEquals(context, "hv_spd", 240);
    
    
        for (Object o : q.query(pre_fit.query())) {
            if (o instanceof Dock) {
            System.out.println("this object is: " + ((Dock)o).getId());
            }
        }
    

    }

4

1 回答 1

2

对于 1,您可以尝试像这样链接查询:

Query<Object> pre_fit = new AndQuery(
                        new PropertyEquals(context, "status", 1), 
                        new PropertyGreaterThanEquals(context, "max_veh", t.getTruck_type()));

Query<Object> q = new PropertyEquals(context, "ops_type", 3);
for (Object o : q.query(pre_fit.query())) { ...

我认为这可能比嵌入 AndQuery 更快,但我不完全确定。

对于 2,我认为 Query 产生的一些 Iterables 实际上是 Java Sets。您可以尝试转换为其中之一,然后调用 size()。如果它不是一个集合,那么您实际上必须进行迭代,因为查询过滤条件实际上是作为迭代的一部分应用的。

对于 3,我认为有一些 Java 方法可以做到这一点。new ArrayList(Iterable),以及 Collections 中的一些方法。

于 2020-05-04T13:25:17.737 回答