Saturday, January 18, 2014

Headers and Includes: Why and How

Organize your directories so that each class has its own header file (.hpp) with the class declaration and its own implementation file (.cpp) with the source code for the class methods.

Your main() function will be in its own .cpp file and all the .cpp files will be compiled into .obj files, which will then be linked into a single program by the linker.

http://www.cplusplus.com/forum/articles/10627/

The #include statement is basically like a copy/paste operation. The compiler will "replace" the #include line with the actual contents of the file you're including when it compiles the file.

The difference between Header files and Source files? Basically, header files are #included and not compiled, whereas source files are compiled and not #included. Files with header extensions might be ignored by the compiler if you try to compile them.

1) Only #include things you need to include (covered next section)
2) Guard against incidental multiple includes with include guards.

An Include Guard is a technique which uses a unique identifier that you #define at the top of the file. Here's an example:

1
2
3
4
5
6
7
8
//x.h

#ifndef __X_H_INCLUDED__   // if x.h hasn't been included yet...
#define __X_H_INCLUDED__   //   #define this so the compiler knows it has been included

class X { };

#endif 


This works by skipping over the entire header if it was already included. __X_H_INCLUDED__ is #defined the first time x.h is included -- and if x.h is included a second time, the compiler will skip over the header because the #ifndef check will fail.

Always guard your headers. Always always always. It doesn't hurt anything to do it, and it will save you some headaches.

C++ Programming (from the book Thinking in C++)

Identifier names

The first letter of an identifier is only capitalized if that identifier is a class. If it is a function or variable, then the first letter is lowercase. The rest of the identifier consists of one or more words, run together but distinguished by capitalizing each word.

So a class looks like this:
class FrenchVanilla : public IceCream {

an object identifier looks like this:
FrenchVanilla myIceCreamCone(3);

and a function looks like this:
void eatIceCreamCone();
(for either a member function or a regular function).

The one exception is for compile-time constants (const or #define), in which all of the letters in the identifier are uppercase.

The value of the style is that capitalization has meaning – you can see from the first letter whether you’re talking about a class or an object/method. This is especially useful when static class members are accessed.

Order of header inclusion
Headers are included in order from “the most specific to the most general.” That is, any header files in the local directory are included first, then any of my own “tool” headers, such as require.h, then any third-party library headers, then the Standard C++ Library headers, and finally the C library headers.

If the order of header inclusion goes “from most specific to most general,” then it’s more likely that if your header doesn't parse by itself, you’ll find out about it sooner and prevent annoyances down the road.

Include guards on header files
Include guards are always used inside header files to prevent multiple inclusion of a header file during the compilation of a single .cpp file. The include guards are implemented using a preprocessor #define and checking to see that a name hasn’t already been defined. The name used for the guard is based on the
name of the header file, with all letters of the file name uppercase and replacing the ‘.’ with an underscore. For example:
// IncludeGuard.h
#ifndef INCLUDEGUARD_H
#define INCLUDEGUARD_H
// Body of header file here...
#endif // INCLUDEGUARD_H

Use of namespaces
In header files, any “pollution” of the namespace in which the header is included must be scrupulously avoided. That is, if you change the namespace outside of a function or class, you will cause that change to occur for any file that includes your header, resulting in all kinds of problems. No using declarations of any
kind are allowed outside of function definitions, and no global using directives are allowed in header files.

Accessor Method
As a general rule of design, you should keep the data members of a class private. To access private data in a class, you must create public functions known as accessor methods.

A public accessor method is a class member function used either to read the value of a private class member variable or to set its value. This practice enables yo to separate the details of how the data is stored from how it is used. You can later change how the data is stored without having to rewrite any of the other functions in your programs that use the data.

const Member Functions
If you declare a class method const, you are promising that the method won't change the value of any of the members of the class. It is good programming practice to declare as many methods to be const as possible.

Class declarations and method definitions
Each function that you declare for your class must have a definition (the function implementation). The convention is to put the declaration into what is called a header file: most of the time, clients of your class don't care about the implementation specifics, and reading the header file tells them everything  they need to know.

The declaration of a class is called its interface because it tells the user how to interact with the class. The function definition tells the compiler how the function works.


Pointers
The address-of operator (&) returns the address of an object in memory.
Pointers are used mainly for three tasks:
1. Managing data on the free store
2. Accessing class member data and functions
3. Passing variables by reference to functions

The free store (heap) is not cleaned until your program ends, and it is your responsibility to free any memory that you've reserved when you are done with it. The advantage to the free store is that the memory you reserve remains available until you explicitly state you are done with it by freeing it.

You allocate memory on the free store in C++ by using the new keyword. new is followed by the type of the object that you want to allocate. The return value from new is a memory address.
int pPointer= new int;

Remember to delete a pointer after you are done using it. For every time in your program that you call new, there should be a call to delete.

When you call delete on a pointer to an object on the free store, that object's destructor is called before the memory is released.

Objects on the free store persist after the return of a function. The capacity to store objects on the free store enables you to decide at runtime how many objects you need, instead of having to declare this in advance.

The this Pointer
Each class member function has a hidden parameter: the this pointer, pointing to "this" individual object.  A pointer to the object that holds the function.

If you declare a pointer to a const object, the only methods that you can call with that pointer are const methods.

Protect objects passed by reference with const if they should not be changed. Set pointers to nullptr rather than leaving them uninitialized or dangling.

The C++ clients of classes and functions can rely on the header file to tell all that is needed: it acts as the interface to the class or function. The actual implementation is hidden from the client. This enables the programmer to focus on the problem at hand and to use the class or function without concern for how it works.


Passing by Reference
Passing by value is like giving a museum a photograph of your masterpiece instead of the real thing. Passing by reference is like sending your home address to the museum and inviting guests to come over and look at the real thing. The solution is to pass a pointer to a constant object OR a reference to a constant object. Doing so prevents calling any non-const method on it, and thus protects the object from change.

Whenever possible, pass parameters by reference. Don't use pointers if references will work.
Whenever possible, use const to protect references and pointers.

It is safer to build your functions so that the delete the memory they create.


Arrays
The American National Standards Institute (ANSI) standard declares the scope of variables in the for loop only to the block of the for loop itself.

Think of the index of an array as the offset.

In C++, an array name is a constant pointer to the first element of the array. In the declaration
Cat Family[500];
Family is a pointer to &Family[0], which is the address of the first element of the array Family. For all practical purposes, you can treat the pointer to an array as the name of the array. The one thing you will need to do, however, is to free the memory you allocated in setting up the array. In C++, arrays are no more than special cases of pointers.

Deleting Family automatically returns all the memory set aside for the array if you use the delete with the [] operator. By including the square brackets, the compiler is smart enough to destroy each object in the array and to return its memory to the free store. If you leave the brackets off, only the first object in the array is deleted.

When you create an item on the heap by using new, you always delete that item and free its memory with delete. Similarly, when you create an array by using new <class>[size], you delete that array and free all its memory with delete []. The brackets signal the compiler that this array is being deleted.

The biggest advantage of being able to allocate arrays on the heap is that you determine the size of the array at runtime and  then allocate it.






Monday, January 6, 2014

Python Trivia

Any command you can run in the terminal window can be run inside IPython when you start the command with !

Shallow copy means copying references and deep copy implies copying the complete contents of an object (roughly speaking). The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
  • A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

 A trailing comma would turn an expression into a one-tuple and "()" would represent a zero-tuple.  it is the commas, not the parentheses, that define the tuple

Like Jave, Python uses automatic garbage collection, releasing objects whose reference count is zero.


Lists and References:

Creating Lists

Python creates a single new list every time you execute the [] expression. No more, no less. And Python never creates a new list if you assign a list to a variable.
A = B = [] # both names will point to the same list

A = []
B = A # both names will point to the same list

A = []; B = [] # independent lists
Note that the for-in statement maintains an internal index, which is incremented for each loop iteration. This means that if you modify the list you’re looping over, the indexes will get out of sync, and you may end up skipping over items, or process the same item multiple times. To work around this, you can loop over a copy of the list:
    for object in L[:]:
        if not condition:
            del L[index]
Alternatively, you can use create a new list, and append to it:
    out = []
    for object in L:
        if condition:
            out.append(object)
>>> l1=range(3)
>>> l2=range(20,23)
>>> l3=range(30,33)
>>> l1[len(l1):]=[l2]    # equivalent to 'append' for subscriptable sequences 
>>> l1[len(l1):]=l3      # same as 'extend'
>>> l1
[0, 1, 2, [20, 21, 22], 30, 31, 32]
By putting the list constructor around l2 in l1[len(l1):]=[l2], or calling l.append(l2), you create a reference that is bound to l2. If you change l2, the references will show the change as well. The length of that in the list is a single element -- the reference to the appended sequence.

With no constructor shortcut as in l1[len(l1):]=l3, you are making a true (shallow) copy of the elements in l3.

So here, changing the element of l2 will change corresponding "list" element of l1, and vice versa. Changing the element of l3 will not changing the corresponding element in l1, and changing corresponding element in l1 will not change the element in l3, because "extend" works using a shallow copy and the elements in l3 is immutable.

>>> l1=range(3)
>>> l2=range(20,23)
>>> l3=[l2]
>>> l1[len(l1):]=l3      # same as 'extend'
>>> l1
In this case, however, changing the element in each of the lists will change the corresponding element in the others, because even for a shallow copy, references are stored because the corresponding elements are mutable (a list).

The list object consists of two internal parts; one object header, and one separately allocated array of object references. The latter is reallocated as necessary.
The list has the following performance characteristics:
  • The list object stores pointers to objects, not the actual objects themselves. The size of a list in memory depends on the number of objects in the list, not the size of the objects.
  • The time needed to get or set an individual item is constant, no matter what the size of the list is (also known as “O(1)” behaviour).
  • The time needed to append an item to the list is “amortized constant”; whenever the list needs to allocate more memory, it allocates room for a few items more than it actually needs, to avoid having to reallocate on each call (this assumes that the memory allocator is fast; for huge lists, the allocation overhead may push the behaviour towards O(n*n)).
  • The time needed to insert an item depends on the size of the list, or more exactly, how many items that are to the right of the inserted item (O(n)). In other words, inserting items at the end is fast, but inserting items at the beginning can be relatively slow, if the list is large.
  • The time needed to remove an item is about the same as the time needed to insert an item at the same location; removing items at the end is fast, removing items at the beginning is slow.
  • The time needed to reverse a list is proportional to the list size (O(n)).
  • The time needed to sort a list varies; the worst case is O(n log n), but typical cases are often a lot better than that.


Friday, November 15, 2013

Overconfidence and Dunning-Kruger effect

People are typically overconfident. They tend to overestimate their abilities in all kinds of areas, ranging from sense of humor, grammar, reasoning skills, to driving skills. Interestingly, this effect is most pronounced among people who have the least skill. Those with a test score in the 12th percentile would on average estimate themselves to be in the 62nd percentile. The Optimism Bias by Tali Sharot gives a lot of examples and corresponding explanation for this prevalent phenomenon of overconfidence, claiming that our brains are irrationally optimistic.

One of my favorite academic papers is The Trouble with Overconfidence by Don Moore and Paul Healy, published in Psychological Review in 2008. They use Bayesian updating to show that even under the assumption of rationality, this phenomenon of overconfidence can appear.

"After experiencing a task, people often have imperfect information about their own performances but even worse information about the performances of others. As a result, people’s post-task estimates of themselves are regressive, and their estimates of others are even more regressive."



Rephrase their conclusion in plain English: when a task is easy, people underestimate their performance but underestimate the performance of others even more, so they think they perform better than others do. When trying to finish a difficult task, however, people overestimate how well they perform but overestimate even more how others perform, so they think others perform better than they do.

Thursday, November 14, 2013

Social Influence and Social Value

Human beings are social animals, and it is important to us how others perceive us. The clothes we wear, the cars we drive, the houses we live, all potentially influences how other people see us. So aside from their physical and practical values, clothes, cars, and houses all have social values, which make us willing to buy something at a price much greater than its utilitarian value. Even what we talk about, aside from the value of communicating information, has social value that influences how others perceive us. So we talk about cool things, we tell jokes, we gossip, not so much for communication as to appear interesting, smart, and knowledgeable, showing our good qualities as potential friends, mates or business partner.. Things that have social values provide visible symbols of social status.

It is interesting to think that while most people choose to talk cool stuff, which bring social value to the "talkers," what most people talk about determines what kind of products or what type of consumption have high social values. When most people talk about a certain product, owning that product bring the owner the attention and social status. Information spread under the disguise a random chat.

The consumption of all social products exhibits positional externality. Well, that is a confusing economic phrase, but to put it a simple way, it means that your consumption of some social product incurs social cost to other people. Here I emphasize the term "social" because the practical value is unaffected. Consider the example of houses. When you have a reasonable-size house while all your neighbors have tiny houses, then you feel good about yourself, which comes from the value of your social standing. You feel good maybe you your neighbors talk a lot about you, like how rich you are, how high your salary must be, how comfortable your life must be in such a "big" house compared to their little tiny ones. Now put your house into a neighborhood where all your neighbors have spacious houses. You feel sad, upset and to some extent depressed. You are out of the focal point of attention now. Your neighbors stop talking about you, or worse, they talk about bad things, like how bad your financial condition must be, how terrible for you to live in such a "small" house, etc. Your physical living condition is the same, but your social standing makes you feel drastically different in these two situations. That explains why we may want to be a big frog in a small pond rather than a small frog in a big pond (c.f. Choosing the Right Pond by Robert Frank).

Notice that the consumption of social value is a zero-sum game. When everyone increases the size of their houses, the social values of the houses don't change that much, though the practical values increase. This will give rise to welfare loss as we over-allocate our resources to consumption that brings social value, while the social value remains unchanged, the marginal practical value keeps decreasing, even to a level we cannot feel the increase of the practical value. Now you should understand why after we have a dramatic increase in our living condition compared to our past, we don't feel any happier. You should also understand why the GDP difference is not a good predictor of happiness: while the United States has a much higher GDP per capita than the Philippines, the Americans are not much happier than the Filipinos (indeed, the Americans are much less happy than the Filipinos according to many happiness indices).

So the lesson? Paying too much attention to the consumption of social goods is a recipe for sadness. But when you compare yourself with others, don't blame anyone. It is our nature as social animals. Evolution has made us that way, and it was advantageous in the hunter-gather society when social connection and cooperation is important and even a matter of life and death. We are hence wired to care about what others think about us, and a consequence of this is our preferences for social standing. It is not a bad thing, but if you want to be happier, you probably need to care less about others' opinions. What should we do then? Maybe first be aware of this, and realize that missing a train in painful only if you run after it (a quote from the book The Black Swan by Nassim Nicholas Taleb), and failing to achieve the success that others expect is painful if you chase after it.

The bottom line: Be yourself. Know who you are and what you want, not who others want you to be or what most people want.

Tuesday, November 12, 2013

Why the gene for suicide?

It is a puzzle why evolution doesn't eliminate the gene that gives people propensity to commit suicide, because if someone has this "suicide" gene and does commit suicide, this gene would not pass on. Natural selection should have selected against that gene, but as we can see, natural selection is not that successful in doing this. We can see some suicidal or nearly suicidal behaviors among animals, which can be explained by kin selection: when your suicidal behavior benefit your close relatives, then it may be helpful to pass on the copy of genes on your relatives, which are the same as yours. The suicidal behavior of human, however, seldom benefit their kin, and hence cannot be explained by kin selection.

To solve this puzzle, it is helpful to realize that not every characteristic of human being is selected directly by natural selection. Sometimes they are just by-products of other characteristics. I would argue that suicidal behavior and its major cause depression are by-products of the human desire to be significant and to have a purpose. This desire to be significant is a major driving force for human, which can bring them more resources and more mating opportunities. When we fail to achieve what we planned, we feel sad. This bad feeling motivates us to try harder. This close to perfect design in the hunter-gatherer society, however, is flawed in modern society. We now live in a time where there are tons of situations that can put us into stress, tons of reasons for us to get disappointed and the fast paced living keeps us from recovering from the stress and disappointment, hence depression develops. As suicides are almost unheard of in primitive societies, we can say that human suicidal behavior is a product of the mal-adaptation of our genes to modern environment.

Monday, November 11, 2013

Evolution and the Prefrontal Cortex

More than 2000 years ago, Confucius said "the desire for food and sex is human nature." From an evolutionary point of view, food and sex are not just human nature, but the nature of every animals. In a general sense, survival and reproduction are the driving force of all living organisms.

What, then, distinguish human from other animals and living organisms? In a word, prefrontal cortex (PFC). PFC is the anterior part of frontal lobe, and it is responsible for planning, decision making, and moderating social behavior. The prefrontal cortex makes up far larger percentage of the brain compared to other animals.

Having a prefrontal cortex is a blessing and a curse. This reminds me of these words from Spider Man: with great power, comes great responsibility. It is a blessing because it enables human to think, to plan, to reason, to imagine, to visualize, to discover and resolve conflicts. With this ability, human start to have dominion over the earth. The prefrontal cortex, however, is also a curse because concomitant with the ability to think and plan is the potential to worry and be anxious about the future. Of course, without the motivating feeling of being worried about the future, the prefrontal cortex would be of no use because people may simply not to use it. But the feeling of worry and anxiety, however, at the same time put stress on human mind and body, and when the feeling is too strong and last too long, it does harm to human both mentally and physically. So the prefrontal cortex develops this ability of self-deception to reduce cognitive dissonance and make human feel better, preventing the harm done by anxiety. It reminds me the tragic ending in Shutter Island where Teddy has to be lobotomized to get rid of his self-deception and illusive imagination.

Interestingly, when people are nervous and anxious, they activate the alarm system built in their brain, which prompted a complex change in brain chemicals that inhibit the functioning of the prefrontal cortex. They temporarily shut down their prefrontal cortex, which is like they have a temporary lobotomy! Believe it or not, this is an advantage in a life-or-death situation. The shutting down of people's profrontal cortex rid off their ability of thinking, and they instead depend more on their instinct, getting ready in an impulsive fight-or-flight state. Consider back in the Pleistocene, you are hunting your dinner somewhere in the savanna and suddenly you spot a tiger eyeing you. What do you do? I don't know what you think, but your brain think it's better to make sure you act quickly with every ounce of energy you have. Your brain think it's better not to let you think. This fight-or-flight response wants is an energy-management instinct, direct you to spend your limited physical and mental energy in an efficient way.

The problem is this once advantageous design back in the hunter-gatherer society is not adaptable to modern society, as there are few life-and-death situations. When we under pressure, we feel nervous, and our instinct mistakenly takes current situations like taking an exam or giving a public speech as life threatening, shuts down our thinking and reasoning ability, and get us ready to engage in a fight or a flight. There are also physiological changes corresponding to this feeling of stress, which consume much more energy much more quickly than common situations. Constant stress, as we can easily see here, gives you a feeling of burning down. It is actually true, because your body burns a lot of energy. This condition if lasting long will be detrimental to your health.