Computer Science with Applications 1 & 2

More Simulation: Structural balance

Due: Thursday, Oct 25, 2012 at 6pm

The goal of this assignment is to give you more practice with loops, arrays, and functions and to reinforce the simulation concepts learned in the first programming assignment.

Introduction

Networks (aka graphs) can be used to model relationships among people, companies, countries, etc and are of great interest to people in many fields. A network consists of a set of nodes that are used to model entities (people, countries, etc) and edges that describe relationships among the entities. Edges may be directed or undirected, weighted, or of different types. In this assignment, we will look at a model of the evolution of friendships in a neighborhood. The nodes of our network will represent people who are either friends (connected by friend edges) or enemies (connected by enemy edges). To simplify the discussion, we are going to assume that everyone in the neighborhood knows everyone else and that any two people are either friends or they are enemies, that is, no one is ambivalent about anyone else.

We are interested in looking at the dynamics of triads (aka, trios) in the network and how changes in their relationships affect the structure of the network as a whole. Social network theory suggests that some combinations of friend/enemy relationships among three people are stable (or balanced) and others are not. There are four possible configurations or types of triads (note: this figure is in color in the on-line version of the assignment):

We identify the type of a triad based on the number of enemy edges. A Type 0 triad represents three mutual friends, which is a stable configuration. Type 2 triads are also stable under the theory that the enemy of my friend is my enemy. In contrast, Type 1 triads are not stable. If person A is friends with persons B and C, it is likely that persons B and C will eventually become friends or at least acquaintances, which yields Type 0 triad. (A property known as triadic closure.) Alternatively, it might be the case that persons B and C cannot stand each other, in which case, it is likely that person A will eventually flip his opinion of one of person B and person C, which yields a Type 2 triad. Finally, the theory that the enemy of my enemy is my friend suggests that Type 3 triads are also not stable. Eventually, two of the three persons in the triad will gang up on the third.

The field of social network theory uses the term balanced to describe a triad that is in a stable configuration. A network is said to be in structural balance if every possible triad is balanced. The question of interest to sociologists is: given a neighborhood where the relationships among the people in the neighborhood are chosen at random and a set of rules for how to update relationships to resolve instabilities, how likely is it that we will eventually reach a state of structural balance?

We will answer this question by simulating the evolution of the relationships in the network. To guarantee that our simulations will terminate, we are going to limit the updates that can be done during a single trial simulation. Instead of asking how likely is it that a neighborhood with certain characteristics will reach structural balance, we ask how likely is it that such neighborhoods will reach update-limited structural-balance, i.e., how likely is it that such neighborhoods will reach structural balance within a specified number of updates. Your task is to write a program to answer this question.

Evolution rules

Here are the rules for evolving a single triad:

Data representation

We will represent neighborhoods with a two dimensional boolean array, neighborhood, where neighborhood[i][j] is true if person i and person j are friends and false if they are enemies. Note that these matrices are symmetric, that is neighborhood[i][j] equals neighborhood[j][i]. We will assume for completeness that the people in our neighborhood are not in need of years of therapy, that is, neighborhood[i][i] is true.

We have provided a function genNeighborhood(int N, double p) that takes the number of people in the neighborhood, N, and the friendship probability, p, and returns a randomly generated neighborhood (where each pair of neighbors are friends with probability p).

For testing purposes, it can be useful to start from a known neighborhood. The distribution contains some simple neighborhoods for this purpose:

  1. tests/sample-neighborhood-0.txt: a neighborhood that has type 0, type 2, and type 3 triads.
  2. tests/sample-neighborhood-1.txt: a neighborhood with only enemy edges,
  3. tests/sample-neighborhood-2.txt: a neighborhood with only friend edges
  4. tests/sample-neighborhood-3.txt: a neighborhood that has type 0 and type 1 triads.

We have also provided functions that read the neighborhood files (boolean[][] TableUtil.loadBooleanTable(String filename)) and print the current state of a neighborhood (TableUtil.printBooleanTable(boolean[][] table)).

Simulation Parameters

There are five parameters for these simulations:

Your task

Your task is to write a program that estimates the likelihood that a neighborhood with certain characteristics (number of people, friend probability, and evolution parameter) will reach update-limited structural-balance. Specifically, you need to implement the function estimateBalanceLikelihood in Balance.java. To accomplish this task, you will need to do the following subtasks:

We have provided the code for your program to accept all the necessary parameters as command-line arguments. Our code validates the parameters and uses them to invoke estimateBalanceLikelihood.

You should not implement your entire solution in that one function! This exercise requires decomposing the problem into multiple functions; instead of telling you what that decomposition is, it is up to you to decide what functions you will need to solve the problem cleanly. You should think carefully about this decomposition and how you will test your functions before you start writing code.

Getting started

We have seeded your PhoenixForge repositories with a directory named pa3, which contains the following:

Balance.java includes code to parse the command-line arguments, call the function estimateBalanceLikelihood, and output the result.

Writing unit tests

Unlike the previous two assignments, we are providing you with only a few tests. Furthermore, these tests only test your complete solution in a few scenarios. So, just because your code passes the tests we have provided is no guarantee that your solution is correct.

In this assignment, it is up to you to write tests that will convince you (and us) that your code is correct. These tests are more properly called unit tests because they focus on a single function (a single "unit" of your program) to determine whether it will function properly when used in a larger context. A good set of unit tests covers all the different types of input the function might receive. For example, if you have a function for determining whether a network is in structural balance, you would want to test it on at least one balanced network and one unbalanced network.

In the previous assignment, we encouraged you to lump all such tests into a TestAuxiliary.java file. Java programmers traditionally write a separate test class, named TestX.java, for each function X. In this assignment, you must follow this convention and provide test code for all your major functions. To get you started, we have provided sample test code for the function estimateBalanceLikelihood (see TestestimateBalanceLikelihood.java) to give you an idea of how to structure your testing code.

When writing your own test classes, we suggest you do the following:

Your grade will depend, in part, on the quality of your test code, that is, whether your tests are comprehensive.

This part of the assignment may sound tedious, but testing each function as you write it can often significantly reduce the amount of time you spend debugging. One of my test functions turned up a bug---I divided by 30 in a place where I had intended to divide by 3.0---that I had overlooked and might never have found in the absence of careful unit testing.

Unit tests with random numbers

Because testing code that uses random numbers can be tricky, our LocalRandom class allows you dictate the sequence of numbers to be generated by calling the function LocalRandom.initRandomFixed() with an array of doubles. Subsequent calls to the random number generator will hand out the values you specified in the order they occur in the array. Note: LocalRandom.randBoolean() generates a random value (using the specified values, if provided) and returns true if the specified value is strictly less than 0.5 and false, otherwise.

For example, if we wish to the test first update rule for type 1 triads, we can set q to be .6 and use the (1,2,3) triad the sample-neighborhood-3.txt as a test case. Here's the setup code for the test:

    boolean[][] network = TableUtil.loadBooleanTable("tests/sample-neighborhood-3.txt");
    double[] vals = {.4};   // yield a value less than q.
    LocalRandom.initRandomFixed(vals);
    // do test on network w/ trial (1,2,3)
To test the second update rule for type 1 triads, you could use the following set-up calls:
    boolean[][] network1 = TableUtil.loadBooleanTable("tests/sample-neighborhood-3.txt");
    double[] vals1 = {.7, .3};    // yield a value greater q, and then yield T.
    LocalRandom.initRandomFixed(vals1);
    // do test on network1 w/ trial (1,2,3)
or
    boolean[][] network2 = TableUtil.loadBooleanTable("tests/sample-neighborhood-3.txt");
    double[] vals2 = {.7, .6};   // yield a value greater q, and then yield F.
    LocalRandom.initRandomFixed(vals2);
    // do test on network2 w/ trial (1,2,3)
depending on which of the two friend edges you wish to flip.

Submission

You will need to add your test code to your PhoenixForge repository using the command svn add <filename> from within your pa3 directory, where <filename> is replaced by the name of the file you wish to add. For example, svn add TestestimateBalanceLikelihood.java will add the file TestestimateBalanceLikelihood.java to the repository.

To submit your assignment, use the command svn status to make sure you have added all your files to your repository and then check your code into PhoenixForge using the command:

 svn ci -m"final version ready for submission"
from within your pa3 directory. We will grade the last version you check in. We recommend checking in your code early and often.

Acknowledgements

This assignment was inspired by the discussion of structural balance in the book Networks, Crowds, and Markets by David Easley and Jon Kleinberg. The evolution rules are taken from the paper "Social balance on networks: The dynamics of friendship and enmity", T. Antal, P.L. Krapivsky, and S. Redner in Physica D (2006) pg. 130-136.