SLOG: Reflections on the Term’s Work and A2

This entry is in response to two previous entries (the SLOGS  on Linked Lists and Recursion), and has been composed with those reflections from earlier in the course in mind. For a full list of entries, see below:

  1. Intro to ADT
  2. Abstraction and Object Oriented Programming
  3. Programming is Poetry for Computers
  4. Linked Lists & Numbers: Developing Abstraction
  5. Recursive Rhythms in Biology and Computing
  6. The Unbearable Simplicity of BSTs
  7. Searching for Clarity: On Search Algorithms and Communication in Computing

Looking back at my feelings towards recursion and abstract data structures earlier in this course, I have to say that I had approached this course with more bravado (borne of a confident term in CSC108) than would have been wise.

Although I understood the fundamentals of both linked lists and recursion individually, and had performed well in lab exercises, integrating the two concepts to implement depth-first search in assignment two and recursive functions in the second term test were harder for me than I’d expected. The trickiest parts for me were figuring out when to create PuzzleNodes out of Puzzles, when to start building the PuzzleNode tree, when to assign children, and how to return to a branch point to search through siblings after exhausting the search down one chain of children.

Ultimately, it was working with my group in the second assignment that really helped me overcome this hump in my coursework.  My group member’s walk-through of the algorithm helped me configure my mind around the placement of the if statements, and, most importantly, to realize how to set up my base cases to effectively utilize recursion.

I realized that the goal of the depth first solver was to build a chain of PuzzleNodes doubly linked via parent and child, not to create a PuzzleNode tree – once I realized this, it was straightforward to understand the implementation: the function uses Python’s call stack as the stack, essentially performing implicit iteration; the base cases (where the if statements came into play) returned either None or a PuzzleNode; based upon the output of the function according to its base cases, recursion would either “turn back” at a fruitless leaf node (in the None case) and return to a prior branching point (i.e., the siblings would be the next items on the call stack), or add the resulting PuzzleNode to a chain. Then, it was a simple matter of following the parent attribute of the recursively generated PuzzleNodes to “walk” back up along the chain of PuzzleNodes, linking each PuzzleNode to its parent via the parent’s children attribute. It was pretty fascinating how this simple combination of a few abstract processes (tree traversal, linked list traversal, recursion) and data structures (trees, linked lists) could automate a cognitively challenging task (puzzle-solving) and complete it in a matter of seconds.

Looking back at my writing from SLOG posts #4, #5, and #7 (above),  I think my conception of abstraction and recursion were much simpler than I’d realized. Moreover, alternate perspectives were incredibly helpful in figuring problems out. Now that I’ve had to apply them to a more complicated scenario, implementing the abstract ideas I had in my head were quite challenging. The transition between the processes I could visualize mentally (“walking” along linked nodes, traversing a tree with a stack, recursively generating output) and actual implementation into computer code sometimes required another set of eyes, another person’s perspective.

SLOG: Searching for Clarity: On Search Algorithms and Communication in Computing

Perhaps one of the most beneficial aspects of group projects in programming is learning to appreciate how different minds conceive of the same concepts, and how those same minds express linguistic manifestations of those concepts in totally different ways. Sometimes, this can be incredibly frustrating: trying to explain how an algorithm functions to another student without being able to show them code can often end up confusing the other person even more.

The cognition required for understanding algorithms is so much like the skill required for throwing a spear with accuracy; it can only be learned through experience. And once the you’ve obtained the necessary experience to master, future instances requiring that same skill seem trivial in comparison to your first attempt. Thinking like a computer scientist is indeed procedural in nature.

I’ve come to really appreciate the effort this course’s instructors have put into composing lab exercises, assignments, lecture slides, and tests that will imbue us with the procedural skill necessary to master programming in Python. However, the same communication roadblock that makes this task difficult can make the course incredibly stressful and frustrating for the wrong reasons. Sometimes, I feel as though the hardest part is “speaking the same language” (expressing concepts in the same terms) as instructors, not necessarily demonstrating my ability to understand, manipulate, and apply programming algorithms.

Nevertheless, on a brighter topic, I am also astounded by how often disparate minds from different backgrounds can converge on the same ideas: namely, how the hundreds of students in CSC148 can all come up with varying algorithms to accomplish the problems posed to us in our assignments. Having spoken to a number of different students on their conceptions of Breadth-First Search and Depth-First Search, everyone could present very similar pseudocode or descriptions of how the searches functioned.

Of course, the hardest part was implementing the code in an efficient manner. What to do to make the algorithm skip visited nodes? What happens if you reach a leaf node in a depth-first-search? How can you schedule children for visits after siblings in a breadth-first-search? How do you avoid an infinite loop in a depth-first search? What’s the difference between recursion and using a stack structure iteratively in depth-first search?

All these questions were best elucidated with a combination of speaking to peers and trying to fumble through the code on my own. It’s incredible how much socialization could scaffold and accelerate learning. And on this final note — I feel it is so important that opportunities for peer-to-peer discussion become central to education, alongside hands-on application of theory. While CSC148 does a great job of providing the hands-on experience through its assignments, I am disappointed by this course (along with many other post-secondary courses) at the lack of facilitated engagement between students. Moreover, the intense focus on a reductive grade and non-contextual, time-limited tests as representative of one’s skill further hinder the learning process. In conjunction with inter-student competition and lack of clear communication, the structure of the tests and grading ends up reflecting performance errors (such as anxiety, miscommunication, etc.), not a student’s programming competence.

SLOG: The Unbearable Simplicity of BSTs

With each additional abstract data structure, I’m further astounded by the human ingenuity behind programming. There seems to be an abstract structure or algorithm to solve nearly any problem!

The most recent one, Binary Search Trees, has really fascinated me with the neatly organized distribution of its data. Comparing my programming notes for BSTs versus the lengthy process to crawl and construct normal trees yields a stark contrast; thanks to the near configuration of BSTs, any piece of data is simple to locate and the tree itself is straightforward to construct.

It still astonishes me that really any child, grandchild, or great-grandchild on the left of the node must be smaller than the current node. Logically, this makes perfect sense but my mere monkey mind still finds itself surprised at the simplicity and pragmatism of this concept.

Research into graph theory and tree traversals yields even more fascinating terrain – how else can this structure be engineered to model problems?

SLOG: Recursive Rhythms in Computing and Biology

It seems ceaselessly salient to find parallels between programming constructs, biology, and cognition. Where recursion and algorithms allow programmers (Algorithm alchemists? Mathemagicians?) to weave much more complex patterns and lattices than the basic binary encoding suggests, biology builds self-exapting brains capable of composing recursive language from simple self-organizing algorithms.

Let me begin with the field I am more familiar with: biology, it turns out, is built upon fractals and surprisingly intricate maths. Where each cell may follow simple guidelines (divide until death; follow DNA), multitudes of cell complexify and integrate to form an organism. Recursively: each cell depends upon the organism, yet the organism is shaped by its cells, which depend upon the organism, which is shaped by the cells… etc. ad inifinitum. Higher levels of complexity yield the human brain, which yields language, among other adaptive, neuroplastic functions.

Computational algorithms seem more like man making machine in nature’s image. (A poor parallel, in my view, but improving rapidly with each year.) Built upon the simple math of binary, ones and zeroes coagulate to form assembly-line language, each new layer of man-moulded complexity building upon the last, until the interfaces that the majority of the population interacts with bears no resemblance to the world’s first computing machines.

In so many ways, recursive computing algorithms reflect the recursion that abounds in nature – programming is like DNA for computers. Like tiers of overtones layered over the fundamental frequency in a musical note, the simplest tier of recursion yields a simple result, but compounded together the various tiers produce something much more complex and dynamic. Like the fractal folding of a space-filling fractal tile, the simple fold recurses to form something much more interesting.

SLOG: Linked Lists and Numbers: Developing Abstraction

Mind = blown. Linked lists are fascinating! In delving into linked lists this past week, it struck me how easily they make organizing data.

Prof. Amir’s demonstration in class really helped knot the concept together: that rather than having one extremely large, unwieldy data structure, linked lists allowed using the abstract object attribute’s of several pieces of discrete data in order to form an abstract data structure.

Branching off an earlier entry on the topic of abstract data structures, this knowledge deepens my appreciation for the versatility and utility of abstraction. Rather than having a true, concrete list in memory, the whole concept of a “list” is simply abstracted in the programmer’s imagination!

The idea reminds me of a landmark analogy oft repeated in developmental psychology: that of a child learning mathematics. While at first, the child relies on concrete objects to substitute for the concept of numbers, once they move beyond simple operations (addition, subtraction, multiplication), they will reach a level of abstraction where they no longer need concrete objects. Instead, the whole idea of numbers has now become abstract for them, and they need only contain these numbers in their minds.

Linked lists are very much like this – the lists do not exist before you, on a screen or even in computer memory; they are only a list when you think about the _next attribute within each node.

SLOG: Programming is Poetry for Computers

Although I was unable to complete Term Test 1 (unfortunately due to the fire alarm incident), the layout of the test and course material from the past couple weeks has really helped solidify concepts of computational abstraction for me.

Having a background in front-end development, I’ve never had to abstract concepts in order to transform them into code – there was always a one-to-one relationship between human perception and the programmable interface. Programming in an object-oriented language to build computational models of solve real-life problems/situations required an entirely different level of cognitive acrobatics.

I have to say the process resembles poetry.

Where programs are external, computer-legible analogues of human situations, poems are external, human-legible analogues of human emotions. Poetry comprises of metaphors, imagery, and meaningful linguistic constructs which a poet may use to represent and communicate their inner feelings, insights, and reflections. Once composed, the output can be fed back into another human via sight and linguistic processing to withdraw a very close analogue of the meaning put in by the poet.

Programs comprise of metaphors, objects, and meaningful programming constructs (syntax) which a programmer may use to represent and communicate a situation or concept to a computer. Once composed, the output can be fed into a compiler and then executed in a computer, a process during which the computer returns results that reflect the situation modelled.

Both are communicative interfaces in their own right, but poems are meant for human-human interaction rather than human-computer interaction.

SLOG: Abstraction and Object Oriented Programming

This week, we were introduced to designing and implementing abstract data classes of containers that operated upon the traditionally accounting/inventory-related concepts of First-In-Last-Out and First-In-First-Out. Specifically, stacks, sacks, and queues!

I’m finding that the hardest thing about computer science is wrapping one’s mind around concepts in the right shape. Much as a baseball can be thrown in a number of different ways, some of which are more useful or less useful for a particular pitcher to hit a target with the ball, programming involves such a a range of abstraction that there are many ways to pitch a programming concept in order to understand, implement, and apply it.

For example, upon first encountering the idea of stacks, the concept is intuitively understandable: it is a sequential collection of items where the addition/access/removal of items occurs in a designed, algorithmic way. But how does one create a stack in Python code with functions and class definitions? In what ways can a stack be useful when solving programming problems (or modelling real life)? How are the class definitions then used to solve a more complex problem? The transformation from an abstract, intuitive concept to a concrete, useful program requires an immeasurable amount of mental legwork.

The legwork is immeasurable because of how abstract it is. With the little we know about human cognition, all we can say about what occurs in the moments before and after understanding is that some “connections” are made between concepts as we somehow realize to find certain aspects relevant – or, something “lit up” like a lightbulb. Yet even these are still abstract representations. In much the same way that we cannot describe how we know how to pitch a ball with any level of replicable accuracy (i.e. as far as our descriptions can be used to program a robot to throw a ball), we cannot describe the cognitive process of understanding.

There are many ways to understand a programming problem or concept. But only one way that works for a particular individual at a particular instance in pursuing a particular goal in a particular context. The challenge, then, I suppose, is finding the meta-method that works best for me in order to pick up these concepts, with the meta-goal of successfully entering the CS minor POSt.

SLOG: Intro to ADT

Series 3: CSC148 / SLOG #1

Hello, world!

This is my first message to the great wide beyond on a topic that, up until about four months ago, was utterly foreign to me: Object-Oriented Programming!

So far, the course material is very interesting. The concept of modelling concepts within a computational framework by pinning attributes and methods to an object under an abstract class seems revolutionary. Memories of the frame stack and object heap from CSC 108 come to mind, as classes were introduced shortly before the end of the course.

Having mostly dealt with front-end web development, the core concept of OOP – manipulating abstract objects in computer memory, rather than relying on a DOM or constantly calling up new variables – open ups so many new possibilities I’d never really thought about before. What could I model? Rather, what couldn’t I model?

Simply exposure to the pre-written APIs for Assignment 1 has already set sparks flying in my mind – is this how Uber works? – and I feel as though the mechanisms underlying software operation and development are slyly opening before me like a timid oyster.

Curiously, I should note, these concepts remind me of semantic networks invoked in computational approaches to human cognition. Just as OOP is based in abstract objects tied to attributes and methods (let’s say, “nouns”, “adjectives”, and “actions” for a linguistic analog), human categorization is modelled by these networks of abstract concepts:

A Semantic Network (WikiMedia)

Likewise, taking the linguistic analog as the exemplar, a similar parallel can be found in sentence diagrams:

Sentence Diagram (WikiMedia)

I don’t yet know how much referring to these other examples of conceptual maps will help with program design, if at all, but I hope I will find out by the end of this term!

 

Kindness Kills

Artwork from: http://www.deviantart.com/art/Hazy-Winter-Sun-163454825

“Hazy Winter Sun” by Flingling. Watercolour on coldpressed paper. Source: http://www.deviantart.com/art/Hazy-Winter-Sun-163454825

Kindness kills with the calm of winter.
It freezes my fist in its fetal form,
it steals the heat from my words, vapour ghosts gone mid-air,
it gathers my thoughts under its gracious light
and reveals the skeletal bark I have donned
in the mirror-pools of your frozen lake-face.

Kindness brings more pain than steel swords ever could,
because it cuts deeper than steel ever could,
past cloth, skin, character-mould
into the soft flesh of ego,
because it lances open questions of “Who could ever deserve kindness?”

Kindness hurts the way pity does,
when a tender touch or gentle word
speaks only of stinging generosity.
Kindness bridges the chasm we left between us
and its soft warmth only reminds me of the coldness I was prepared for.

Your kindness leaves me bereft of myself.

Kindness is passion distilled in the afterglow of sunset
when all light has faded except that which we hold in our souls.
And yet kindness feels like all passion diluted
in a single timid cup afraid to spill over.

I do not know how to deal with kindness.
It is too much, or too little
and never enough.

It leaves me with a longing for the winter sun
and wary of its light.

Your kindness makes me unkind.
I wish I could destroy it, discard it,
spit the bitter pomegranate seed at you, devoid of sweet juice–
Or return it to you with the grace of my own kindness
but your kindness wakens my fears.
And fear makes me less hopeful, more hateful.

Your kindness kills.
It kills me in imagined conversations and illusory fates
It kills me though my pettiness, your guilt, our falsehood,
It kills me that you only ever show kindness instead of the love I was always looking for.

The Pen and the Sword

This dull blade on gentle skin:
is this what love feels like?
To smooth the downy hairs, open the tender flesh, and let sweet juice run down the blade.

It would be release:
the pressure
gone
in the instant the the pain drains from the wound,
but it would be release:
all my thoughts would vanish
my strategy
my skill
any poem i could ever write.

We do not write poems about happiness;
          at least not memorable ones.

But there is pressure within me
and this dull blade would be easy, so easy
to rend the flesh / soothe the spirit
bring this moment into sudden clarity
and destroy all your ghosts

at least, that is the hope.

Instead, I sit here and stare at this page
wondering where or who you are
and what you might be thinking
and these symbols spill as I tap out my woes and the ghosts,
They feel welcome to stay.