Search This Blog

Thursday, February 15, 2018

TBD: Chapter I

It was a night like any other, yet there was a difference. A full moon lit up the otherwise dark alleys branching away from Fifth Avenue. Two men in thick, black jackets were crossing the intersection at S Aiken street, their footsteps disrupting the night silence. One of the men had a distinctively rugged beard.

Click.

The sound of the revolver clicking startled the slower of the two men! Were they not alone? He spun around as quickly as his body would allow. For a split second, he thought he saw the silhouette of a tall woman.

Then there was darkness.

-----

Where am I?

It had been over five minutes since he had woken up. Why had it taken him this long to ask this question? He was cold. Very cold. The warmth emanating from the single yellow incandescent streetlight was a welcome relief. He inched towards it, cautiously taking in the view.

Although his surroundings looked oddly familiar, he wasn't sure where he had seen that abandoned building before. Just as that thought crossed his mind, he realized why he couldn't place his surroundings. The building wasn't abandoned, at least, not when he had been there last week.

This was Squirrel Hill.

Although, not quite. He had just been inside Crazy Mocha a week ago, ordering a Chai Latte. Yet, here it stood before him, abandoned, and on the verge of collapsing.

Where was he?

A gust of cold wind blew from the direction of Forbes Avenue, accompanied by a low growl that sent a shiver down his spine. He hurried into Crazy Mocha, closing what was left of the door behind him. The door creaked shut.

It was pitch dark inside. As his pupils adjusted to the level of light inside the room, an overwhelmingly strong musty smell hit him. All he wanted was to run away from the place, but the thought of going back out onto the abandoned street made him stand his ground.

He could finally see enough of the room. It looked like no one had visited the place in months. The broken tables and chairs were covered in dust. There were no fresh coffee stains anywhere. The chalkboard used to list the specials was empty. There was no sign of life.

Where was he?

Something stirring in the shadows caught his attention. He reached for the phone in his pocket, hoping to use it as a flashlight. As he reached into his pocket, he realized that he couldn’t feel the familiar weight of his phone and his wallet. Did they not follow him to this odd new place?

There was more movement in the dark behind the coffee counter. He squinted, peering into the dark to identify the source of the disturbance. Whatever was making the noise was moving fast. Were those a pair of eyes?

A loud thud caused him to freeze. That thing had knocked over a table. Silence followed. Within a few seconds, something — someone — whimpered, then began to cry. The voice sounded like it belonged to a little girl. What was a little girl doing in a place like this? Would she be able to tell him what was going on?

Saturday, October 1, 2016

What is a "good" motivating factor?

I have been asking myself this question for a while now, but the debates I've had with myself haven't produced a satisfactory answer in the time that I've had to think about it. This is my attempt to put these debates into words, in the hope that it might help.

So, who or what decides how good of a motivator something is? Before we jump in to that, how do we even decide whether a motivating factor is good or bad? Can we even objectively arrive at an answer to that? The easy solution is to do away with the trouble of trying to do so, and declare it to be subjective. That doesn't satisfy me. Maybe we just haven't thought about it enough? Even if it does turn out to be subjective, it would make an interesting exercise to realize why this is so. Further, if one is going to make major decisions like choosing their career based on a motivating factor (say interest or curiosity), what is the guarantee that he/she will have the same drive ten-twenty years down the line? Is that even an important property for a motivating factor to have? Having established why this exercise is worth the time, I'll get started.

How do we decide if a motivating factor is good or bad? Are there any axes along which we can quantitatively measure the "goodness" of a motivating factor? Even if we don't actually assign values to these factors along these axes, can we get everyone to agree that a particular factor lies further along an axes than another factor? Let's being by trying to define such axes.

As I've indicated above, one important axis might be sustainability, i.e. how long will this motivating factor continue to drive me to obtain the goal it defines? Let us try to take two motivating factors as examples to see where we can place them along this axis: competition and interest. These two motivating factors have roots in different emotions, namely pride/jealousy and love/curiosity. Trained as we have been from childhood, just putting these into words brings about good feelings for interest and bad ones for competition. But we'll get to that shortly. Let's look objectively at how sustainable competition and interest are as motivators. Note that a motivator is always associated with an end goal, so if your end goal changes, the motivator has changed as well. Under this definition, competition lasts as long as you have peers to compete with. Interest is harder to limit, as it could be either because of curiosity, or because of love. Interest due to curiosity as a motivator lasts as long as you don't have enough of a flavor of that topic to decide whether to work towards a new goal (in which case the motivator changes) or not. I'm going to be hand-wavy in saying that interest due to love is not well thought out, and there is actually another driving emotion that defines why you love the subject/field/job. If we think about it, we actually love some subject/field/job because of a few reasons. Maybe it sates our thirst for puzzles, in which case the true emotion is the pleasure of satisfaction. We want our brain to release more of the chemicals associated with the feeling of satisfaction. Maybe it makes us nostalgic about something from our childhood, in which case the true emotion is the pleasure/grief associated with nostalgia. Anyhow, let us say that we break down interest due to love into one (or more) of these emotions. Let us compare, for example, motivation due to competition, curiosity and pleasure of satisfaction. How sustainable are they? Leaving out a few cases, almost everyone can always find peers to compete with. You can find ranks to grow in an organization, peers to beat or stay ahead of while publishing, stats of peers to beat as an athlete, etc. Especially if you set a vague enough end goal (like I want to rise in ranks as much as possible, independent of the organization), you can sustain that motivation for quite a long time. Remember that we are associating a motivator with the end goal, so I argue that we can always objectively place it somewhere on this axis relative to other motivators. Motivation due to curiosity is not very sustainable (as you might have figured without even performing this analysis). To put it in formal terms, you don't really know your end goal when you are curious about something. Thus, you are forced to set a short-term end goal, which is bounded by what you know about that subject. Our motivator changes once we understand enough about the topic to switch goals. Similarly for motivation due to the pleasure of satisfaction: once we are satisfied with a particular puzzle, the motivator changes. One might argue that we can pick a puzzle that will never be solved, or equivalently, will take our lifetime to solve. But can one truly find a puzzle of that form (a concrete task, and not a vague area)? Even if we do find such an area, would someone be motivated enough to pursue a puzzle that won't result in satisfaction (take an infinite amount of time to do so)? Is the true emotion that drives that person still satisfaction in such a case?

By our definition, given a 3-tuple of an (end goal, emotion, context), we can objectively argue about the sustainability of such a motivator. Note that it is no longer truly subjective as we are embedding all the relevant information into that 3-tuple. To conclude, sustainability(motivation due to competition to always grow to the highest rank) >= sustainability(curiosity to learn more about a vast area) >= sustainability(get satisfaction by solving a particular puzzle).

Let us look at another axis, daily happiness, and see how the same motivators rank. I understand that my choice of axes is arbitrary, but the point of the exercise is the following: given a set of axes and 3-tuples, can we objectively argue (agree on) where these 3-tuples lie along these axes? If you want to choose another set of axes, then by all means, please do so! But when we share the set of axes and 3-tuples with each other, we should agree on the placement of the 3-tuples.

Back to daily happiness. Motivation to always grow to the highest rank possible rank will result in very short impulses of happiness on a daily basis. This is because your highest rank is infinitely far away (by definition), and even if you progress in ranks once every few months/weeks/days, the incremental happiness would theoretically be very small. Further, since competition has its roots in pride/jealousy, watching your peers rise in ranks while you don't can be frustrating and affect your daily happiness. Since you could potentially be competing against a large number of people, and someone or the other will grow in their rank (due to ORs on probabilities of someone growing), the gains are small while the losses can potentially be large. What about daily happiness due to curiosity? Since you don't know much about the area, with high probability, you will be learning something new on a daily basis. Each one will give you more happiness than the previous case, as you are working towards a goal that can probably be achieved in a much shorter period of time. Finally, motivation due to the satisfaction of solving puzzles. This again will provide more daily happiness than the motivation due to competition, as you are making more progress towards your goal on a daily basis; Arguably more than the curiosity case as this is achievable in a much shorter duration. In short, satisfaction from puzzles >= curiosity >= competition. But does this mean the sustainability and daily happiness axes are inversely related? Can we find a counter example where a motivator (3-tuple) provides more incremental happiness than another motivator (3-tuple), while also lasting longer? I'm running short of time, so I'm not going to pursue that train of thought.

Let's do one more axis: self improvement (is that also a motivator? Can we define a 3-tuple for it?). Does competition necessarily lead to self improvement? Not in all cases. Since your goal is to improve in ranks relative to your peers, you might find shortcuts to come out on top without actually having gained anything through the exercise. What about curiosity? By definition, you are pursuing a goal to learn more about the area and how it relates to other areas. We could all agree that self improvement in doing so will be more than in the case of competition. How about satisfaction due to solving puzzles? Since your end goal is to solve the puzzle and get satisfaction out of the intermediate steps, you might learn just enough to solve that puzzle and not more than necessary (since you are trying to rapidly progress in the direction of solving the puzzle). While the gains will potentially be more than in the competition case (you need to gain some basic knowledge to solve the puzzle!), it will be less than in the case when you are driven by curiosity to learn more about a particular topic. Thus, curiosity >= puzzles >= competition.

We could define other axes, but in the interest of time, I'm going to stop here and ask, what have we learned from this exercise? We can see that given a set of axes and 3-tuples that are motivators, we can (potentially) objectively agree on where these 3-tuples should be placed, relative to each other, along each of these axes. Can we absolutely declare that one motivator is better than another? Well, can we absolutely agree about anything in that fashion? Can we argue that an algorithm is absolutely better than another one? What about a Machine Learning model? A processor? An operating system? We define axes, such as time complexity, space complexity, error on a given task, cycles to execute a particular benchmark, time efficiency of handling signals etc. and objectively argue about how these algorithms/models/devices/systems compare along these axes. Does that mean that the comparison is subjective? Not really. How these things rank against one another is objective given the axes. What is subjective is the relevance of the axes.

