学生现在基本上围绕着操场的中心漫游,看不出很大的区别。
我们现在让学生之间有联系:学生之间可以有讨厌或者喜欢的程度,用权值代表。
在本例中增加一个Field,也就是network.
sim.field.network.Network: 可以定义有向/无向、有权值/无、带/不带标签的联系。
任何的对象都可以作为节点,sim.field.network.Edge连接两个节点。
现在改变Students类,为它增加network:
package com.mason.learn;
import sim.engine.*;
import sim.util.*;
import sim.field.continuous.*;
import sim.field.network.*;
public class Students extends SimState {
private static final long serialVersionUID = 1L;
public Continuous2D yard = new Continuous2D(1.0, 100, 100);
public int numStudents = 50;
double forceToSchoolMultiplier = 0.01;
double randomMultiplier = 0.1;
public Network buddies = new Network(false);
public Students(long seed) {
super(seed);
}
public void start() {
super.start();
// clear the yard
yard.clear();
// clear the buddies
buddies.clear();
// add some students to the yard
for (int i = 0; i < numStudents; i++) {
Student student = new Student();
yard.setObjectLocation(student, new Double2D(yard.getWidth() * 0.5
+ random.nextDouble() - 0.5, yard.getHeight() * 0.5
+ random.nextDouble() - 0.5));
buddies.addNode(student);
schedule.scheduleRepeating(student);
}
// define like/dislike relationships
// Bag is faster than ArrayList, and the result of getAllNodes() is
// read-only.
Bag students = buddies.getAllNodes();
for (int i = 0; i < students.size(); i++) {
Object student = students.get(i);
// who does he like?
Object studentB = null;
do
studentB = students.get(random.nextInt(students.numObjs));
while (student == studentB);
double buddiness = random.nextDouble();
buddies.addEdge(student, studentB, new Double(buddiness));
// who does he dislike?
do
studentB = students.get(random.nextInt(students.numObjs));
while (student == studentB);
buddiness = random.nextDouble();
buddies.addEdge(student, studentB, new Double(-buddiness));
}
}
public static void main(String[] args) {
doLoop(Students.class, args);
System.exit(0);
}
}
现在仿真中的network已经有了权值,现在我们改变Student让学生依据喜恶程度来进行移动。
package com.mason.learn;
import sim.engine.*;
import sim.field.continuous.*;
import sim.util.*;
import sim.field.network.*;
public class Student implements Steppable {
private static final long serialVersionUID = 1L;
public static final double MAX_FORCE = 3.0;
public void step(SimState state) {
Students students = (Students) state;
Continuous2D yard = students.yard;
Double2D me = students.yard.getObjectLocation(this);
MutableDouble2D sumForces = new MutableDouble2D();
// Go through my buddies and determine how much I want to be near them
MutableDouble2D forceVector = new MutableDouble2D();
Bag out = students.buddies.getEdges(this, null);
int len = out.size();
for (int buddy = 0; buddy < len; buddy++) {
Edge e = (Edge) (out.get(buddy));
double buddiness = ((Double) (e.info)).doubleValue();
// I could be in the to() end or the from() end. getOtherNode is a
// cute function
// which grabs the guy at the opposite end from me.
Double2D him = students.yard
.getObjectLocation(e.getOtherNode(this));
if (buddiness >= 0) // the further I am from him the more I want to
// go to him
{
forceVector.setTo((him.x - me.x) * buddiness, (him.y - me.y)
* buddiness);
if (forceVector.length() > MAX_FORCE) // I’m far enough away
forceVector.resize(MAX_FORCE);
} else // the nearer I am to him the more I want to get away from
// him, up to a limit
{
forceVector.setTo((him.x - me.x) * buddiness, (him.y - me.y)
* buddiness);
if (forceVector.length() > MAX_FORCE) // I’m far enough away
forceVector.resize(0.0);
else if (forceVector.length() > 0)
forceVector.resize(MAX_FORCE - forceVector.length()); // invert
// the
// distance
}
sumForces.addIn(forceVector);
}
// add in a vector to the "teacher" -- the center of the yard, so we
// don’t go too far away
sumForces.addIn(new Double2D((yard.width * 0.5 - me.x)
* students.forceToSchoolMultiplier, (yard.height * 0.5 - me.y)
* students.forceToSchoolMultiplier));
// add a bit of randomness
sumForces.addIn(new Double2D(students.randomMultiplier
* (students.random.nextDouble() * 1.0 - 0.5),
students.randomMultiplier
* (students.random.nextDouble() * 1.0 - 0.5)));
sumForces.addIn(me);
students.yard.setObjectLocation(this, new Double2D(sumForces));
}
}
运行结果:
如果想要让联系显示出来,可以增加network portrayal。
NetworkPortrayal2D buddiesPortrayal = new NetworkPortrayal2D();
在setupPortrayals里面增加:
buddiesPortrayal.setField( new SpatialNetwork2D( students.yard, students.buddies ) );
buddiesPortrayal.setPortrayalForAll(new SimpleEdgePortrayal2D());
display.attach( buddiesPortrayal, "Buddies" );
运行结果如图: