The main data structure for this week's project was Singly Linked-List, which was implemented during the lab. The concept of the project was very similar with project 3, Game of Life. The difference was that we used linked-list, instead of 2D-grid array, to store the agents (or cells) and display them through GUI. Another concept we implemented more explicitly in this project was "polymorphism". Based on Agent class, we created additional child classes such as SocialAgent and CategorizedSocialAgent, which store information about x and y coordinates. Different types of agents have different updateState() methods as well, which show different results on the main window. The differences will be discussed below. Simulation classes simply put other classes together and simulate the agents through java Swings package.
My Agent class is not abstract. Therefore, its child classes did not have to implement abstract methods.
One thing to note is that updateState() and draw() methods in Agent class are blank. The reason is that they are implemented in its child classes, differently according to the type of agent.
draw() method draws an agent with light grey if it moved, or with dark grey if it did not.
One thing to note is that I added getMoved() and setMoved() methods in order to access private instance variable moved in SocialAgent's child classes.
getNeighbors() method uses Math package's square root and power methods to calculate the distance between an agent and its neighbors.
Below is the image of running LandscapeDisplay.java
First of all, I decided to not include an agent in the neighbors list if the agent is exactly at the location passed in as x0, y0. In order to do so, I added a conditional statement to Landscape class's getNeighbors() method.
updateState() method first loops through the list of neighbors and calculates how many there are. If there are more than 3 neighbors, then the Agent is likely not to move. Otherwise, it moves until it finds enough neighbors.
updateAgents() method creates an randomized array-list using toShuffledList() and then uses for-each loop to call each Agent's updateState() method.
The attachment is my animation of SocialAgentSimulation; radius for updateState() method is 20, which is default.
When running SocialAgentSimulation.java, user needs to type four command line arguments: 1) width of landscape, 2) height of landscape, 3) number of agents to draw, 4) the radius for updateState() method. The 4th argument is my extension, which will be explained below.
Type in capitalized characters for the radius, i.e. DEFAULT, SMALL, MEDIUM, LARGE. As the size of radius grows, agents will stop moving faster.
For SocialAgents, DEFAULT = 20, SMALL = 5, MEDIUM = 40, and LARGE = 80.
updateState() method in this class is quite different from that in SocialAgent class. The agents move in a bigger range[-10, 10] and drawn with different colors according to its category.
Category 1: If moved, drawn with LightRed. If not, drawn with DarkRed.
Category 2: If moved, drawn with LightBlue. If not, drawn with DarkBlue.
I customized the colors as well, which are static variables of CategorizedSocialAgent class.
Below are the screenshots of running CategorizedSocialAgentSimulation with three different radius rules of updateState() method.
When running simulation, type in the same parameters as SocialAgentSimulation (four of them) on the command line argument.
For CategorizedSocialAgentSimulation, DEFAULT = 15, SMALL = 5, MEDIUM = 40, and LARGE = 80.
(DEFAULT radius) (MEDIUM radius) (LARGE radius)
As the radius size gets bigger, the number of unmoved agents increases. In fact, the bigger the radius, the more agents are likely not to move in the first place.
Instead of making separate main classes for each type of simulation, write just one Simulation class and make it possible for the user to control the type of SocialAgents from the command line. Let them control the radius and other parameters as well.
I created AgentSimulation class in order to enable user to choose the type of Agent, radius size for updateState() method, number of agents to draw, and number of iterations for simulation.
When running AgentSimulation class, user needs to type in following command line arguments: 1) width, 2) height, 3) number of agents, 4) number of iterations, 5) type of agent, 6) radius size. For the type of Agent, 1 refers to SocialAgent; 2 refers to CategorizedSocialAgent; 3 refers to CoordinateAgent.
Regarding controlling the radius size, I created enumeration Radius in each type of Agent.
Then I added a method setRadius() in each Agent class, which would be used in simulation classes. The size of radius is actually changed in updateState() method, which I used conditional statement for.
In AgentSimulation class, I created a LinkedList of agents in order to loop through them and call an appropriate setRadius method based on the type of agent.
User can choose the type of Agents by typing 1, 2, or 3, which simulation class will then take in and use conditional statement to add certain type of Agent to the landscape based on the input.
See if you can mix and match different agent types and write about what happens.
I created MixSimulation class to mix and match different agent types. When running MixSimulation class, user needs to type in following parameters: 1) width, 2) height, 3) first agent to be mixed, 4) number of first agents, 5) second agent to be mixed, 6) number of second agent, 7) radius size for the Agents.
Like AgentSimulation class, I used conditional statement to determine which type of agent to add to landscape based on user input. When setting the radius size and updating the agents, I needed to use different approach because agents were mixed in the landscape. Therefore, I added an instance variable type to Agent class to differentiate between different SocialAgent classes. I also added getType() method to Agent class, which is used in Landscape and Simulation classes. Landscape's updateAgents() method loops through the list of neighbors and uses conditional statements to call appropriate updateState() method based on the neighbor's type.
In MixSimulation, I did the same thing to set the radius size for each Agent according to its type.
The attachment is the animation of running MixSimulation with following arguments: 700 700 1 100 2 100 MEDIUM
Try out additional SocialAgent subclasses with different update rules.
I created another child class of SocialAgent class, CoordinateAgent. It does not have a category. The difference from SocialAgent is that updateState() method updates the agent if it has 2 or more neighbors that have bigger x and y coordinates than itself. Thus, it's difficult to be updated, and I noticed the agent switched its moved status quite frequently.
If moved, the agent is drawn with pink; if not, drawn with black.
. Below attachment is the animation of AgeSimulation class with following parameters: 700 700 200 200 3 DEFAULT
Experiment with the effects of modifying some of the update rules. These should be compare and contrast. Try to avoid comparing simulations where more than one thing has been changed.
For the first attachment, I modified update rule of SocialAgent so that it would update when there are more than 5 neighbors. For the second attachment, I ran AgentSimulation without modifying the update rule, which is more than 3 neighbors.
In the first animation, agents are hardly updated because of the new update rule.
To produce same results, run AgentSimulation with following arguments: 700 700 200 100 1 MEDIUM.
Re-implement the Queue using an array-based method instead of a Node-based method and show the functionality is identical.
I re-implemented the singly Linked-List using an array instead of a Node. Please refer to LinkedArray.java and LATest.java to see the functionality is identical. The output of LATest.java should be same as that of LLTest.java.
I learned how to work with linked-lists to store and obtain data to run a simulation like this. I also became more familiar with polymorphism and usage of type casting.
For this project, I received help from professor Layton and Maxwell, and TAs.