Similarly, I argue that we can objectively compare the "goodness" of the motivators along some given axes. What is really subjective here, is how important these axes are to us at a given point of time in our lives.

Tuesday, October 27, 2015

My precious... (Part 1)

So I've been meaning to make (semi) detailed notes of my Arch Linux config files for a while now, in the hope that these notes will help me set up my Arch quickly if I ever have to do so from scratch. This is how my Arch currently looks. If you like what you see, read ahead!

Home sweet home

Work in progress

The WM and related scripts:

Okay, so first things first, no DEs here (in the interest of being lightweight and productive). Right now I'm running i3wm with small (and dirty) custom scripts to add some common DE-like functionality that I find useful. So what all am I referring to?
  • A modified i3bar that shows me the information that I require and of course looks good too. There are some scripts in here to fetch and display the information that I require, but I'll get to that in a bit. 
  • Some custom i3 keyboard bindings to speed common tasks. 
  • Labelling of workspaces to organize my windows.
  • A wallpaper changer to shuffle and display my massive wallpaper collection.
  • A notification daemon and scripts to display some useful notifications.
  • A modification to dmenu to detach launched processes from their parent shells.
  • A good command line file manager.
So let me get right to it!

First up, modifying i3bar to make it prettier and to extend its functionality. First up, the modifications to the bar settings in the i3config file:

bar {
  mode dock
  font pango:DejaVuSansCondensed regular 6.5
  colors {
  # Show status text in light blue color
    #statusline #ADD8E6
    background #222222
    statusline #dddddd
    separator  #666666
    active_workspace   #333333 #333333 #888888
    focused_workspace  #0088CC #0088CC #ffffff
    inactive_workspace #333333 #333333 #888888
    urgent_workspace   #2f343a #900000 #ffffff
  }

  status_command conky -c ~/.conkyrc
  status_command /home/anant/.i3/i3bar-wrapper.sh
}
Nothing fancy here, some color settings, an appropriate font and size, and specifying dock mode. The last two lines are important. I am using conky 1.10.0 to add the colors and formatting. The first command tells conky to use the .conkyrc config file in my home folder. This is the file (most of the stuff in there is pretty easy to understand):

out_to_x no
out_to_console yes
short_units yes
update_interval 1
#use_spacer left
#pad_percents 2
if_up_strictness address

TEXT

[\
# Music:
{"full_text":"${if_match ${exec ~/.i3/testmusic.sh}>=1}♫","color":"\#ffffff","separator":false,"separator_block_width":5},\
{"full_text":"${exec ~/.i3/music.sh}","color":"\#EC3B83","separator":true,"separator_block_width":8},\
{"full_text":"${endif}"},\
# Mounted Devices:
{"full_text":"${if_match ${exec ~/.i3/hasmounted.sh}>=1} USB","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${exec ~/.i3/getmounteddevices.sh} ","color":"\#F0DC64","separator":true,"separator_block_width":6},\
{"full_text":"${endif}"},\
# Disk Usage:
{"full_text":" 💾","color":"\#aaaaaa","separator":false,"separator_block_width":6},\
{"full_text":"${execi 3600 df -h --output=avail / | tail -n1 | sed -e 's/\s//g'} ","color":"\#FF9933","separator":true,"separator_block_width":6},\
# Internet:
{"full_text":"${if_up enp60s0}"},\
{"full_text":" LAN","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${addr enp60s0} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up br0}"},\
{"full_text":" BRIDGE","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${addr br0} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up enp0s20u1}"},\
{"full_text":" USB","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${addr enp0s20u1} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up wls1}"},\
{"full_text":" Wi-Fi","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"(${exec iwgetid -r})","color":"\#EC3B83","separator":false,"separator_block_width":6},\
{"full_text":"${addr wls1} ","color":"\#00ff00","separator":true,"separator_block_width":9},\
{"full_text":"${endif}"},\
{"full_text":"${if_up enp60s0}"},\
{"full_text":"${else}"},\
{"full_text":"${if_up enp0s20u1}"},\
{"full_text":"${else}"},\
{"full_text":"${if_up br0}"},\
{"full_text":"${else}"},\
{"full_text":"${if_up wls1}"},\
{"full_text":"${else}"},\
{"full_text":" No Internet ","color":"\#ff3300","separator":true,"separator_block_width":9},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
# CPU temperature:
{"full_text":" CPU","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${if_match ${hwmon 0 temp 1}<50}${hwmon 0 temp 1}","color":"\#AAF096","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${hwmon 0 temp 1}<55}${hwmon 0 temp 1}","color":"\#F0DC64","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${hwmon 0 temp 1}<60}${hwmon 0 temp 1}","color":"\#FF9933","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${hwmon 0 temp 1}>=60}${hwmon 0 temp 1}","color":"\#FF3333","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
{"full_text":"°C ","color":"\#7FFFD4","separator":true,"separator_block_width":6},\
# GPU temperature:
{"full_text":" GPU","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${execi 5 nvidia-settings -q gpucoretemp -t | head -n1}","color":"\#AAF096","separator":false,"separator_block_width":0},\
{"full_text":"°C ","color":"\#7FFFD4","separator":true,"separator_block_width":6},\
# Memory:
{"full_text":" MEM","color":"\#888888","separator":false,"separator_block_width":6},\
{"full_text":"${if_match ${memperc}<30}${mem} / ${memmax} ","color":"\#AAF096","separator":true,"separator_block_width":9},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${memperc}<60}${mem} / ${memmax} ","color":"\#F0DC64","separator":true,"separator_block_width":9},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${memperc}<85}${mem} / ${memmax} ","color":"\#FF9933","separator":true,"separator_block_width":9},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${memperc}>=85}${mem} / ${memmax} ","color":"\#FF3333","separator":true,"separator_block_width":9},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
# CPU:
{"full_text":" 💻","color":"\#aaaaaa","separator":false,"separator_block_width":6},\
{"full_text":"${if_match ${cpu cpu0}<25}${cpu cpu0}","color":"\#AAF096","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${cpu cpu0}<50}${cpu cpu0}","color":"\#F0DC64","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${cpu cpu0}<75}${cpu cpu0}","color":"\#FF9933","separator":false,"separator_block_width":0},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${cpu cpu0}<=100}${cpu cpu0}","color":"\#FF3333","separator":false,"separator_block_width":0},\
{"full_text":"${endif}${endif}${endif}${endif}"},\
{"full_text":"% ","color":"\#EEEEEE","separator":true,"separator_block_width":8},\
# Battery:
{"full_text":"${if_match ${exec ~/.i3/batterystatus.sh}>=2} 🔌","color":"\#aaaaaa","separator":false,"separator_block_width":5},\
{"full_text":"ON ","color":"\#00ff00","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${exec ~/.i3/batterystatus.sh}>=1} 🔌","color":"\#aaaaaa","separator":false,"separator_block_width":5},\
{"full_text":"${else}"},\
{"full_text":" 🔋","color":"\#aaaaaa","separator":false,"separator_block_width":7},\
{"full_text":"${endif}"},\
{"full_text":"${if_match ${battery_percent}>80}${battery_percent}% : ${battery_time} ","color":"\#AAF096","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${battery_percent}>50}${battery_percent}% : ${battery_time} ","color":"\#F0DC64","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${if_match ${battery_percent}>25}${battery_percent}% : ${battery_time} ","color":"\#FF9933","separator":true,"separator_block_width":6},\
{"full_text":"${else}"},\
{"full_text":"${battery_percent}% : ${battery_time} ","color":"\#FF3333","separator":true,"separator_block_width":6},\
{"full_text":"${endif}${endif}${endif}"},\
{"full_text":"${endif}"},\
# Backlight:
{"full_text":" 🔅","color":"\#FFFFFF","separator":false,"separator_block_width":6},\
{"full_text":"${exec xbacklight | cut -d '.' -f1}% ","color":"\#ff8080","separator":true,"separator_block_width":6},\
# Volume:
{"full_text":" 🔊","color":"\#AAAAAA","separator":false,"separator_block_width":7},\
{"full_text":"${exec ~/.i3/getvolume.sh} ","color":"\#ff8080","separator":true,"separator_block_width":8},\
# Date:
{"full_text":" 📅","color":"\#aaaaaa","separator":false,"separator_block_width":8},\
{"full_text":"${time %D} ${execi 3600 date | cut -d ' ' -f1 | awk '{print toupper($0)}'} ","color":"\#7FFFD4","separator":true,"separator_block_width":8},\
# Time:
{"full_text":" ⏰","color":"\#FFFFFF","separator":false,"separator_block_width":7},\
{"full_text":"${time %r}","color":"\#7FFFD4","separator":true}\
],
Before I get to the scripts mentioned in the conky config file, let me just touch on the last thing, the wrapper for i3bar. The last line in the bar part of the i3 config file points to a wrapper for i3bar that lets it display information from conky. This is the content of i3bar-wrapper.sh:

#!/bin/sh

echo '{"version":1}'
echo '['

echo '[],'

exec conky -c /home/$USER/.conkyrc
So the first line tells i3bar that we are using JSON, and the second line starts the endless array of inputs. Finally the last two lines are the loop part where an empty array of blocks and the information from conky are sent to i3bar.

Now for the scripts in the conkyrc file. All the commands/scripts are simple to understand and don't really need any explanation. The only script that probably warrants an explanation is music.sh. I use cmus as my music player so the script as-is will work only for if you use cmus too. However, with a couple of minor modifications, it should be possible to extend this to any music player that supports querying track information from the command line. The testmusic.sh script just tests if cmus is active using cmus-remote and returns 1 if it is active. The interesting script is music.sh:

#!/bin/sh

artist=$(cmus-remote -Q | grep ' artist ' | cut -d ' ' -f3- | sed -e 's/\&/and/g')
song=$(cmus-remote -Q | grep ' title ' | cut -d ' ' -f3- | sed -e 's/\&/and/g')

songlen=${#song}
artistlen=${#artist}

duration=$(cmus-remote -Q | grep duration | cut -d ' ' -f2-)
elapsed=$(cmus-remote -Q | grep position | cut -d ' ' -f2-)
dmin=$(($duration/60))
dsec=$(($duration%60))
if [ "$dsec" -lt "10" ]; then
  dsec="0$dsec"
fi
emin=$(($elapsed/60))
esec=$(($elapsed%60))
if [ "$esec" -lt "10" ]; then
  esec="0$esec"
fi

if [ "$songlen" -gt "20" ]; then
  modlen=$songlen
  offset=$(($elapsed % $modlen))
  if [ "$offset" -ge "$(($songlen-10))" ]; then
    song=$(echo $song | cut -c $(($songlen-19))-)
  elif [ "$offset" -gt "10" ]; then
    offset=$(($offset - 10))
    song=$(echo $song | cut -c $offset-$(($offset+19)))
  else
    song=$(echo $song | cut -c -20)
  fi
fi

if [ "$artistlen" -gt "15" ]; then
  modlen=$artistlen
  offset=$(($elapsed % $modlen))
  if [ "$offset" -ge "$(($artistlen-5))" ]; then
    artist=$(echo $artist | cut -c $(($artistlen-14))-)
  elif [ "$offset" -gt "10" ]; then
    offset=$(($offset - 10))
    artist=$(echo $artist | cut -c $offset-$(($offset+14)))
  else
    artist=$(echo $artist | cut -c -15)
  fi
fi

echo "$song -- $artist ($emin:$esec/$dmin:$dsec) "
Okay, so what's going on here? Remember those Mp3 players that we used to get in the early 2000s with inbuilt flash memory and small digital displays? Remember how the song names used to scroll on the screen, character by character, at the rate of one character a second? That is exactly what this script does. It returns a substring of the song name and the artist name to conky, and this text when displayed on the screen makes it look like the song text is scrolling.
The intended output is that the first 20 (15) characters of the song (artist) name should be displayed for 10 seconds. Then the rest of the song (artist) name should scroll on the screen, one character at at time, and finally it should pause at the last 20 characters of the song (artist) name for 5 seconds before the same cycle starts again. After we extract the song name, artist and elapsed time, we format the elapsed and total time so that they can be displayed beautifully (8 seconds should be displayed as 00:08 and not 0:8). Then if the song name length is greater than 20 characters, we find out what range of characters need to be displayed depending on the elapsed time (some fairly straightforward math in there), and use cut to pick out those characters. We repeat the same for the artist name. So now we have a working music player widget for our bar!

The result


That's all there is to the beautiful looking i3bar.

Next up, the important bindings in the i3 config file:

bindsym $mod+Return exec urxvtc

# hide the i3bar
bindsym $mod+m bar mode toggle

# hide the window titles
bindsym $mod+b border toggle
for_window [class="^.*"] border pixel 1

# Volume controls
bindsym XF86AudioRaiseVolume exec /usr/bin/bash /home/anant/.i3/increasevolume.sh && /usr/bin/bash /home/anant/.i3/volume.sh && killall -SIGUSR1 conky
bindsym XF86AudioLowerVolume exec /usr/bin/bash /home/anant/.i3/decreasevolume.sh && /usr/bin/bash /home/anant/.i3/volume.sh && killall -SIGUSR1 conky
bindsym XF86AudioMute exec amixer -q set Master toggle && killall -SIGUSR1 conky

bindsym XF86MonBrightnessUp exec xbacklight -inc 5 && killall -SIGUSR1 conky
bindsym XF86MonBrightnessDown exec xbacklight -dec 5 && killall -SIGUSR1 conky

# Keyboard backlight scripts for ASUS
bindsym XF86KbdBrightnessUp exec sudo /home/anant/.i3/asus_kbd_backlight_permission.sh && /usr/bin/bash /home/anant/.i3/asus_kbd_backlight.sh inc
bindsym XF86KbdBrightnessDown exec sudo /home/anant/.i3/asus_kbd_backlight_permission.sh && /usr/bin/bash /home/anant/.i3/asus_kbd_backlight.sh dec

bindsym $mod+F2 exec xbacklight -dec 5 && killall -SIGUSR1 conky
bindsym $mod+F3 exec xbacklight -inc 5 && killall -SIGUSR1 conky

# Lock screen shortcut
bindsym Mod4+Shift+l exec i3lock -i /home/anant/.config/variety/Downloaded/wallbase_macro/wallpaper-2684199.png -p default -d -n -f
bindsym Mod4+Shift+s exec systemctl suspend

bindsym $mod+Shift+n exec /usr/bin/variety --next
bindsym $mod+Shift+p exec /usr/bin/variety --previous

exec --no-startup-id /usr/bin/variety
exec --no-startup-id /usr/bin/dunst
exec --no-startup-id /home/anant/.i3/lowbattery.sh

# Creating named workspaces
set $tag1 "1: Web"
bindsym $mod+1 workspace $tag1
bindsym $mod+Shift+1 move container to workspace $tag1

set $tag2 "2: DC++"
bindsym $mod+2 workspace $tag2
bindsym $mod+Shift+2 move container to workspace $tag2

set $tag3 "3: Music"
bindsym $mod+3 workspace $tag3
bindsym $mod+Shift+3 move container to workspace $tag3

set $tag4 "4: Code"
bindsym $mod+4 workspace $tag4
bindsym $mod+Shift+4 move container to workspace $tag4

set $tag5 "5: ToDo"
bindsym $mod+5 workspace $tag5
bindsym $mod+Shift+5 move container to workspace $tag5

# Media controls
bindsym $mod+Shift+Home exec /usr/bin/cmus-remote -n && killall -SIGUSR1 conky
bindsym $mod+Shift+End exec /usr/bin/cmus-remote -r && killall -SIGUSR1 conky
bindsym XF86AudioNext exec /usr/bin/cmus-remote -n && killall -SIGUSR1 conky
bindsym XF86AudioPrev exec /usr/bin/cmus-remote -r && killall -SIGUSR1 conky
bindsym XF86AudioPlay exec /bin/bash /home/anant/.i3/cmusplaypause
bindsym XF86AudioPause exec /usr/bin/cmus-remote -u
bindsym $mod+Shift+Delete exec /bin/bash /home/anant/.i3/cmusplaypause

# Move to left/right workspace
bindsym Control+$mod+Left workspace prev
bindsym Control+$mod+Right workspace next
None of this really needs any explaining, but the next few paragraphs will explain some of the referenced scripts.

I use variety + feh to get the beautiful looking clock on my desktop and to shuffle through my wallpaper collection. To get variety to use feh (this is disabled by default due to some issues in Ubuntu), uncomment the line that executes the feh command in set_wallpaper in your variety config folder. The font used for the clock in the screenshot is called Akbar Plain, and the date font is called Alba Super Regular.

The variety clock+date setup


The notification daemon that I use is called dunst; it is nice and simple, and serves all my purposes. I use it primarily to receive notifications about two types of events - volume changes and low battery warnings. This is a simple script that displays the volume as a notification:

#!/bin/bash

vol=$(amixer get Master | grep % | cut -d ' ' -f7 | cut -c 2- | cut -d ']' -f1 | head -n1)

if amixer get Master | grep -q "off"; then
  dunstify -r 999 -u critical -t 1 "Volume: $vol (Muted)"
else
  dunstify -r 999 -u normal -t 1 "Volume: $vol"
fi

Volume notifications


The first line gets the volume value and the subsequent call to dunstify displays it. The -u critical/normal flags are just used to display different colors when muted/unmuted. The -r ensures that the volume notification always gets the same notification ID (if there are many calls to the script in a short span of time, the previous notifications shouldn't linger, rather, they should be replaced by the newer notifications).

Now for the low battery warning script:

#!/bin/bash

while true; do
  state=$(acpi -b | cut -d ' ' -f3 | head -c-2)
  perc=$(acpi -b | cut -d ' ' -f4 | head -c-3)
  if [ "$state" == "Discharging" ]; then
    if [ "$perc" -lt "15" ]; then
      /usr/bin/dunstify -r 998 -u critical "Battery Critically Low! (${perc}%)\n$(acpi -b | cut -d ' ' -f 5-)"
      sleep 60
    elif [ "$perc" -lt "20" ]; then
      /usr/bin/dunstify -r 998 -u normal "Battery Level Low (${perc}%)\n$(acpi -b | cut -d ' ' -f 5-)"
      sleep 120
    elif [ "$perc" -lt "30" ]; then
      /usr/bin/dunstify -r 998 -u low "Battery Level Low (${perc}%)\n$(acpi -b | cut -d ' ' -f 5-)"
      sleep 240
    else
      sleep 300
    fi
  else
    if [ "$perc" == "100" ]; then
      /usr/bin/dunstify -r 998 -u low "Battery Full (100%)"
      sleep 600
    else
      sleep 300
    fi
  fi
done

We check if the battery is discharging, the warning notifications are only displayed then. If the battery is full and discharging, the full battery notification is displayed. The rest is fairly straightforward, the percentage and time remaining and retrieved and displayed. Finally, depending on the percentage value, the script is put to sleep for either a minute, 2 minutes, 4 minutes or 5 minutes.

Battery notifications using dunst


Two final things: the script /usr/bin/dmenu_run can be modified to detach created processes from their parent shells by changing the execute command to: exec $(dmenu_path | dmenu "$@"), and a command line file manager like ranger can be used to make the task of browsing files easier.

Phew! I guess that covers the WM configuration part. That's all the time I have right now, so I'm going to defer explaining the configuration settings for my terminal emulator (urxvtd+c), text editor (vim), media player + nVidia integration (mpv), music player (cmus) and shell (zsh) to future blog posts.

Monday, October 26, 2015

What studying Machine Learning has really taught me

I find myself surprised, even a little disappointed, by how emotions drive many of my decisions. Emotions feel like a necessary evil; many times they prevent me from making morally wrong decisions, much like religion does, but at other times they cloud my judgement and make it hard for me to think logically. I think we all have something to learn from Machine Learning here.

Whenever I am presented with a tough choice, more often than not I am able to reason about the merits and demerits of each option. This makes sense - years or training data provided to the system in my brain, along with positive and negative feedback, are helping it draw sharper boundaries based on the different attribute values presented to it. But here's where things get tricky. While I am able to reason about the positive and negative feedback that I received from previous choices that I have made, there are elements of the classification system that have formed as a result of emotions, possessing weights that I have no idea how to interpret. Let me explain that a bit better. Say I watch a violent movie by telling myself that I won't be affected by it (I do this often, because I believe that I understand better than to let some movie affect me). But this is analogous to saying, "Hey I'll just pass these (partially) misclassified data points through the training module of this Machine Learning system, but it's all good! I have added conditional statements to prevent these points from affecting these few weight values, so the integrity of the whole system will be preserved". While I can be pretty sure that doing this won't significantly affect the weight values that I have kept fixed, I can make no such assumptions about weights that I am unaware of. So the repercussions of passing such points through my classification system could be catastrophic to the accuracy and general coherency of the system. While it is true that the brain is a much more complex system than I have outlined and this might not be how it works, it is highly likely that watching that violent movie does affect weight values somewhere in a way that I cannot hope to understand. Over time a combination of these modified weight values could mutate the decision boundaries produced by the system to such an extent that I would be shocked the next time that I attempt to understand the decision making process.
Coming back to how I started this post, I am now able to relate the involvement of emotions in the decisions that I make and the inscrutable weight values in my classification system. It is pretty clear now that the reason that I am shocked when emotions affect my decisions is that I did not know the decision boundaries had been bent so. However, there is one aspect of this that doesn't fit well into this whole picture. Whenever I am presented with a choice, I see not one decision boundary, but two or more of them. One boundary that is the result of logical thinking, formed by weighing the pros and cons of each option, and another one, that is the result of emotions. Of course, I am oversimplifying; the two decision boundaries are not completely independent of each other, and sometimes there are way more than two sets of boundaries. But let's start with the easy case of two independent boundaries and solve that first.
The fact that there I am presented with two boundaries that I am able to perceive leads me to believe that the classification system in my brain uses an ensemble of classifiers to arrive at a decision. This raises many pertinent issues; are all the classifiers independent of each other? Were they trained independently, i.e. emotion related data points in a separate classifier and other points elsewhere (if this is even possible)? What is the function used to combine their output decisions? Why do I feel that the output produced by the emotion-only classifier is weighted much higher than the others in the combination function?
I've made a promise to myself to better analyze these data points and decision boundaries to try to understand how the classification system works. Furthermore, until I've done so to a satisfactory level, I'm going to assume that even mundane things that I do everyday are affecting weight values in ways that I do not understand, and so I need to keep a close watch on my emotions whenever I receive any training data (which is just about all the time!). Also, if anyone has any data files that can help me study this phenomenon, please email the labelled examples (preferably in CSV format) to me for analysis.
Lol jk :)

Wednesday, December 31, 2014

Was I this mature then?

Yesterday I realized that I hadn't logged in to my Hotmail account in a really long time, so I thought I would try logging in to make sure that it had not expired. Upon logging in I found that this account was frozen in time. When I was creating my Hotmail account I had the idea that this would be my official account and so I had not signed up for any weekly digests or newsletters. Consequently, the first page of my inbox was filled with formal email conversations from a couple of years back that I had had with friends, college seniors and employees in Open Source organizations. I found these emails really fascinating and I thought I would browse through them for a bit - to decide whether I should delete this account or keep it so that I could refer to these emails later.

I was really intrigued by the content of the emails. It was not that the emails showed a level of understanding of Computer Science topics that I didn't know I possessed a couple of years back. No, it was pretty clear from the emails that my knowledge of Computer Science topics had increased over the past few years thanks to the courses that I have been taking and the books that I have been reading. What stunned me was the level of maturity of the person who had written the emails. I found it hard to believe that I had written all those emails; surely I wasn't that mature back then? Then it struck me that I had often seen many parents express similar feelings of disbelief when they saw their child say or do something that was mature for his or her age. I know that more often than not they are right about the fact that the action was unexpectedly mature for a child of that age. But sometimes it is due to the fact that we tend to underestimate how mature a child of that age would be. Why? Because when we have no reference to compare to (we don't know enough people in that age group to generalize), we try to remember how mature we were at that age based on a few incidents that come to our mind. This is exactly what I was doing while going through those emails.

We all know/have those Aunts and Uncles who are great with kids. What sets them apart from others? It is the fact that they are able to estimate the level of maturity of the kids better. Why are they able to do so? Is it because they know a lot of kids of different age groups and are thus able to generalize accurately at any given point of time? Seems highly unlikely. I think the key idea is that they never lost touch with how mature they were at a given age. This begs the question, why do we forget how mature we were some time back? I think this is because we incorrectly correlate an increase in knowledge in any area to an increase in the level of maturity. Sure, reading a few books and figuring out the solutions to a few problems helps you draw analogies between new problems that you encounter and problems that you have solved, but have you become more mature at the end of the exercise? Probably not. Unfortunately we can't quantify maturity, but if we were to estimate how mature someone is we would probably look at a few key areas like: their understanding of social norms, their views on how risky something is, they ability to control their temper, their ability to recognize that there may be no single solution to a problem, their ability to recognize that quite often there is no right or wrong but only shades of gray / circumstantial correctness, their views on religion, their views on sex, etc. My point is, the next time you learn something new, make it a point to ask yourself, "Have I become more mature after acquiring this piece of information?". Many people, myself included, don't put in the time and effort to ask themselves this question and over a period of time forget how mature they were a while back.

So why is all this important? We regularly find ourselves debating with others on important issues - sometimes with those who are younger than us. Even if you are debating with those who are older than you, the roles are reversed so that the above applies to them. In a debate our goal is to pool our common knowledge and try to arrive at a solution to the issue at hand that is most acceptable to all parties involved. It is therefore crucial that we understand the context in which a person expresses a particular thought, and we use a person's level of maturity (amongst other things) to give context to his/her ideas. Now if we are unable to correctly estimate a person's level of maturity, we may dismiss good suggestions put forward by that person based on the false premise that he/she is 'immature'. The conclusion is that if you are in a debate, it is in everyone's best interest that you correctly estimate everyone's level of maturity and to do so you need to be in touch with your own level of maturity and how it has changed over a period of time.

So when you have some time on your hands, open up a few emails in your inbox from a couple of years back and see if you are surprised by the level of maturity of the younger you. I sure was!

Sunday, June 2, 2013

Ubuntu 13.04, GNOME 3 and Bumblebee

I just upgraded my Ubuntu from 12.10 to 13.04 (now that I have a good internet connection) and I did find the desktop to be more responsive than before. The file browser seemed to be working faster, applications seemed to be launching faster and even my laptop seemed to be running a tad cooler !
I thought I'd push my luck a little and try installing the nVidia proprietary driver for my GT 630M that I had been trying to install since the December of last year. Bad move. I was left with a terminal screen and no GUI. The nVidia install script had altered my current display manager config in ways I did not know how to repair (I couldn't find all the files that had been altered).



I don't know much about hardware but from what I could understand of what was written online, the way laptops with nVidia Optimus technology work is that they direct all traffic through the in-built Intel graphics card (in my case the Intel HD 3000). If this load is detected (somehow) to be too much for the Intel card to handle, it calls upon the dedicated graphics card (enter nVidia) by redirecting the data to be processed to it. Now the major problem with this setup is that operating systems like my dear Ubuntu-Linux refused to detect the dedicated graphics card all together and hence all my attempts to install the nVidia drivers failed miserably. Let me pause for a second - I wanted a GUI before experimenting any further and so I thought I would sort out the Unity issue first before proceeding with the graphics card issue.

Taking my brother's advice I decided to scrap Unity in favour of GNOME 3.8 and lightdm in favour of gdm. So I removed Unity and installed GNOME 3.8 by getting the packages from their repository.
sudo add-apt-repository ppa:gnome3-team/gnome3
sudo apt-get update
sudo apt-get install gnome-shell ubuntu-gnome-desktop

Done ! GNOME 3.8 installed and running. It was the bare minimum with no addons but it would do for now. The only remaining task was to get my nVidia card to work.

My Ubuntu running GNOME 3

After searching around for a while I found a project called Bumblebee which aims to provide an Optimus-like solution for users running Linux distros on laptops with i3 / i5 / i7 processors and nVidia graphics cards. The main aim of the project is to help with discrete nVidia graphics power management on Linux the way Optimus works on Windows.
You can find out more about the Bumblebee project here : http://bumblebee-project.org/
I followed the installation instructions provided for Ubuntu here - http://bumblebee-project.org/install.html and hurray ! My nVidia card now works on Ubuntu ! Plus my battery life while running Linux has improved tremendously. I am now getting over 4.5 hours on full charge (as opposed to the short 1.5 - 2 hours that I used to get before Bumblebee & GNOME 3).

Using my nVidia card to run a test
I am just hoping that I don't end up with a terminal screen and no GUI anytime soon !

Tuesday, May 28, 2013

Google Summer of Code (GSoC) 2013 !

Received a letter of acceptance for GSoC 2013 last night ! This is going to be one hell of a summer !

I'd like to thank my mentor Tiziana Refice and others at Measurement Lab, Dominic Hamon and Eric Gavaletz for their valuable input while I was understanding the project and preparing my proposal. Ofcourse a big thanks to my college seniors and my brother who encouraged me to take up a project and use my summer productively !

I will be working with Measurement Lab developing a Flash client for their Network Diagnostic Tool (NDT). You can find out more about the organization here : Measurement Lab. The design document for the project is available here : NDT Client Design Doc.

I will be posting project updates and useful findings here.
Can't wait to get started !