I want to achieve a logic like this:
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;
}
as can be seen, the query needs to be repetively called and updated in the while loop, and the second query is composed of 3 conditions (Which is not easy with AndQuery() method).
This is very easy to implement in Netlogo. What is the suitable and shorter way to achieve in repast?
UPDATE - the initial attempt
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();
}
There are three issues to fix:
1) The query of a particular agent set has to consider three conditions; AndQuery only composes two conditions. is there a Query method which allows more than two conditions to be considered at the same time?
current problem:
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));
The initial composition of two conditions works fine and queries fast. However, when I add the third condition "ops_type", the query speed becomes hugely slow. What's the reason behind? Or is this a correct way to compose three conditions?
2) Is there simpler way to query the size (count) of a particular agent set, other than writing a custom count function (as shown in example)?
3) what is the shortest way to add(or copy) the queried agent set into a list for related list operations?
update entire code block:
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();
}
UPDATE on 5/5
I have moved the query outside the while loop for better detection. I found the slow speed could be largely due to the use of "PropertyGreaterThanEquals". regardless whether the queried field is int or double.
- when you query using "PropertyGreaterThanEquals", the query runs very slow regardless wether the queried field is int or double. However, it returns correct result.
when you query using "PropertyEquals", the query runs in less than one second regardless wether the queried field is int or double. however, it returns result which is not correct since it needs to consider ">=".
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()); } }
}