2011, Max Weber, and Markov Chains

I’ve been quite lazy in updating this blog. I guess WoW has really taken its toll on my free time but once school starts back up, I’ll have to tone it down. In my sociology class this past semester (I have a love-hate relationship with sociology), we had to read some interesting essays by Max Weber. He coined the term “life chances“:

Weberian life chances can be seen as an expansion on some of Karl Marx’s ideas. Both Weber and Marx agreed that economic factors were important in determining one’s future, but Weber’s concepts of life chances are more complex; inspired by, but different from Marx’s views on social stratification and social class. Where for Marx the class status were the most important factor, and he correlated life chances with material wealth, Weber introduced other factors, such as social mobility and social equality. Other factors include those related to one socioeconomic status, such as gender, race, race and ethnicity.

While some of those factors, like age, race or gender, are random, Weber stressed the link between life chances and the non-random elements of the three-component theory of stratification – how social class, social status and political affiliation impact each individual’s life. In other words, individuals in certain groups have in common a specific causal component of their life chances: they are in similar situation, which tends to imply a similar outcome to their actions. Weber notes the importance of economic factors.How the power of those with property, compared to those without property, gives the former great advantages over the latter. Weber also noted that life chances are to certain extent subjective: what an individual thinks of one’s life chances will affect their actions, therefore if one feels that one can become or is a respected and valued member of society, then it is likely to become a reality and results in one being more successful and respected than somebody without this conviction.

Naturally, this interesting sociological idea immediately made me think of Markov chains and how one would mathematically model such a hypothesis. Having never attempted to implement a Markov chain programmatically before, here’s my first stab at it:
[cpp]
class Markov {
public:
Markov(int _o) {
this->order = _o;
markov_chain.resize(this->order+1);
}

void Learn(ifstream &_i) {
string word;
while (_i >> word) {
this->words.push_back(word);
}
for_each (words.begin(), words.end(), bind1st(mem_fun(&Markov::LinkChain), this));
}

void DumpStates(string _s) {
int _o = _s.length();
if (_o <= markov_chain.size() && markov_chain[_o].find(_s) != markov_chain[_o].end())
for_each (markov_chain[_o].find(_s)->second.begin(), markov_chain[_o].find(_s)->second.end(), bind1st(mem_fun(&Markov::DumpChain), this));
}

string GetLink(string _s, int _o = 1) {
int order = _o;
string seed;
if (order == 0 || order > this->order || order > _s.length()) {
return "";
} else {
seed = _s.substr(_s.length() – order, order);
} if (markov_chain[order].find(seed) != markov_chain[order].end() && !markov_chain[order].find(seed)->second.empty()) {
random_shuffle(markov_chain[order].find(seed)->second.begin(), markov_chain[order].find(seed)->second.end());
string s = markov_chain[order].find(seed)->second.back();
return s;
}
return "";
}

~Markov() {

}

private:
// just for debugging
void DumpChain(string _s) {
cout << "dumping: " << _s << endl;
}

void LinkChain(string _s) {
transform(_s.begin(), _s.end(), _s.begin(), ::tolower);
for (int order = 1; order <= this->order; ++order) {
for (int i = 0; i < _s.length(); i++) {
// Create a new key if we need to
if (markov_chain[order].find(_s.substr(i, order)) == markov_chain[order].end() && _s.substr(i, order).length() >= order) {
markov_chain[order].insert(make_pair(_s.substr(i, order), vector<string>()));
}

// Link the next single state to key of order o
if (_s.length() > (i + order) && _s.substr(i + order, 1).length() >= 1) {
markov_chain[order].find(_s.substr(i, order))->second.push_back(_s.substr(i + order, 1));
}
}
}
}

int order;
vector <string> words;
vector <map<string, vector<string>>> markov_chain;
};
[/cpp]

The above implementation actually works with any order which is kind of neat; it also dumps the chain as a sort of unit test but the class could be significantly cleaned up. This was also my first encounter with bind1st(mem_fun(...)) which, as most would agree, is a complete nightmare. C++0x should fix some of these annoying idiosyncrasies when binding functions (or rather, function pointers).

However, as I was writing this C++ class several months back, I couldn’t help but think that Weber, and Marx, were perhaps partly wrong. It’s easy to forgo personal responsibility for ones life when one owes much to what they are to a socially deterministic model so easily put into an algorithm. Not only that, but I was looking at the problem from an admittedly personal perspective. My parents had incredibly poor life chances – even I had arguably poor life chances, and yet the current position along this “Markov chain” of life seems to be completely anomalous (at least statistically speaking). However, Weber has made the stipulation that life chances are largely subjective; saying that, however, seems to discredit the very idea of life chances and perhaps some aspects of social determinism.

I do appreciate the elegance of the idea of life chances and how eloquently it’s modeled – and the Markov brothers would perhaps agree. As far as 2011 goes, a new year brings new life chances, and I suppose the point I’m trying to make is that maybe another year is yet another link in the (Markov) chain, or another year is what we (or rather, you, dear reader) want to make of it. The programmer in me wants to believe the former, but the romantic in me wants to believe the latter. After all that, I really need a drink. Thank God it’s New Years.